--- zzzz-none-000/linux-2.4.17/net/sched/cls_u32.c 2001-12-21 17:42:06.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/net/sched/cls_u32.c 2004-11-24 13:22:06.000000000 +0000 @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,31 @@ return h; } +static int u32_port_match(u8 *ptr, struct tc_u32_key *key, u32 off2) +{ + __u16 src_min, src_max, dst_min, dst_max; + __u16 src_port, dst_port; + __u32 value; + + /* Get min/max values for source and destination ports */ + src_min = (key->val & 0xffff0000) >> 16; + dst_min = key->val & 0x0000ffff; + src_max = (key->mask & 0xffff0000) >> 16; + dst_max = key->mask & 0x0000ffff; + + /* Get source and destination port from the packet */ + value = (*(u32*)(ptr+key->off+(off2&key->offmask))); + src_port = (value & 0xffff0000) >> 16; + dst_port = value & 0x0000ffff; + + /* The max value for src/dst is checked if it is zero, then + * corresponding classification is ignored. */ + if (((src_max != 0) && (src_port < src_min || src_port > src_max)) || + ((dst_max != 0) && (dst_port < dst_min || dst_port > dst_max))) + return 0; /* match failed */ + return 1; /* match success */ +} + static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_result *res) { struct { @@ -111,21 +137,58 @@ int off2 = 0; int sel = 0; int i; + u8 tos_set = 0; + u16 chk; + +#ifdef CONFIG_IP_NF_TARGET_MASQUERADE + u32 src; +#endif + +#ifdef CONFIG_NET_SCH_PRIOWRR + /* This can happen for PPP Control packets. These packets are not IP packets so the + * IP header is NULL. This packet is classified to the EF2 queue.*/ + if (ptr == NULL) + { + res->classid = 2; + return 0; + } +#endif + + chk = skb->nh.iph->check; + +#ifdef CONFIG_IP_NF_TARGET_MASQUERADE + src = skb->nh.iph->saddr; + skb->nh.iph->saddr = *(__u32 *)skb->cb; +#endif #if !defined(__i386__) && !defined(__mc68000__) if ((unsigned long)ptr & 3) return -1; #endif + skb->nh.iph->check = (u16)skb->__unused; + next_ht: n = ht->ht[sel]; next_knode: if (n) { struct tc_u32_key *key = n->sel.keys; - for (i = n->sel.nkeys; i>0; i--, key++) { - if ((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) { + if (key->off == 0) + { + skb->nh.iph->check = 0; + skb->nh.iph->tos = key->val >> 8; /* Write both Precedence and TOS bits */ + tos_set = 1; + } + else if (key->off == 20) + { + if (!u32_port_match(ptr, key, off2)) { + n = n->next; + goto next_knode; + } + } + else if ((*(u32*)(ptr+key->off+(off2&key->offmask))^key->val)&key->mask) { n = n->next; goto next_knode; } @@ -134,12 +197,24 @@ check_terminal: if (n->sel.flags&TC_U32_TERMINAL) { *res = n->res; + +#ifdef CONFIG_IP_NF_TARGET_MASQUERADE + skb->nh.iph->saddr = src; + *(__u32 *)skb->cb = 0; +#endif + + if (tos_set == 1) + skb->nh.iph->check = ip_fast_csum((unsigned char *)skb->nh.iph, skb->nh.iph->ihl); + else + skb->nh.iph->check = chk; + #ifdef CONFIG_NET_CLS_POLICE if (n->police) { int pol_res = tcf_police(skb, n->police); if (pol_res >= 0) return pol_res; - } else + } + else #endif return 0; } @@ -184,11 +259,25 @@ ptr = stack[sdepth].ptr; goto check_terminal; } + skb->nh.iph->check = chk; + +#ifdef CONFIG_IP_NF_TARGET_MASQUERADE + skb->nh.iph->saddr = src; + //*(__u32 *)skb->cb = 0; +#endif + return -1; deadloop: if (net_ratelimit()) printk("cls_u32: dead loop\n"); + skb->nh.iph->check = chk; + +#ifdef CONFIG_IP_NF_TARGET_MASQUERADE + skb->nh.iph->saddr = src; + //*(__u32 *)skb->cb = 0; +#endif + return -1; }