/****************************************************************************** ** ** FILE NAME : danube_ppa_stack_al.c ** PROJECT : Twinpass-E ** MODULES : PPA (Routing Acceleration) ** ** DATE : 12 SEP 2006 ** AUTHOR : Xu Liang ** DESCRIPTION : PPA (Routing Acceleration) Protocol Stack (Linux) Adaptor ** COPYRIGHT : Copyright (c) 2006 ** Infineon Technologies AG ** Am Campeon 1-12, 85579 Neubiberg, Germany ** ** Any use of this software is subject to the conclusion of a respective ** License agreement. Without such a License agreement no rights to the ** software are granted ** ** HISTORY ** $Date $Author $Comment ** 12 SEP 2006 Xu Liang Initiate Version ** 26 OCT 2006 Xu Liang Add GPL header. *******************************************************************************/ /* * #################################### * Version No. * #################################### */ #define VER_FAMILY 0xC0 // bit 0: res // 1: Danube // 2: Twinpass // 3: Amazon-SE // 4: res // 5: AR9 // 6: GR9 #define VER_DRTYPE 0x10 // bit 0: Normal Data Path driver // 1: Indirect-Fast Path driver // 2: HAL driver // 3: Hook driver // 4: Stack/System Adaption Layer driver // 5: PPA API driver #define VER_INTERFACE 0x00 // bit 0: MII 0 // 1: MII 1 // 2: ATM WAN // 3: PTM WAN #define VER_ACCMODE 0x00 // bit 0: Routing // 1: Bridging #define VER_MAJOR 0 #define VER_MINOR 1 /* * #################################### * Head File * #################################### */ /* * Common Head File */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Chip Specific Head File */ #include /* * #################################### * Definition * #################################### */ #define ENABLE_MY_MEMCPY 0 /* * #################################### * Data Type * #################################### */ /* * #################################### * Declaration * #################################### */ /* * #################################### * Global Variable * #################################### */ static uint32_t g_local_irq_save_flag = 0; static uint32_t g_local_irq_save_flag_lock = 0; /* * #################################### * Global Variable * #################################### */ /* * #################################### * Extern Variable * #################################### */ /* * #################################### * Local Function * #################################### */ /* * #################################### * Global Function * #################################### */ PPA_SESSION *ppa_get_session(PPA_BUF *ppa_buf) { enum ip_conntrack_info ctinfo; return ip_conntrack_get(ppa_buf, &ctinfo); } uint8_t ppa_get_pkt_ip_proto(PPA_BUF *ppa_buf) { #if 1 return (uint8_t)ppa_buf->nh.iph->protocol; #else return ppa_buf->nh.iph ? (uint8_t)ppa_buf->nh.iph->protocol : IPPROTO_MAX; #endif } unsigned long ppa_get_tcp_connect_status(PPA_BUF *ppa_buf) { return ppa_get_session(ppa_buf)->status; } uint32_t ppa_get_pkt_src_ip(PPA_BUF *ppa_buf) { return ppa_buf->nh.iph->saddr; } uint32_t ppa_get_pkt_dst_ip(PPA_BUF *ppa_buf) { return ppa_buf->nh.iph->daddr; } void *ppa_get_pkt_transport_hdr(PPA_BUF *ppa_buf) { return (void *)((uint32_t *)ppa_buf->nh.iph + ppa_buf->nh.iph->ihl); } uint16_t ppa_get_pkt_src_port(PPA_BUF *ppa_buf) { return (uint16_t)(((struct udphdr *)ppa_get_pkt_transport_hdr(ppa_buf))->source); } uint16_t ppa_get_pkt_dst_port(PPA_BUF *ppa_buf) { return (uint16_t)(((struct udphdr *)ppa_get_pkt_transport_hdr(ppa_buf))->dest); } void ppa_get_pkt_rx_src_mac_addr(PPA_BUF *ppa_buf, uint8_t mac[PPA_ETH_ALEN]) { ppa_memcpy(mac, ppa_buf->mac.raw + PPA_ETH_ALEN, PPA_ETH_ALEN); } void ppa_get_pkt_rx_dst_mac_addr(PPA_BUF *ppa_buf, uint8_t mac[PPA_ETH_ALEN]) { ppa_memcpy(mac, ppa_buf->mac.raw, PPA_ETH_ALEN); } PPA_NETIF *ppa_get_pkt_src_if(PPA_BUF *ppa_buf) { return ppa_buf->dev; } PPA_NETIF *ppa_get_pkt_dst_if(PPA_BUF *ppa_buf) { return ppa_buf->dst->dev; } #if !defined(CONFIG_PPPOE) && !defined(CONFIG_PPPOE_MODULE) __u16 ppa_get_pkt_pppoe_session_id(PPA_BUF *ppa_buf) { return 0; } #endif int32_t ppa_pppoe_get_physical_if(PPA_IFNAME *ifname, PPA_IFNAME phy_ifname[PPA_IF_NAME_SIZE]) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) PPA_NETIF *netif; netif = ppa_get_netif(ifname); if ( !netif ) return -1; if ( !ppa_check_is_pppoe_netif(netif) ) return -1; return ppa_pppoe_get_eth_netif(netif, phy_ifname); #else return -1; #endif } uint32_t ppa_check_is_ppp_netif(PPA_NETIF *netif) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) return (netif->flags & IFF_POINTOPOINT) ? 1 : 0; #else return 0; #endif } uint32_t ppa_check_is_pppoe_netif(PPA_NETIF *netif) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) struct pppoe_addr pa; if ( !(netif->flags & IFF_POINTOPOINT) ) return 0; return pppoe_get_pppoe_addr(netif, &pa) ? 0 : 1; #else return 0; #endif } int32_t ppa_pppoe_get_dst_mac(PPA_NETIF *netif, uint8_t mac[PPA_ETH_ALEN]) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) struct pppoe_addr pa; if ( pppoe_get_pppoe_addr(netif, &pa) ) { printk("fail in getting pppoe addr\n"); return -1; } ppa_memcpy(mac, pa.remote, sizeof(pa.remote)); return 0; #else return -1; #endif } int32_t ppa_get_dst_mac(PPA_BUF *ppa_buf, PPA_SESSION *p_session, uint8_t mac[PPA_ETH_ALEN]) { int32_t ret; struct hh_cache *hh; /* * Assumption, function only gets called from POSTROUTING so skb->dev = o/p i/f */ /* First need to check if PPP output interface */ if ( ppa_check_is_ppp_netif(ppa_buf->dev) ) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) /* Check if PPPoE interface */ if ( !ppa_check_is_pppoe_netif(ppa_buf->dev) ) { printk("not pppoe netif: %s\n", ppa_buf->dev->name); return RET_E_NOT_POSSIBLE; } /* Determine PPPoE MAC address */ return ppa_pppoe_get_dst_mac(ppa_buf->dev, mac); #else //printk("failed in getting PPPoE mac\n"); return RET_E_NOT_POSSIBLE; #endif } if ( !ppa_buf->dst ) { //printk("dest entry is not ready: ppa_buf->dst == NULL\n"); return RET_E_NOT_AVAIL; // Dst MAC address not known } hh = ppa_buf->dst->hh; if ( !hh ) { if ( ppa_buf->dst->neighbour && (ppa_buf->dst->neighbour->ha[0] != 0 || ppa_buf->dst->neighbour->ha[1] != 0 || ppa_buf->dst->neighbour->ha[2] != 0 || ppa_buf->dst->neighbour->ha[3] != 0 || ppa_buf->dst->neighbour->ha[4] != 0 || ppa_buf->dst->neighbour->ha[5] != 0) ) { ppa_memcpy(mac, (uint8_t *)ppa_buf->dst->neighbour->ha, PPA_ETH_ALEN); return RET_E_OK; } //else //{ // if ( !ppa_buf->dst->neighbour ) // printk("hh and neighbour are not ready\n"); // else // printk("neighbour mac is zero: %d:%d:%d:%d:%d:%d\n", ppa_buf->dst->neighbour->ha[0], ppa_buf->dst->neighbour->ha[1], ppa_buf->dst->neighbour->ha[2], ppa_buf->dst->neighbour->ha[3], ppa_buf->dst->neighbour->ha[4], ppa_buf->dst->neighbour->ha[5]); // return RET_E_NOT_AVAIL; //} //printk("hh is not ready: ppa_buf->dst->hh == NULL\n"); return RET_E_NOT_AVAIL; } read_lock_bh(&hh->hh_lock); if ( hh->hh_len != ETH_HLEN ) { //printk("head length is not correct: hh->hh_len = %d, ETH_HLEN = %d\n", (int)hh->hh_len, ETH_HLEN); ret = RET_E_NOT_POSSIBLE; } else { ppa_memcpy(mac, (uint8_t *)hh->hh_data + HH_DATA_ALIGN(hh->hh_len) - hh->hh_len, PPA_ETH_ALEN); ret = RET_E_OK; } read_unlock_bh(&hh->hh_lock); return ret; } PPA_NETIF *ppa_get_netif(PPA_IFNAME *ifname) { // This implementation has risk that the device is destroyed after we get and free it PPA_NETIF *netif; if ( (netif = dev_get_by_name(ifname)) ) { ppa_put_netif(netif); return netif; } else return NULL; } void ppa_put_netif(PPA_NETIF *netif) { dev_put(netif); } void ppa_get_netif_hwaddr(PPA_NETIF *netif, uint8_t mac[PPA_ETH_ALEN]) { #if 0 if ( netif->br_port == NULL ) { #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) if ( ppa_check_is_pppoe_netif(netif) ) { // PPPoE char name[PPA_IF_NAME_SIZE]; PPA_NETIF *phys_netif; if ( ppa_pppoe_get_eth_netif(netif, name) || !(phys_netif = ppa_get_netif(name)) ) ppa_memset(mac, 0, PPA_ETH_ALEN); else } } else // VLAN and normal interface ppa_memcpy(mac, netif->dev_addr, PPA_ETH_ALEN); #else ppa_memcpy(mac, netif->dev_addr, PPA_ETH_ALEN); #endif } else // bridge ppa_memcpy(mac, netif->br_port->br->dev.dev_addr, PPA_ETH_ALEN); #else #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) if ( ppa_check_is_pppoe_netif(netif) ) { char name[PPA_IF_NAME_SIZE]; if ( ppa_pppoe_get_eth_netif(netif, name) || !(netif = ppa_get_netif(name)) ) { ppa_memset(mac, 0, PPA_ETH_ALEN); return; } } #endif if ( netif->br_port == NULL ) ppa_memcpy(mac, netif->dev_addr, PPA_ETH_ALEN); else ppa_memcpy(mac, netif->br_port->br->dev->dev_addr, PPA_ETH_ALEN); #endif // printk("+++ ppa_get_netif_hwaddr(%s): (br_port == %08X ) %02X:%02X:%02X:%02X:%02X:%02X\n", netif->name, (uint32_t)netif->br_port, (uint32_t)mac[0], (uint32_t)mac[1], (uint32_t)mac[2], (uint32_t)mac[3], (uint32_t)mac[4], (uint32_t)mac[5]); } PPA_IFNAME *ppa_get_netif_name(PPA_NETIF *netif) { return netif ? netif->name : NULL; } uint32_t ppa_is_netif_equal(PPA_NETIF *netif1, PPA_NETIF *netif2) { return netif1 && netif2 && netif1->ifindex == netif2->ifindex ? 1 : 0; } uint32_t ppa_is_netif_name(PPA_NETIF *netif, PPA_IFNAME *ifname) { return netif && ifname && strcmp(netif->name, ifname) == 0 ? 1 : 0; } uint32_t ppa_is_netif_name_prefix(PPA_NETIF *netif, PPA_IFNAME *ifname_prefix, int n) { return netif && strncmp(netif->name, ifname_prefix, n) == 0 ? 1 : 0; } int32_t ppa_get_physical_if(PPA_NETIF *netif, PPA_IFNAME *ifname, PPA_IFNAME phy_ifname[PPA_IF_NAME_SIZE]) { if ( !netif ) netif = ppa_get_netif(ifname); if ( !netif ) return -1; #if defined(CONFIG_PPPOE) || defined(CONFIG_PPPOE_MODULE) if ( ppa_check_is_pppoe_netif(netif) ) { uint32_t ret; ret = ppa_pppoe_get_eth_netif(netif, phy_ifname); if ( ret == 0 ) { #if 0 netif = ppa_get_netif(phy_ifname); if ( (netif->priv_flags & IFF_802_1Q_VLAN) ) strcpy(phy_ifname, VLAN_DEV_INFO(netif)->real_dev->name); #else ret = ppa_get_physical_if(NULL, phy_ifname, phy_ifname); #endif } return ret; } #endif if ( (netif->priv_flags & IFF_802_1Q_VLAN) ) { #if 0 strcpy(phy_ifname, VLAN_DEV_INFO(netif)->real_dev->name); return 0; #else uint32_t ret; ret = ppa_get_physical_if(NULL, VLAN_DEV_INFO(netif)->real_dev->name, phy_ifname); return ret; #endif } strcpy(phy_ifname, netif->name); return 0; } int32_t ppa_if_is_vlan_if(PPA_NETIF *netif, PPA_IFNAME *ifname) { // TODO: need testing #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) if ( !netif ) netif = ppa_get_netif(ifname); if ( !netif ) return 0; // can not get interface if ( (netif->priv_flags & IFF_802_1Q_VLAN) ) return 1; #endif return 0; } int32_t ppa_vlan_get_physical_if(PPA_IFNAME *ifname, PPA_IFNAME phy_ifname[PPA_IF_NAME_SIZE]) { // TODO: need testing PPA_NETIF *netif; netif = ppa_get_netif(ifname); if ( !netif ) return -1; if ( !(netif->priv_flags & IFF_802_1Q_VLAN) ) return -1; strcpy(phy_ifname, VLAN_DEV_INFO(netif)->real_dev->name); return 0; } #if defined(CONFIG_VLAN_8021Q) // || defined(CONFIG_VLAN_8021Q_MODULE) extern int vlan_dev_get_vid(const char *dev_name, unsigned short* result); #endif uint32_t ppa_get_vlan_id(PPA_NETIF *netif) { #if defined(CONFIG_VLAN_8021Q) // || defined(CONFIG_VLAN_8021Q_MODULE) unsigned short vid; if ( !netif ) return 0; if ( vlan_dev_get_vid(netif->name, &vid) == 0 ) return (uint32_t)vid; #endif return 0; } int32_t ppa_is_netif_bridged(PPA_IFNAME *ifname, PPA_NETIF *netif) { if ( !netif ) netif = ppa_get_netif(ifname); if ( !netif ) return 0; // can not get if ( netif->br_port != NULL ) return 1; else return 0; } int32_t ppa_get_bridge_member_ifs(PPA_IFNAME *ifname, int *num_ifs, PPA_IFNAME **pp_member_ifs) { // TODO: wait for implementation return -1; } int32_t ppa_if_is_br_if(PPA_NETIF *netif, PPA_IFNAME *ifname) { if ( !netif ) { if ( !ifname && !(netif = ppa_get_netif(ifname)) ) return 0; } if ( netif->hard_start_xmit == br_dev_xmit ) return 1; return 0; } int32_t ppa_get_br_dst_port(PPA_NETIF *netif, PPA_BUF *ppa_buf, PPA_NETIF **p_netif) { struct net_bridge *br; //unsigned char *dest; unsigned char dest[PPA_ETH_ALEN]; struct net_bridge_fdb_entry *dst; br = netif->priv; //dest = ppa_buf->data; ppa_get_dst_mac(ppa_buf, NULL, dest); if ( (dest[0] & 1) ) return 1; if ( (dst = br_fdb_get(br, dest)) != NULL ) { *p_netif = dst->dst->dev; br_fdb_put(dst); return 0; } return -1; } #if defined(CONFIG_ATM_BR2684) && (defined(CONFIG_IFX_PPA_A5) || defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) struct br2684_dev { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) struct net_device *net_dev; #else struct net_device net_dev; #endif struct list_head br2684_devs; int number; struct list_head brvccs; /* one device <=> one vcc (before xmas) */ struct net_device_stats stats; int mac_was_set; }; enum br2684_encaps { e_vc = 0, e_llc = 1, }; enum br2684_payload { p_routed = 0, p_bridged = 1, }; struct br2684_vcc { struct atm_vcc *atmvcc; struct br2684_dev *brdev; /* keep old push,pop functions for chaining */ void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ enum br2684_encaps encaps; enum br2684_payload payload; /*Add by Henry*/ struct list_head brvccs; /* remove un-used data */ }; extern int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev); #endif int32_t ppa_br2684_get_vcc(PPA_NETIF *netif, PPA_VCC **pvcc) { #if defined(CONFIG_ATM_BR2684) && (defined(CONFIG_IFX_PPA_A5) || defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) if ( netif && (uint32_t)br2684_start_xmit == (uint32_t)netif->hard_start_xmit ) { struct br2684_dev *brdev; struct br2684_vcc *brvcc; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) brdev = (struct br2684_dev *)netif->priv; #else brdev = (struct br2684_dev *)((char *)(netif) - (unsigned long)(&((struct br2684_dev *)0)->net_dev)); #endif brvcc = list_empty(&brdev->brvccs) ? NULL : list_entry(brdev->brvccs.next, struct br2684_vcc, brvccs); if ( brvcc ) { *pvcc = brvcc->atmvcc; return 0; } } #endif return -1; } int32_t ppa_if_is_br2684(PPA_NETIF *netif, PPA_IFNAME *ifname) { #if defined(CONFIG_ATM_BR2684) && (defined(CONFIG_IFX_PPA_A5) || defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) if ( !netif ) netif = ppa_get_netif(ifname); if ( !netif ) return 0; // can not get return (uint32_t)br2684_start_xmit == (uint32_t)netif->hard_start_xmit ? 1 : 0; #else return 0; #endif } int32_t ppa_if_is_ipoa(PPA_NETIF *netif, PPA_IFNAME *ifname) { #if defined(CONFIG_ATM_BR2684) && (defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) if ( ppa_if_is_br2684(netif, ifname) ) { struct br2684_dev *brdev; struct br2684_vcc *brvcc; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) brdev = (struct br2684_dev *)netif->priv; #else brdev = (struct br2684_dev *)((char *)(netif) - (unsigned long)(&((struct br2684_dev *)0)->net_dev)); #endif brvcc = list_empty(&brdev->brvccs) ? NULL : list_entry(brdev->brvccs.next, struct br2684_vcc, brvccs); return brvcc && brvcc->payload == p_routed ? 1 : 0; } #endif return 0; } #if (!defined(CONFIG_PPPOATM) && !defined(CONFIG_PPPOATM_MODULE)) && (defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) int32_t ppa_pppoa_get_vcc(PPA_NETIF *netif, PPA_VCC **patmvcc) { return -1; } int32_t ppa_if_is_pppoa(PPA_NETIF *netif, PPA_IFNAME *ifname) { return 0; } #endif uint32_t ppa_is_session_equal(PPA_SESSION *session1, PPA_SESSION *session2) { return session1 == session2 ? 1 : 0; } uint32_t ppa_get_session_helper(PPA_SESSION *p_session) { return (uint32_t)(p_session->helper); } #if defined(CONFIG_IP_NF_NAT_NEEDED) uint32_t ppa_get_nat_helper(PPA_SESSION *p_session) { return p_session ? (uint32_t)(p_session->nat.info.helper) : 0; } #endif uint32_t ppa_check_is_special_session(PPA_BUF *ppa_buf, PPA_SESSION *p_session) { enum ip_conntrack_info ct_info; if ( !p_session ) p_session = ip_conntrack_get(ppa_buf, &ct_info); if ( ppa_get_session_helper(p_session) ) return 1; #if defined(CONFIG_IP_NF_NAT_NEEDED) if ( ppa_get_nat_helper(p_session) ) return 1; #endif /* XXX: Any other criteria for special sessions ? Add here */ return 0; } int32_t ppa_is_pkt_fragment(PPA_BUF *ppa_buf) { return (ppa_buf->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) == 0 ? 0 : 1; } int32_t ppa_is_pkt_host_output(PPA_BUF *ppa_buf) { return ppa_buf->dev == NULL || ppa_buf->pkt_type == PACKET_OUTGOING ? 1 : 0; } int32_t ppa_is_pkt_broadcast(PPA_BUF *ppa_buf) { return ppa_buf->pkt_type == PACKET_BROADCAST ? 1 : 0; } int32_t ppa_is_pkt_multicast(PPA_BUF *ppa_buf) { return ppa_buf->pkt_type == PACKET_MULTICAST ? 1 : 0; } int32_t ppa_is_pkt_loopback(PPA_BUF *ppa_buf) { return ppa_buf->pkt_type == PACKET_LOOPBACK ? 1 : 0; } int32_t ppa_is_pkt_local(PPA_BUF *ppa_buf) { /* XXX: Check this. What about ip_mc_forward */ /* return ((uint32_t)ppa_buf->dst->input != (uint32_t)ip_forward); */ return ppa_buf->dst != NULL && (uint32_t)(ppa_buf->dst->input) == (uint32_t)ip_local_deliver ? 1 : 0; } int32_t ppa_is_pkt_routing(PPA_BUF *ppa_buf) { return ppa_buf->dst != NULL && (uint32_t)(ppa_buf->dst->input) == (uint32_t)ip_forward ? 1 : 0; } int32_t ppa_is_pkt_mc_routing(PPA_BUF *ppa_buf) { return ppa_buf->dst != NULL && (uint32_t)(ppa_buf->dst->output) == (uint32_t)ip_mc_output ? 1 : 0; } int32_t ppa_lock_init(PPA_LOCK *p_lock) { sema_init(p_lock, 1); return 0; } void ppa_lock_get(PPA_LOCK *p_lock) { if ( !in_interrupt() ) down(p_lock); } void ppa_lock_release(PPA_LOCK *p_lock) { if ( !in_interrupt() ) up(p_lock); } void ppa_lock_destroy(PPA_LOCK *p_lock) { } void ppa_disable_int(void) { uint32_t flag; local_irq_save(flag); if ( !g_local_irq_save_flag_lock ) { g_local_irq_save_flag = flag; g_local_irq_save_flag_lock = 1; } } void ppa_enable_int(void) { if ( g_local_irq_save_flag_lock ) { g_local_irq_save_flag_lock = 0; local_irq_restore(g_local_irq_save_flag); } } void *ppa_malloc(uint32_t size) { return kmalloc(size, GFP_KERNEL); } int32_t ppa_free(void *buf) { kfree(buf); return 0; } int32_t ppa_mem_cache_create(const char *name, uint32_t size, PPA_MEM_CACHE **pp_cache) { PPA_MEM_CACHE* p_cache; if ( !pp_cache ) return -1; p_cache = kmem_cache_create(name, size, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); if ( !p_cache ) return -1; *pp_cache = p_cache; return 0; } int32_t ppa_mem_cache_destroy(PPA_MEM_CACHE *p_cache) { if ( !p_cache ) return -1; kmem_cache_destroy(p_cache); return 0; } void *ppa_mem_cache_alloc(PPA_MEM_CACHE *p_cache) { return kmem_cache_alloc(p_cache, GFP_ATOMIC); } void ppa_mem_cache_free(void *buf, PPA_MEM_CACHE *p_cache) { kmem_cache_free(p_cache, buf); } void ppa_memcpy(void *dst, const void *src, uint32_t count) { #if defined(ENABLE_MY_MEMCPY) && ENABLE_MY_MEMCPY char *d = (char *)dst, *s = (char *)src; if (count >= 32) { int i = 8 - (((unsigned long) d) & 0x7); if (i != 8) while (i-- && count--) { *d++ = *s++; } if (((((unsigned long) d) & 0x7) == 0) && ((((unsigned long) s) & 0x7) == 0)) { while (count >= 32) { unsigned long long t1, t2, t3, t4; t1 = *(unsigned long long *) (s); t2 = *(unsigned long long *) (s + 8); t3 = *(unsigned long long *) (s + 16); t4 = *(unsigned long long *) (s + 24); *(unsigned long long *) (d) = t1; *(unsigned long long *) (d + 8) = t2; *(unsigned long long *) (d + 16) = t3; *(unsigned long long *) (d + 24) = t4; d += 32; s += 32; count -= 32; } while (count >= 8) { *(unsigned long long *) d = *(unsigned long long *) s; d += 8; s += 8; count -= 8; } } if (((((unsigned long) d) & 0x3) == 0) && ((((unsigned long) s) & 0x3) == 0)) { while (count >= 4) { *(unsigned long *) d = *(unsigned long *) s; d += 4; s += 4; count -= 4; } } if (((((unsigned long) d) & 0x1) == 0) && ((((unsigned long) s) & 0x1) == 0)) { while (count >= 2) { *(unsigned short *) d = *(unsigned short *) s; d += 2; s += 2; count -= 2; } } } while (count--) { *d++ = *s++; } // return d; #else memcpy(dst, src, count); #endif } void ppa_memset(void *dst, uint32_t pad, uint32_t n) { memset(dst, pad, n); } int32_t ppa_timer_init(PPA_TIMER *p_timer, void (*callback)(unsigned long)) { //ppa_memset(p_timer, 0, sizeof(*p_timer)); init_timer(p_timer); p_timer->function = callback; return 0; } int32_t ppa_timer_add(PPA_TIMER *p_timer, uint32_t timeout_in_sec) { p_timer->expires = jiffies + timeout_in_sec * HZ - 1; add_timer(p_timer); return 0; } void ppa_timer_del(PPA_TIMER *p_timer) { del_timer(p_timer); } uint32_t ppa_get_time_in_sec(void) { return (jiffies + HZ / 2) / HZ; } EXPORT_SYMBOL(ppa_get_session); EXPORT_SYMBOL(ppa_get_pkt_ip_proto); EXPORT_SYMBOL(ppa_get_pkt_src_ip); EXPORT_SYMBOL(ppa_get_pkt_dst_ip); EXPORT_SYMBOL(ppa_get_pkt_transport_hdr); EXPORT_SYMBOL(ppa_get_pkt_src_port); EXPORT_SYMBOL(ppa_get_pkt_dst_port); EXPORT_SYMBOL(ppa_get_pkt_rx_src_mac_addr); EXPORT_SYMBOL(ppa_get_pkt_rx_dst_mac_addr); EXPORT_SYMBOL(ppa_get_pkt_src_if); EXPORT_SYMBOL(ppa_get_pkt_dst_if); EXPORT_SYMBOL(ppa_check_is_ppp_netif); EXPORT_SYMBOL(ppa_check_is_pppoe_netif); EXPORT_SYMBOL(ppa_pppoe_get_dst_mac); EXPORT_SYMBOL(ppa_get_dst_mac); EXPORT_SYMBOL(ppa_get_netif); EXPORT_SYMBOL(ppa_put_netif); EXPORT_SYMBOL(ppa_get_netif_hwaddr); EXPORT_SYMBOL(ppa_get_netif_name); EXPORT_SYMBOL(ppa_is_netif_equal); EXPORT_SYMBOL(ppa_is_netif_name); EXPORT_SYMBOL(ppa_is_netif_name_prefix); EXPORT_SYMBOL(ppa_get_physical_if); EXPORT_SYMBOL(ppa_if_is_vlan_if); EXPORT_SYMBOL(ppa_vlan_get_physical_if); EXPORT_SYMBOL(ppa_get_vlan_id); EXPORT_SYMBOL(ppa_get_bridge_member_ifs); EXPORT_SYMBOL(ppa_if_is_br_if); EXPORT_SYMBOL(ppa_get_br_dst_port); EXPORT_SYMBOL(ppa_br2684_get_vcc); EXPORT_SYMBOL(ppa_if_is_br2684); EXPORT_SYMBOL(ppa_if_is_ipoa); #if (!defined(CONFIG_PPPOATM) && !defined(CONFIG_PPPOATM_MODULE)) && (defined(CONFIG_IFX_PPA_A4) || defined(CONFIG_DANUBE_PPA_A4)) EXPORT_SYMBOL(ppa_pppoa_get_vcc); EXPORT_SYMBOL(ppa_if_is_pppoa); #endif EXPORT_SYMBOL(ppa_is_session_equal); EXPORT_SYMBOL(ppa_get_session_helper); #if defined(CONFIG_IP_NF_NAT_NEEDED) EXPORT_SYMBOL(ppa_get_nat_helper); #endif EXPORT_SYMBOL(ppa_check_is_special_session); EXPORT_SYMBOL(ppa_is_pkt_fragment); EXPORT_SYMBOL(ppa_is_pkt_host_output); EXPORT_SYMBOL(ppa_is_pkt_broadcast); EXPORT_SYMBOL(ppa_is_pkt_multicast); EXPORT_SYMBOL(ppa_is_pkt_loopback); EXPORT_SYMBOL(ppa_is_pkt_local); EXPORT_SYMBOL(ppa_is_pkt_routing); EXPORT_SYMBOL(ppa_is_pkt_mc_routing); EXPORT_SYMBOL(ppa_lock_init); EXPORT_SYMBOL(ppa_lock_get); EXPORT_SYMBOL(ppa_lock_release); EXPORT_SYMBOL(ppa_lock_destroy); EXPORT_SYMBOL(ppa_disable_int); EXPORT_SYMBOL(ppa_enable_int); EXPORT_SYMBOL(ppa_malloc); EXPORT_SYMBOL(ppa_free); EXPORT_SYMBOL(ppa_mem_cache_create); EXPORT_SYMBOL(ppa_mem_cache_destroy); EXPORT_SYMBOL(ppa_mem_cache_alloc); EXPORT_SYMBOL(ppa_mem_cache_free); EXPORT_SYMBOL(ppa_memcpy); EXPORT_SYMBOL(ppa_memset); EXPORT_SYMBOL(ppa_timer_init); EXPORT_SYMBOL(ppa_timer_add); EXPORT_SYMBOL(ppa_timer_del); EXPORT_SYMBOL(ppa_get_time_in_sec);