diff options
| author | Jamal Hadi Salim <hadi@znyx.com> | 2004-06-15 06:37:41 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.davemloft.net> | 2004-06-15 06:37:41 -0700 |
| commit | 4e54c4816bfe51c145382d272b19c2ae41e9e36f (patch) | |
| tree | b339b5972390a72c296ef6bdab04f58a93cf1191 /net/core/dev.c | |
| parent | 71279d2bf78ec4f7026531e85b36c1d3d7fcb4c2 (diff) | |
[NET]: Add tc extensions infrastructure.
Signed-off-by: Jamal Hadi Salim <hadi@znyx.com>
Signed-off-by: David S. Miller <davem@redhat.com>
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index fb20e1047f27..e3ef7d5884ff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1351,6 +1351,9 @@ int dev_queue_xmit(struct sk_buff *skb) /* Grab device queue */ spin_lock_bh(&dev->queue_lock); q = dev->qdisc; +#ifdef CONFIG_NET_CLS_ACT + skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); +#endif if (q->enqueue) { rc = q->enqueue(skb, q); @@ -1731,6 +1734,48 @@ static inline int __handle_bridge(struct sk_buff *skb, return 0; } + +#ifdef CONFIG_NET_CLS_ACT +/* TODO: Maybe we should just force sch_ingress to be compiled in + * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions + * a compare and 2 stores extra right now if we dont have it on + * but have CONFIG_NET_CLS_ACT + * NOTE: This doesnt stop any functionality; if you dont have + * the ingress scheduler, you just cant add policies on ingress. + * + */ +int ing_filter(struct sk_buff *skb) +{ + struct Qdisc *q; + struct net_device *dev = skb->dev; + int result = TC_ACT_OK; + + if (dev->qdisc_ingress) { + __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); + if (MAX_RED_LOOP < ttl++) { + printk("Redir loop detected Dropping packet (%s->%s)\n", + skb->input_dev?skb->input_dev->name:"??",skb->dev->name); + return TC_ACT_SHOT; + } + + skb->tc_verd = SET_TC_RTTL(skb->tc_verd,ttl); + + skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); + if (NULL == skb->input_dev) { + skb->input_dev = skb->dev; + printk("ing_filter: fixed %s out %s\n",skb->input_dev->name,skb->dev->name); + } + spin_lock(&dev->ingress_lock); + if ((q = dev->qdisc_ingress) != NULL) + result = q->enqueue(skb, q); + spin_unlock(&dev->ingress_lock); + + } + + return result; +} +#endif + int netif_receive_skb(struct sk_buff *skb) { struct packet_type *ptype, *pt_prev; @@ -1762,6 +1807,13 @@ int netif_receive_skb(struct sk_buff *skb) skb->mac_len = skb->nh.raw - skb->mac.raw; pt_prev = NULL; +#ifdef CONFIG_NET_CLS_ACT + if (skb->tc_verd & TC_NCLS) { + skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); + goto ncls; + } + #endif + rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_all, list) { if (!ptype->dev || ptype->dev == skb->dev) { @@ -1771,6 +1823,26 @@ int netif_receive_skb(struct sk_buff *skb) } } +#ifdef CONFIG_NET_CLS_ACT + if (pt_prev) { + atomic_inc(&skb->users); + ret = pt_prev->func(skb, skb->dev, pt_prev); + pt_prev = NULL; /* noone else should process this after*/ + } else { + skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); + } + + ret = ing_filter(skb); + + if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) { + kfree_skb(skb); + goto out; + } + + skb->tc_verd = 0; +ncls: +#endif + handle_diverter(skb); if (__handle_bridge(skb, &pt_prev, &ret)) @@ -2824,6 +2896,10 @@ int register_netdevice(struct net_device *dev) spin_lock_init(&dev->queue_lock); spin_lock_init(&dev->xmit_lock); dev->xmit_lock_owner = -1; +#ifdef CONFIG_NET_CLS_ACT + spin_lock_init(&dev->ingress_lock); +#endif + #ifdef CONFIG_NET_FASTROUTE dev->fastpath_lock = RW_LOCK_UNLOCKED; #endif @@ -3358,4 +3434,9 @@ EXPORT_SYMBOL(netdev_fastroute); EXPORT_SYMBOL(netdev_fastroute_obstacles); #endif +#ifdef CONFIG_NET_CLS_ACT +EXPORT_SYMBOL(ing_filter); +#endif + + EXPORT_PER_CPU_SYMBOL(softnet_data); |
