Fix to the missing SYN/ACK bug
[linux-2.6.git] / linux-2.6-525-sknid-elevator.patch
1 diff -Nurb linux-2.6.22-524/net/core/dev.c linux-2.6.22-525/net/core/dev.c
2 --- linux-2.6.22-524/net/core/dev.c     2008-07-21 16:44:33.000000000 -0400
3 +++ linux-2.6.22-525/net/core/dev.c     2008-07-27 22:02:10.000000000 -0400
4 @@ -97,6 +97,8 @@
5  #include <linux/proc_fs.h>
6  #include <linux/seq_file.h>
7  #include <linux/stat.h>
8 +#include <linux/ip.h>
9 +#include <linux/tcp.h>
10  #include <linux/if_bridge.h>
11  #include <net/dst.h>
12  #include <net/pkt_sched.h>
13 @@ -1131,7 +1133,7 @@
14                 if ((ptype->dev == dev || !ptype->dev) &&
15                     (ptype->af_packet_priv == NULL ||
16                      (struct sock *)ptype->af_packet_priv != skb->sk)) {
17 -                       struct sk_buff *skb2= skb_clone(skb, GFP_ATOMIC);
18 +                       struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
19                         if (!skb2)
20                                 break;
21  
22 @@ -1803,6 +1805,7 @@
23   * the ingress scheduler, you just cant add policies on ingress.
24   *
25   */
26 +
27  static int ing_filter(struct sk_buff *skb)
28  {
29         struct Qdisc *q;
30 @@ -1832,13 +1835,21 @@
31  }
32  #endif
33  
34 +/* The code already makes the assumption that packet handlers run
35 + * sequentially on the same CPU. -Sapan */
36 +DEFINE_PER_CPU(int, sknid_elevator) = 0;
37 +
38  int netif_receive_skb(struct sk_buff *skb)
39  {
40         struct packet_type *ptype, *pt_prev;
41         struct net_device *orig_dev;
42         int ret = NET_RX_DROP;
43 +       int *cur_elevator=&__get_cpu_var(sknid_elevator);
44 +       struct sk_buff *skb2;
45         __be16 type;
46  
47 +       *cur_elevator = 0;
48 +
49         /* if we've gotten here through NAPI, check netpoll */
50         if (skb->dev->poll && netpoll_rx(skb))
51                 return NET_RX_DROP;
52 @@ -1871,10 +1882,12 @@
53         }
54  #endif
55  
56 +       skb2 = skb_clone(skb, GFP_ATOMIC);
57         list_for_each_entry_rcu(ptype, &ptype_all, list) {
58                 if (!ptype->dev || ptype->dev == skb->dev) {
59 -                       if (pt_prev)
60 +                       if (pt_prev) {
61                                 ret = deliver_skb(skb, pt_prev, orig_dev);
62 +                       }
63                         pt_prev = ptype;
64                 }
65         }
66 @@ -1891,6 +1904,7 @@
67  
68         if (ret == TC_ACT_SHOT || (ret == TC_ACT_STOLEN)) {
69                 kfree_skb(skb);
70 +               kfree_skb(skb2);
71                 goto out;
72         }
73  
74 @@ -1899,8 +1913,17 @@
75  #endif
76  
77         skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
78 -       if (!skb)
79 +       if (!skb) {
80 +               kfree_skb(skb2);
81                 goto out;
82 +       }
83 +
84 +       /* We don't want the packet handlers to throw the packet away
85 +        * if we want the taps to treat it again - Sapan */
86 +       if (!skb2) {
87 +               *cur_elevator = 0;
88 +       }
89 +
90  
91         type = skb->protocol;
92         list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
93 @@ -1914,6 +1937,7 @@
94  
95         if (pt_prev) {
96                 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
97 +               
98         } else {
99                 kfree_skb(skb);
100                 /* Jamal, now you will not able to escape explaining
101 @@ -1922,6 +1946,29 @@
102                 ret = NET_RX_DROP;
103         }
104  
105 +       if ((*cur_elevator)>0) {
106 +               skb2->skb_tag = *cur_elevator;
107 +               list_for_each_entry_rcu(ptype, &ptype_all, list) {
108 +                       if ((!ptype->dev || ptype->dev == skb2->dev) && (ptype->sknid_elevator)) {
109 +                               ret = deliver_skb(skb2, ptype, orig_dev);
110 +                       }
111 +               }
112 +               type = skb2->protocol;
113 +               list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) {
114 +                       if (ptype->type == type &&
115 +                           (!ptype->dev || ptype->dev == skb2->dev) && (ptype->sknid_elevator)) {
116 +                               ret = deliver_skb(skb2, ptype, orig_dev);
117 +                       }
118 +               }
119 +       }
120 +
121 +       if (skb2) {
122 +               /* We have a packet */
123 +               kfree_skb(skb2);
124 +       }
125 +
126 +       *cur_elevator=0;
127 +
128  out:
129         rcu_read_unlock();
130         return ret;
131 @@ -3780,6 +3827,7 @@
132  EXPORT_SYMBOL(net_enable_timestamp);
133  EXPORT_SYMBOL(net_disable_timestamp);
134  EXPORT_SYMBOL(dev_get_flags);
135 +EXPORT_PER_CPU_SYMBOL(sknid_elevator);
136  
137  #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
138  EXPORT_SYMBOL(br_handle_frame_hook);
139 diff -Nurb linux-2.6.22-524/net/packet/af_packet.c linux-2.6.22-525/net/packet/af_packet.c
140 --- linux-2.6.22-524/net/packet/af_packet.c     2007-07-08 19:32:17.000000000 -0400
141 +++ linux-2.6.22-525/net/packet/af_packet.c     2008-07-27 22:02:22.000000000 -0400
142 @@ -78,6 +78,7 @@
143  #include <linux/poll.h>
144  #include <linux/module.h>
145  #include <linux/init.h>
146 +#include <linux/vs_network.h>
147  
148  #ifdef CONFIG_INET
149  #include <net/inet_common.h>
150 @@ -246,10 +247,53 @@
151  
152  static const struct proto_ops packet_ops_spkt;
153  
154 +extern DEFINE_PER_CPU(int, sknid_elevator);
155 +
156 +static inline unsigned int slice_check_and_elevate(struct sk_buff *skb, struct sock *sk) {
157 +       /* This mechanism is quite involved, and caused us a lot of pain
158 +        * including crashes and packet loss during the 4.2 rollout. This
159 +        * function decides if a slice is allowed to see a given packet.
160 +        * Unfortunately, the first time it is invoked for a packet it does not
161 +        * have enough information to make this call, since xt_MARK has not had
162 +        * a chance to tag it with the slice id.  There is also no way of
163 +        * passing state between xt_MARK and this function through a packet --
164 +        * because the skb gets cloned quite a few times between these two
165 +        * points.  I'd rather not use skb_shared_info because it's treated as
166 +        * a blob of memory, and so it would be quite hard to maintain.
167 +        *
168 +        * What we do is to keep a global variable (per CPU) that transfers the
169 +        * required state between xt_MARK and af_packet.c. As an optimization,
170 +        * this state transfer and the step that follows is only executed for
171 +        * packets that first get dropped here. When we drop a packet, we mark
172 +        * it for 'elevation' (that's what this trick is called). When xt_MARK
173 +        * tags the packet with the right slice, it intercepts this mark and
174 +        * sets the value of sknid_elevator. Next, the packet is sent back here
175 +        * for a second round, this time with the xid tag set.
176 +        */
177 +
178 +       int *elevator=&__get_cpu_var(sknid_elevator);
179 +       int tag = skb->skb_tag;
180 +
181 +       if (sk->sk_nx_info && !(tag == 1 || sk->sk_nid == tag)) {
182 +               if (skb->pkt_type==PACKET_HOST) {
183 +                       *elevator=-2; /* Rejecting this packet. Mark it for elevation in xt_MARK */
184 +               }
185 +               return 0;
186 +       }
187 +       else if (!sk->sk_nx_info && (*elevator>0)) {
188 +               /* Root has already seen this packet once, since it has been elevated */
189 +               return 0;
190 +       }
191 +
192 +       return 1;
193 +}
194 +
195  static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt, struct net_device *orig_dev)
196  {
197         struct sock *sk;
198         struct sockaddr_pkt *spkt;
199 +       int tag = skb->skb_tag;
200 +
201  
202         /*
203          *      When we registered the protocol we saved the socket in the data
204 @@ -269,6 +313,16 @@
205          *      so that this procedure is noop.
206          */
207  
208 +       /* 
209 +        * (18:05:41) daniel_hozac: where?
210 +        * (18:05:58) daniel_hozac: we already have filters on PF_PACKET, don't we?
211 +        * (18:05:58) er: in packet_rcv_skpt
212 +        * (18:07:33) daniel_hozac: oh, that's evil. 
213 +        */
214 +
215 +       if (!slice_check_and_elevate(skb, sk))
216 +               return 0;
217 +
218         if (skb->pkt_type == PACKET_LOOPBACK)
219                 goto out;
220  
221 @@ -324,6 +378,9 @@
222         __be16 proto=0;
223         int err;
224  
225 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SEND))
226 +               return -EPERM;
227 +
228         /*
229          *      Get and verify the address.
230          */
231 @@ -416,11 +473,16 @@
232         return err;
233  }
234  
235 +
236 +
237  static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
238                                       unsigned int res)
239  {
240         struct sk_filter *filter;
241  
242 +       if (!slice_check_and_elevate(skb, sk)) 
243 +               return 0;
244 +
245         rcu_read_lock_bh();
246         filter = rcu_dereference(sk->sk_filter);
247         if (filter != NULL)
248 @@ -711,6 +773,9 @@
249         unsigned char *addr;
250         int ifindex, err, reserve = 0;
251  
252 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SEND)) 
253 +               return -EPERM;
254 +
255         /*
256          *      Get and verify the address.
257          */
258 @@ -880,6 +945,7 @@
259  
260         po->num = protocol;
261         po->prot_hook.type = protocol;
262 +       po->prot_hook.sknid_elevator = 1;
263         po->prot_hook.dev = dev;
264  
265         po->ifindex = dev ? dev->ifindex : 0;
266 @@ -984,8 +1050,9 @@
267         __be16 proto = (__force __be16)protocol; /* weird, but documented */
268         int err;
269  
270 -       if (!capable(CAP_NET_RAW))
271 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET))
272                 return -EPERM;
273 +               
274         if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
275             sock->type != SOCK_PACKET)
276                 return -ESOCKTNOSUPPORT;
277 @@ -1016,6 +1083,7 @@
278  
279         spin_lock_init(&po->bind_lock);
280         po->prot_hook.func = packet_rcv;
281 +       po->prot_hook.sknid_elevator = 1;
282  
283         if (sock->type == SOCK_PACKET)
284                 po->prot_hook.func = packet_rcv_spkt;