13 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
19 #include <linux/netlink.h>
21 #include <linux/rtnetlink.h>
28 #include <linux/icmpv6.h>
29 #include <linux/igmp.h>
39 #define CSUM_TAB_MASK 15
41 static u32 csum_idx_gen;
55 struct tc_action *
a,
int ovr,
int bind)
77 &csum_idx_gen, &csum_hash_info);
90 spin_lock_bh(&p->tcf_lock);
91 p->tcf_action = parm->action;
93 spin_unlock_bh(&p->tcf_lock);
95 if (ret == ACT_P_CREATED)
101 static int tcf_csum_cleanup(
struct tc_action *a,
int bind)
117 static void *tcf_csum_skb_nextlayer(
struct sk_buff *
skb,
118 unsigned int ihl,
unsigned int ipl,
121 int ntkoff = skb_network_offset(skb);
124 if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
126 !skb_clone_writable(skb, hl + ntkoff) &&
130 return (
void *)(skb_network_header(skb) + ihl);
133 static int tcf_csum_ipv4_icmp(
struct sk_buff *skb,
134 unsigned int ihl,
unsigned int ipl)
138 icmph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*icmph));
151 static int tcf_csum_ipv4_igmp(
struct sk_buff *skb,
152 unsigned int ihl,
unsigned int ipl)
156 igmph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*igmph));
169 static int tcf_csum_ipv6_icmp(
struct sk_buff *skb,
struct ipv6hdr *ip6h,
170 unsigned int ihl,
unsigned int ipl)
174 icmp6h = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*icmp6h));
189 static int tcf_csum_ipv4_tcp(
struct sk_buff *skb,
struct iphdr *iph,
190 unsigned int ihl,
unsigned int ipl)
194 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*tcph));
200 tcph->
check = tcp_v4_check(ipl - ihl,
208 static int tcf_csum_ipv6_tcp(
struct sk_buff *skb,
struct ipv6hdr *ip6h,
209 unsigned int ihl,
unsigned int ipl)
213 tcph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*tcph));
228 static int tcf_csum_ipv4_udp(
struct sk_buff *skb,
struct iphdr *iph,
229 unsigned int ihl,
unsigned int ipl,
int udplite)
241 udph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*udph));
247 if (udplite || udph->
check) {
254 else if ((ul >=
sizeof(*udph)) && (ul <= ipl - ihl))
257 goto ignore_obscure_skb;
260 goto ignore_obscure_skb;
279 static int tcf_csum_ipv6_udp(
struct sk_buff *skb,
struct ipv6hdr *ip6h,
280 unsigned int ihl,
unsigned int ipl,
int udplite)
292 udph = tcf_csum_skb_nextlayer(skb, ihl, ipl,
sizeof(*udph));
304 else if ((ul >=
sizeof(*udph)) && (ul <= ipl - ihl))
308 goto ignore_obscure_skb;
311 goto ignore_obscure_skb;
329 static int tcf_csum_ipv4(
struct sk_buff *skb,
u32 update_flags)
334 ntkoff = skb_network_offset(skb);
336 if (!pskb_may_pull(skb,
sizeof(*iph) + ntkoff))
344 if (!tcf_csum_ipv4_icmp(skb, iph->ihl * 4,
350 if (!tcf_csum_ipv4_igmp(skb, iph->ihl * 4,
356 if (!tcf_csum_ipv4_tcp(skb, iph, iph->ihl * 4,
362 if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4,
368 if (!tcf_csum_ipv4_udp(skb, iph, iph->ihl * 4,
375 if (skb_cloned(skb) &&
376 !skb_clone_writable(skb,
sizeof(*iph) + ntkoff) &&
389 static int tcf_csum_ipv6_hopopts(
struct ipv6_opt_hdr *ip6xh,
390 unsigned int ixhl,
unsigned int *
pl)
392 int off,
len, optlen;
393 unsigned char *xh = (
void *)ip6xh;
395 off =
sizeof(*ip6xh);
404 optlen = xh[off + 1] + 2;
405 if (optlen != 6 || len < 6 || (off & 3) != 2)
411 optlen = xh[off + 1] + 2;
425 static int tcf_csum_ipv6(
struct sk_buff *skb,
u32 update_flags)
429 unsigned int hl, ixhl;
434 ntkoff = skb_network_offset(skb);
438 if (!pskb_may_pull(skb, hl + ntkoff))
441 ip6h = ipv6_hdr(skb);
453 if (!pskb_may_pull(skb, hl +
sizeof(*ip6xh) + ntkoff))
455 ip6xh = (
void *)(skb_network_header(skb) + hl);
457 if (!pskb_may_pull(skb, hl + ixhl + ntkoff))
460 !(tcf_csum_ipv6_hopopts(ip6xh, ixhl, &pl)))
466 if (update_flags & TCA_CSUM_UPDATE_FLAG_ICMP)
467 if (!tcf_csum_ipv6_icmp(skb, ip6h,
468 hl, pl +
sizeof(*ip6h)))
472 if (update_flags & TCA_CSUM_UPDATE_FLAG_TCP)
473 if (!tcf_csum_ipv6_tcp(skb, ip6h,
474 hl, pl +
sizeof(*ip6h)))
478 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDP)
479 if (!tcf_csum_ipv6_udp(skb, ip6h, hl,
480 pl +
sizeof(*ip6h), 0))
484 if (update_flags & TCA_CSUM_UPDATE_FLAG_UDPLITE)
485 if (!tcf_csum_ipv6_udp(skb, ip6h, hl,
486 pl +
sizeof(*ip6h), 1))
492 }
while (pskb_may_pull(skb, hl + 1 + ntkoff));
509 spin_lock(&p->tcf_lock);
511 bstats_update(&p->tcf_bstats, skb);
512 action = p->tcf_action;
514 spin_unlock(&p->tcf_lock);
521 if (!tcf_csum_ipv4(skb, update_flags))
525 if (!tcf_csum_ipv6(skb, update_flags))
533 spin_lock(&p->tcf_lock);
534 p->tcf_qstats.drops++;
535 spin_unlock(&p->tcf_lock);
539 static int tcf_csum_dump(
struct sk_buff *skb,
540 struct tc_action *a,
int bind,
int ref)
542 unsigned char *
b = skb_tail_pointer(skb);
546 .index = p->tcf_index,
547 .action = p->tcf_action,
548 .refcnt = p->tcf_refcnt - ref,
549 .bindcnt = p->tcf_bindcnt - bind,
554 goto nla_put_failure;
559 goto nla_put_failure;
568 static struct tc_action_ops act_csum_ops = {
570 .hinfo = &csum_hash_info,
572 .capab = TCA_CAP_NONE,
575 .dump = tcf_csum_dump,
576 .cleanup = tcf_csum_cleanup,
578 .init = tcf_csum_init,
585 static int __init csum_init_module(
void)
590 static void __exit csum_cleanup_module(
void)