#ifndef __IP6_FASTPATH_CORE_H__ #define __IP6_FASTPATH_CORE_H__ #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/in.h> #include <linux/in6.h> #include <linux/ipv6.h> #include <net/ipv6.h> #include <linux/udp.h> #include <linux/tcp.h> #include <linux/netdevice.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv6.h> #include <net/dst.h> #include <linux/init.h> #include <net/route.h> #include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_zones.h> #include <linux/if_arp.h> #include "../ipv4/fastpath_core.h" #if 1 #define USE_SKB_DEV 1 #else #undef USE_SKB_DEV #endif /* ---------------------------------------------------------------------------------------------------- */ #define IP6_NAPT_TABLE_LIST_MAX 2048 #define IP6_NAPT_TABLE_ENTRY_MAX 2048 #define IP6_PATH_TABLE_LIST_MAX 2048 #define IP6_PATH_TABLE_ENTRY_MAX (IP6_NAPT_TABLE_ENTRY_MAX*2) #define INET6_ADDRSTRLEN 46 //#define IP6_FP_DBG 1 #define IP6_FP_DBG 0 #if IP6_FP_DBG #define IP6_DEBUGP_API printk #else #define IP6_DEBUGP_API(format, args...) #endif #if IP6_FP_DBG #define IP6_DEBUGP_PKT printk #else #define IP6_DEBUGP_PKT(format, args...) #endif #if IP6_FP_DBG #define IP6_DEBUGP_SYS printk #else #define IP6_DEBUGP_SYS(format, args...) #endif /* [MARCO FUNCTION] ========================================================================= */ #define IP6_FASTPATH_ADJUST_CHKSUM_NAT_UDP(ip_mod, ip_org, chksum) \ do { \ s32 accumulate = 0; \ int i; \ if (chksum == 0) break; \ if (!ipv6_addr_any(ip_mod) && !ipv6_addr_any(ip_org)){ \ for (i=0; i<8; i++) { \ accumulate += (ip_org->s6_addr16[i]); \ } \ for (i=0; i<8; i++) { \ accumulate -= (ip_mod->s6_addr16[i]); \ } \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ #define IP6_FASTPATH_ADJUST_CHKSUM_NPT_UDP(port_mod, port_org, chksum) \ do { \ s32 accumulate = 0; \ if (chksum == 0) break; \ if (((port_mod) != 0) && ((port_org) != 0)){ \ accumulate += (port_org); \ accumulate -= (port_mod); \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ #define IP6_FASTPATH_ADJUST_CHKSUM_NAPT_UDP(ip_mod, ip_org, port_mod, port_org, chksum) \ do { \ s32 accumulate = 0; \ int i; \ if (chksum == 0) break; \ if (!ipv6_addr_any(ip_mod) && !ipv6_addr_any(ip_org)){ \ for (i=0; i<8; i++) { \ accumulate += (ip_org->s6_addr16[i]); \ } \ for (i=0; i<8; i++) { \ accumulate -= (ip_mod->s6_addr16[i]); \ } \ } \ if (((port_mod) != 0) && ((port_org) != 0)){ \ accumulate += (port_org); \ accumulate -= (port_mod); \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ #define IP6_FASTPATH_ADJUST_CHKSUM_NAT(ip_mod, ip_org, chksum) \ do { \ s32 accumulate = 0; \ int i; \ if (!ipv6_addr_any(ip_mod) && !ipv6_addr_any(ip_org)) { \ for (i=0; i<8; i++) { \ accumulate += (ip_org->s6_addr16[i]); \ } \ for (i=0; i<8; i++) { \ accumulate -= (ip_mod->s6_addr16[i]); \ } \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ #define IP6_FASTPATH_ADJUST_CHKSUM_NPT(port_mod, port_org, chksum) \ do { \ s32 accumulate = 0; \ if (((port_mod) != 0) && ((port_org) != 0)){ \ accumulate += (port_org); \ accumulate -= (port_mod); \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ #define IP6_FASTPATH_ADJUST_CHKSUM_NAPT(ip_mod, ip_org, port_mod, port_org, chksum) \ do { \ s32 accumulate = 0; \ int i; \ if (!ipv6_addr_any(ip_mod) && !ipv6_addr_any(ip_org)){ \ for (i=0; i<8; i++) { \ accumulate += (ip_org->s6_addr16[i]); \ } \ for (i=0; i<8; i++) { \ accumulate -= (ip_mod->s6_addr16[i]); \ } \ } \ if (((port_mod) != 0) && ((port_org) != 0)){ \ accumulate += (port_org); \ accumulate -= (port_mod); \ } \ accumulate += ntohs(chksum); \ if (accumulate < 0) { \ accumulate = -accumulate; \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) ~accumulate); \ } else { \ accumulate = (accumulate >> 16) + (accumulate & 0xffff); \ accumulate += accumulate >> 16; \ chksum = htons((__u16) accumulate); \ } \ }while(0) /* Checksum adjustment */ /* ---------------------------------------------------------------------------------------------------- */ #ifdef CONFIG_NF_CONNTRACK_IPV6 #if defined(USE_SKB_DEV) enum LR_RESULT fastpath_addRoutedIp6NaptConnection(struct sk_buff *skb, struct nf_conn *ct, struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple, int state); enum LR_RESULT fastpath_updateIp6NaptConnection(struct sk_buff *skb, struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple, unsigned int mark); #else enum LR_RESULT fastpath_addRoutedIp6NaptConnection(struct nf_conn *ct, struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple, int state); enum LR_RESULT fastpath_updateIp6NaptConnection(struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple, unsigned int mark); #endif enum LR_RESULT fastpath_delIp6NaptConnection (struct nf_conntrack_tuple *orig_tuple, struct nf_conntrack_tuple *reply_tuple); #else enum LR_RESULT fastpath_addRoutedIp6NaptConnectionWithoutNFV6(struct ipv6hdr *ip6hdr); enum LR_RESULT fastpath_delIp6NaptConnectionWithoutNFV6(struct ipv6hdr *ip6hdr); #endif int Ip6_FastPath_Enter(struct sk_buff *skb); int Ip6_clearFastPathEntry(void); /* ---------------------------------------------------------------------------------------------------- */ struct IP6_FP_NAPT_entry { struct in6_addr intIp; struct in6_addr extIp; struct in6_addr remIp; __u32 intPort; __u32 extPort; __u32 remPort; __u16 protocol; }; /* --- NAPT Table Structures --- */ struct Ip6_Napt_List_Entry { __u8 valid; __u16 protocol; struct in6_addr intIp; __u32 intPort; struct in6_addr extIp; __u32 extPort; struct in6_addr remIp; __u32 remPort; __u16 state; //0-unreplied 1-established. 2-path exist __u16 refcnt; __u32 course; //if no conntrack exist, we should use course to establish conntrack. CTAILQ_ENTRY(Ip6_Napt_List_Entry) napt_link; CTAILQ_ENTRY(Ip6_Napt_List_Entry) tqe_link; }; /* --- PATH Table Structures --- */ struct Ip6_Path_List_Entry { __u8 valid; __u16 *protocol; struct in6_addr *in_sIp; __u32 *in_sPort; struct in6_addr *in_dIp; __u32 *in_dPort; struct in6_addr *out_sIp; __u32 *out_sPort; struct in6_addr *out_dIp; __u32 *out_dPort; __u8 *out_ifname; __u8 course; /* 1:Out-Bonud 2:In-Bound */ void *dst; //struct dst_entry *dst; __u8 type; //pure routing, SNAT, SNPT, DNAT, DNPT /* FIXME: below two field are reserved now, they are used for IPQoS */ __u32 mark; //for IP QoS, TC __u32 last_refresh_time; //lifetime for this entry __u32 fdb_ageing; //this member only for upstream void * conn; //conntrack struct nf_conntrack_tuple orig_tuple; // tuple in IP_CT_DIR_ORIGINAL in conntrack __u32 pps; /* packets per second */ CTAILQ_ENTRY(Ip6_Path_List_Entry) path_link; CTAILQ_ENTRY(Ip6_Path_List_Entry) tqe_link; }; extern int ip6_fp_on; extern unsigned int br_ageing_time; static inline int Ip6_FastPath_Enabled(void) { return ip6_fp_on; } #ifdef CONFIG_NF_CONNTRACK_IPV6 enum LR_RESULT ip6_fastpath_addNaptConnection(void *ct, struct IP6_FP_NAPT_entry *napt, int state); enum LR_RESULT ip6_fastpath_delNaptConnection(struct IP6_FP_NAPT_entry *napt); enum LR_RESULT ip6_fastpath_updateNaptConnection(struct IP6_FP_NAPT_entry *napt, unsigned int mark); #else enum LR_RESULT ip6_fastpath_addNaptConnectionWithoutNFV6(struct IP6_FP_NAPT_entry *napt, int course); enum LR_RESULT ip6_fastpath_delNaptConnectionWithoutNFV6(struct IP6_FP_NAPT_entry *napt, int course); #endif int Ip6_FastPath_Process(void *pskb, struct ipv6hdr *ip6hdr); int fp_ip6route_input(void *pSt /*struct skbuff * */, struct ipv6hdr *iph, struct in6_addr *fp_dip, unsigned int course); int isNeighCreated(void *pDst, void* pSkb); int needFragment(void* pSkb, void *pDst); void ip6_fp_br_fdb_update(void *pSt); void updateConxTimer(struct Ip6_Path_List_Entry *ptr); int Ip6_packetParser(struct ipv6hdr *ip6hdr, __u8 *protoType, __u16 *sport, __u16 *dport, __u8 **l4hdr); int ip6_finish_output3(void *pskb, unsigned int course); char *ip6_sprintf(char *ip6buf, const struct in6_addr *addr); extern void __ip6_route_input(struct sk_buff *skb, struct in6_addr *saddr, struct in6_addr *daddr, struct net_device *in_dev); int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi6 *fl); #endif /* __IP6_FASTPATH_CORE_H__ */