Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 15 Jul 2006 04:57:06 +0000 (21:57 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 15 Jul 2006 04:57:06 +0000 (21:57 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6:
  [VLAN]: __vlan_hwaccel_rx can use the faster ether_compare_addr
  [PKT_SCHED] HTB: initialize upper bound properly
  [IPV4]: Clear skb cb on IP input
  [NET]: Update frag_list in pskb_trim

include/linux/if_vlan.h
net/core/skbuff.c
net/ipv4/ip_input.c
net/sched/sch_htb.c

index eef0876..383627a 100644 (file)
@@ -23,8 +23,8 @@ struct vlan_collection;
 struct vlan_dev_info;
 struct hlist_node;
 
-#include <linux/proc_fs.h> /* for proc_dir_entry */
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 
 #define VLAN_HLEN      4               /* The additional bytes (on top of the Ethernet header)
                                         * that VLAN requires.
@@ -185,7 +185,8 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb,
                 * This allows the VLAN to have a different MAC than the underlying
                 * device, and still route correctly.
                 */
-               if (!memcmp(eth_hdr(skb)->h_dest, skb->dev->dev_addr, ETH_ALEN))
+               if (!compare_ether_addr(eth_hdr(skb)->h_dest,
+                                       skb->dev->dev_addr))
                        skb->pkt_type = PACKET_HOST;
                break;
        };
index 44f6a18..476aa39 100644 (file)
@@ -257,11 +257,11 @@ nodata:
 }
 
 
-static void skb_drop_fraglist(struct sk_buff *skb)
+static void skb_drop_list(struct sk_buff **listp)
 {
-       struct sk_buff *list = skb_shinfo(skb)->frag_list;
+       struct sk_buff *list = *listp;
 
-       skb_shinfo(skb)->frag_list = NULL;
+       *listp = NULL;
 
        do {
                struct sk_buff *this = list;
@@ -270,6 +270,11 @@ static void skb_drop_fraglist(struct sk_buff *skb)
        } while (list);
 }
 
+static inline void skb_drop_fraglist(struct sk_buff *skb)
+{
+       skb_drop_list(&skb_shinfo(skb)->frag_list);
+}
+
 static void skb_clone_fraglist(struct sk_buff *skb)
 {
        struct sk_buff *list;
@@ -830,41 +835,75 @@ free_skb:
 
 int ___pskb_trim(struct sk_buff *skb, unsigned int len)
 {
+       struct sk_buff **fragp;
+       struct sk_buff *frag;
        int offset = skb_headlen(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
        int i;
+       int err;
+
+       if (skb_cloned(skb) &&
+           unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
+               return err;
 
        for (i = 0; i < nfrags; i++) {
                int end = offset + skb_shinfo(skb)->frags[i].size;
-               if (end > len) {
-                       if (skb_cloned(skb)) {
-                               if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
-                                       return -ENOMEM;
-                       }
-                       if (len <= offset) {
-                               put_page(skb_shinfo(skb)->frags[i].page);
-                               skb_shinfo(skb)->nr_frags--;
-                       } else {
-                               skb_shinfo(skb)->frags[i].size = len - offset;
-                       }
+
+               if (end < len) {
+                       offset = end;
+                       continue;
                }
-               offset = end;
+
+               if (len > offset)
+                       skb_shinfo(skb)->frags[i++].size = len - offset;
+
+               skb_shinfo(skb)->nr_frags = i;
+
+               for (; i < nfrags; i++)
+                       put_page(skb_shinfo(skb)->frags[i].page);
+
+               if (skb_shinfo(skb)->frag_list)
+                       skb_drop_fraglist(skb);
+               break;
        }
 
-       if (offset < len) {
+       for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
+            fragp = &frag->next) {
+               int end = offset + frag->len;
+
+               if (skb_shared(frag)) {
+                       struct sk_buff *nfrag;
+
+                       nfrag = skb_clone(frag, GFP_ATOMIC);
+                       if (unlikely(!nfrag))
+                               return -ENOMEM;
+
+                       nfrag->next = frag->next;
+                       frag = nfrag;
+                       *fragp = frag;
+               }
+
+               if (end < len) {
+                       offset = end;
+                       continue;
+               }
+
+               if (end > len &&
+                   unlikely((err = pskb_trim(frag, len - offset))))
+                       return err;
+
+               if (frag->next)
+                       skb_drop_list(&frag->next);
+               break;
+       }
+
+       if (len > skb_headlen(skb)) {
                skb->data_len -= skb->len - len;
                skb->len       = len;
        } else {
-               if (len <= skb_headlen(skb)) {
-                       skb->len      = len;
-                       skb->data_len = 0;
-                       skb->tail     = skb->data + len;
-                       if (skb_shinfo(skb)->frag_list && !skb_cloned(skb))
-                               skb_drop_fraglist(skb);
-               } else {
-                       skb->data_len -= skb->len - len;
-                       skb->len       = len;
-               }
+               skb->len       = len;
+               skb->data_len  = 0;
+               skb->tail      = skb->data + len;
        }
 
        return 0;
index e1a7dba..184c78c 100644 (file)
@@ -428,6 +428,9 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt,
                goto drop;
        }
 
+       /* Remove any debris in the socket control block */
+       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
+
        return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
                       ip_rcv_finish);
 
index 34afe41..cd0a973 100644 (file)
@@ -196,7 +196,7 @@ struct htb_class
     struct qdisc_rate_table *rate;     /* rate table of the class itself */
     struct qdisc_rate_table *ceil;     /* ceiling rate (limits borrows too) */
     long buffer,cbuffer;               /* token bucket depth/rate */
-    long mbuffer;                      /* max wait time */
+    psched_tdiff_t mbuffer;            /* max wait time */
     long tokens,ctokens;               /* current number of tokens */
     psched_time_t t_c;                 /* checkpoint time */
 };
@@ -1601,7 +1601,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
                /* set class to be in HTB_CAN_SEND state */
                cl->tokens = hopt->buffer;
                cl->ctokens = hopt->cbuffer;
-               cl->mbuffer = 60000000; /* 1min */
+               cl->mbuffer = PSCHED_JIFFIE2US(HZ*60) /* 1min */
                PSCHED_GET_TIME(cl->t_c);
                cl->cmode = HTB_CAN_SEND;