aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-14 03:38:47 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-15 15:26:26 -0400
commitf697c3e8b35c18b2698d64137c0fa84b0cdb3d10 (patch)
treea234201c36081f540179195dfabfce4b434aa0f2 /net
parent776c729e8d91b2740583a2169678f2d3f383458b (diff)
[NET]: Avoid unnecessary cloning for ingress filtering
As it is we always invoke pt_prev before ing_filter, even if there are no ingress filters attached. This can cause unnecessary cloning in pt_prev. This patch changes it so that we only invoke pt_prev if there are ingress filters attached. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c68
1 files changed, 40 insertions, 28 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 99b7bda37d10..39aba4862f21 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1949,27 +1949,51 @@ static int ing_filter(struct sk_buff *skb)
1949 struct Qdisc *q; 1949 struct Qdisc *q;
1950 struct net_device *dev = skb->dev; 1950 struct net_device *dev = skb->dev;
1951 int result = TC_ACT_OK; 1951 int result = TC_ACT_OK;
1952 u32 ttl = G_TC_RTTL(skb->tc_verd);
1952 1953
1953 if (dev->qdisc_ingress) { 1954 if (MAX_RED_LOOP < ttl++) {
1954 __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); 1955 printk(KERN_WARNING
1955 if (MAX_RED_LOOP < ttl++) { 1956 "Redir loop detected Dropping packet (%d->%d)\n",
1956 printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", 1957 skb->iif, dev->ifindex);
1957 skb->iif, skb->dev->ifindex); 1958 return TC_ACT_SHOT;
1958 return TC_ACT_SHOT; 1959 }
1959 }
1960 1960
1961 skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl); 1961 skb->tc_verd = SET_TC_RTTL(skb->tc_verd, ttl);
1962 skb->tc_verd = SET_TC_AT(skb->tc_verd, AT_INGRESS);
1962 1963
1963 skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); 1964 spin_lock(&dev->ingress_lock);
1965 if ((q = dev->qdisc_ingress) != NULL)
1966 result = q->enqueue(skb, q);
1967 spin_unlock(&dev->ingress_lock);
1968
1969 return result;
1970}
1964 1971
1965 spin_lock(&dev->ingress_lock); 1972static inline struct sk_buff *handle_ing(struct sk_buff *skb,
1966 if ((q = dev->qdisc_ingress) != NULL) 1973 struct packet_type **pt_prev,
1967 result = q->enqueue(skb, q); 1974 int *ret, struct net_device *orig_dev)
1968 spin_unlock(&dev->ingress_lock); 1975{
1976 if (!skb->dev->qdisc_ingress)
1977 goto out;
1969 1978
1979 if (*pt_prev) {
1980 *ret = deliver_skb(skb, *pt_prev, orig_dev);
1981 *pt_prev = NULL;
1982 } else {
1983 /* Huh? Why does turning on AF_PACKET affect this? */
1984 skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
1970 } 1985 }
1971 1986
1972 return result; 1987 switch (ing_filter(skb)) {
1988 case TC_ACT_SHOT:
1989 case TC_ACT_STOLEN:
1990 kfree_skb(skb);
1991 return NULL;
1992 }
1993
1994out:
1995 skb->tc_verd = 0;
1996 return skb;
1973} 1997}
1974#endif 1998#endif
1975 1999
@@ -2021,21 +2045,9 @@ int netif_receive_skb(struct sk_buff *skb)
2021 } 2045 }
2022 2046
2023#ifdef CONFIG_NET_CLS_ACT 2047#ifdef CONFIG_NET_CLS_ACT
2024 if (pt_prev) { 2048 skb = handle_ing(skb, &pt_prev, &ret, orig_dev);
2025 ret = deliver_skb(skb, pt_prev, orig_dev); 2049 if (!skb)
2026 pt_prev = NULL; /* noone else should process this after*/
2027 } else {
2028 skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd);
2029 }
2030
2031 ret = ing_filter(skb);
2032
2033 if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
2034 kfree_skb(skb);
2035 goto out; 2050 goto out;
2036 }
2037
2038 skb->tc_verd = 0;
2039ncls: 2051ncls:
2040#endif 2052#endif
2041 2053