On Friday 2009-06-05 03:15, Florian Westphal wrote: > >+static u32 hash_v4(const struct sk_buff *skb) >+{ >+ const struct iphdr *iph = ip_hdr(skb); >+ u32 ipaddr; >+ >+ /* packets in either direction go into same queue */ >+ ipaddr = iph->saddr ^ iph->daddr; >+ >+ return jhash_2words(ipaddr, iph->protocol, jhash_initval); >+} >+ >+static unsigned int >+nfqueue_tg4_v1(struct sk_buff *skb, const struct xt_target_param *par) >+{ >+ const struct xt_NFQ_info_v1 *info = par->targinfo; >+ u32 queue = info->queuenum; >+ >+ if (info->queues_total > 1) >+ queue = hash_v4(skb) % info->queues_total + queue; >+ return NF_QUEUE_NR(queue); >+} >+ >+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) >+static u32 hash_v6(const struct sk_buff *skb) >+{ >+ const struct ipv6hdr *ip6h = ipv6_hdr(skb); >+ u32 addr[4]; >+ >+ addr[0] = ip6h->saddr.s6_addr32[0] ^ ip6h->daddr.s6_addr32[0]; >+ addr[1] = ip6h->saddr.s6_addr32[1] ^ ip6h->daddr.s6_addr32[1]; >+ addr[2] = ip6h->saddr.s6_addr32[2] ^ ip6h->daddr.s6_addr32[2]; >+ addr[3] = ip6h->saddr.s6_addr32[3] ^ ip6h->daddr.s6_addr32[3]; >+ >+ return jhash2(addr, 4, jhash_initval); >+} >+ >+static unsigned int >+nfqueue_tg6_v1(struct sk_buff *skb, const struct xt_target_param *par) >+{ >+ const struct xt_NFQ_info_v1 *info = par->targinfo; >+ u32 queue = info->queuenum; >+ >+ if (info->queues_total > 1) >+ queue = hash_v6(skb) % info->queues_total + queue; >+ return NF_QUEUE_NR(queue); >+} >+#endif >+ >+static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par) >+{ >+ const struct xt_NFQ_info_v1 *info = par->targinfo; >+ u32 maxid; >+ >+ if (info->queues_total == 0) { >+ printk(KERN_ERR "NFQUEUE: number of total queues is 0\n"); >+ return false; >+ } >+ maxid = info->queues_total - 1 + info->queuenum; >+ if (maxid > 0xffff) { >+ printk(KERN_ERR "NFQUEUE: number of queues (%u) out of range (got %u)\n", >+ info->queues_total, maxid); >+ return false; >+ } >+ return true; >+} >+ > static struct xt_target nfqueue_tg_reg[] __read_mostly = { > { > .name = "NFQUEUE", >@@ -39,10 +111,31 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = { > .targetsize = sizeof(struct xt_NFQ_info), > .me = THIS_MODULE, > }, >+ { >+ .name = "NFQUEUE", >+ .revision = 1, >+ .family = NFPROTO_IPV4, >+ .checkentry = nfqueue_tg_v1_check, >+ .target = nfqueue_tg4_v1, >+ .targetsize = sizeof(struct xt_NFQ_info_v1), >+ .me = THIS_MODULE, >+ }, >+#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) >+ { >+ .name = "NFQUEUE", >+ .revision = 1, >+ .family = NFPROTO_IPV6, >+ .checkentry = nfqueue_tg_v1_check, >+ .target = nfqueue_tg6_v1, >+ .targetsize = sizeof(struct xt_NFQ_info_v1), >+ .me = THIS_MODULE, >+ }, >+#endif I'd say this could be done with much less code: (tg_reg with NFPROTO_UNSPEC entry) and static bool nfqueue_v1(skb, tgpar) { const struct xt_NFQ_info_v1 *info = par->targinfo; u32 queue = info->queuenum; if (info->queues_total > 1) { if (tgpar->target->family == NFPROTO_IPV4) queue = hash_v4(skb) % info->queues_total + queue; #if IPV6 else if (tgpar->target->family == NFPROTO_IPV6) queue = hash_v6(skb) % info->queues_total + queue; #endif } return NF_QUEUE_NR(queue); } -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html