net/packet/built-in.o:(.discard+0x0): multiple definition of __pcpu_unique_sknid_elevator
[linux-2.6.git] / linux-2.6-525-sknid-elevator.patch
1 diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
2 index 4267c8b..3f36a91 100644
3 --- a/include/linux/netdevice.h
4 +++ b/include/linux/netdevice.h
5 @@ -1057,6 +1057,7 @@ struct napi_gro_cb {
6  struct packet_type {
7         __be16                  type;   /* This is really htons(ether_type). */
8         struct net_device       *dev;   /* NULL is wildcarded here           */
9 +       unsigned char           sknid_elevator; 
10         int                     (*func) (struct sk_buff *,
11                                          struct net_device *,
12                                          struct packet_type *,
13 diff --git a/net/core/dev.c b/net/core/dev.c
14 index 8b6b941..651a1c3 100644
15 --- a/net/core/dev.c
16 +++ b/net/core/dev.c
17 @@ -99,6 +99,8 @@
18  #include <linux/proc_fs.h>
19  #include <linux/seq_file.h>
20  #include <linux/stat.h>
21 +#include <linux/ip.h>
22 +#include <linux/tcp.h>
23  #include <linux/if_bridge.h>
24  #include <linux/if_macvlan.h>
25  #include <net/dst.h>
26 @@ -2275,6 +2277,10 @@ void netif_nit_deliver(struct sk_buff *skb)
27         rcu_read_unlock();
28  }
29  
30 +/* The code already makes the assumption that packet handlers run
31 + * sequentially on the same CPU. -Sapan */
32 +DEFINE_PER_CPU(int, sknid_elevator) = 0;
33 +
34  /**
35   *     netif_receive_skb - process receive buffer from network
36   *     @skb: buffer to process
37 @@ -2296,8 +2302,11 @@ int netif_receive_skb(struct sk_buff *skb)
38         struct net_device *orig_dev;
39         struct net_device *null_or_orig;
40         int ret = NET_RX_DROP;
41 +       int *cur_elevator = &__get_cpu_var(sknid_elevator);
42         __be16 type;
43  
44 +       *cur_elevator = 0;
45 +
46         if (!skb->tstamp.tv64)
47                 net_timestamp(skb);
48  
49 @@ -2373,7 +2382,27 @@ ncls:
50         }
51  
52         if (pt_prev) {
53 +               /* At this point, cur_elevator may be -2 or a positive value, in
54 +                * case a previous protocol handler marked it */
55 +               if (*cur_elevator) {
56 +                       atomic_inc(&skb->users);
57 +               }
58 +               
59                 ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
60 +
61 +               if ((*cur_elevator)>0) {
62 +                       skb->skb_tag = *cur_elevator;
63 +                       list_for_each_entry_rcu(ptype, &ptype_all, list) {
64 +                               if ((!ptype->dev || ptype->dev == skb->dev) && (ptype->sknid_elevator)) {
65 +                                       ret = deliver_skb(skb, ptype, orig_dev);
66 +                               }
67 +                       }
68 +               }
69 +
70 +               if (*cur_elevator) {
71 +                       /* We have a packet */
72 +                       kfree_skb(skb);
73 +               }
74         } else {
75                 kfree_skb(skb);
76                 /* Jamal, now you will not able to escape explaining
77 @@ -4127,6 +4156,7 @@ unsigned dev_get_flags(const struct net_device *dev)
78         return flags;
79  }
80  EXPORT_SYMBOL(dev_get_flags);
81 +EXPORT_PER_CPU_SYMBOL(sknid_elevator);
82  
83  /**
84   *     dev_change_flags - change device settings
85 diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
86 index 1bd109e..5c2e9ad 100644
87 --- a/net/packet/af_packet.c
88 +++ b/net/packet/af_packet.c
89 @@ -78,6 +78,7 @@
90  #include <linux/poll.h>
91  #include <linux/module.h>
92  #include <linux/init.h>
93 +#include <linux/vs_network.h>
94  #include <linux/mutex.h>
95  
96  #ifdef CONFIG_INET
97 @@ -337,12 +338,54 @@ static const struct proto_ops packet_ops;
98  
99  static const struct proto_ops packet_ops_spkt;
100  
101 +DECLARE_PER_CPU(int, sknid_elevator);
102 +
103 +static inline unsigned int slice_check_and_elevate(struct sk_buff *skb, struct sock *sk) {
104 +       /* This mechanism is quite involved, and caused us a lot of pain
105 +        * including crashes and packet loss during the 4.2 rollout. This
106 +        * function decides if a slice is allowed to see a given packet.
107 +        * Unfortunately, the first time it is invoked for a packet it does not
108 +        * have enough information to make this call, since xt_MARK has not had
109 +        * a chance to tag it with the slice id.  There is also no way of
110 +        * passing state between xt_MARK and this function through a packet --
111 +        * because the skb gets cloned quite a few times between these two
112 +        * points.  I'd rather not use skb_shared_info because it's treated as
113 +        * a blob of memory, and so it would be quite hard to maintain.
114 +        *
115 +        * What we do is to keep a global variable (per CPU) that transfers the
116 +        * required state between xt_MARK and af_packet.c. As an optimization,
117 +        * this state transfer and the step that follows is only executed for
118 +        * packets that first get dropped here. When we drop a packet, we mark
119 +        * it for 'elevation' (that's what this trick is called). When xt_MARK
120 +        * tags the packet with the right slice, it intercepts this mark and
121 +        * sets the value of sknid_elevator. Next, the packet is sent back here
122 +        * for a second round, this time with the xid tag set.
123 +        */
124 +
125 +       int *elevator=&__get_cpu_var(sknid_elevator);
126 +       int tag = skb->skb_tag;
127 +
128 +       if (sk->sk_nx_info && !(tag == 1 || sk->sk_nid == tag)) {
129 +               if (skb->pkt_type==PACKET_HOST) {
130 +                       *elevator=-2; /* Rejecting this packet. Mark it for elevation in xt_MARK */
131 +               }
132 +               return 0;
133 +       }
134 +       else if (!sk->sk_nx_info && (*elevator>0)) {
135 +               /* Root has already seen this packet once, since it has been elevated */
136 +               return 0;
137 +       }
138 +
139 +       return 1;
140 +}
141 +
142  static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
143                            struct packet_type *pt, struct net_device *orig_dev)
144  {
145         struct sock *sk;
146         struct sockaddr_pkt *spkt;
147 -
148 +       int tag = skb->skb_tag;
149 +       
150         /*
151          *      When we registered the protocol we saved the socket in the data
152          *      field for just this event.
153 @@ -361,6 +404,16 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
154          *      so that this procedure is noop.
155          */
156  
157 +       /* 
158 +        * (18:05:41) daniel_hozac: where?
159 +        * (18:05:58) daniel_hozac: we already have filters on PF_PACKET, don't we?
160 +        * (18:05:58) er: in packet_rcv_skpt
161 +        * (18:07:33) daniel_hozac: oh, that's evil. 
162 +        */
163 +
164 +       if (!slice_check_and_elevate(skb, sk))
165 +               return 0;
166 +
167         if (skb->pkt_type == PACKET_LOOPBACK)
168                 goto out;
169  
170 @@ -419,6 +472,9 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
171         __be16 proto = 0;
172         int err;
173  
174 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SEND))
175 +               return -EPERM;
176 +
177         /*
178          *      Get and verify the address.
179          */
180 @@ -509,11 +565,16 @@ out_unlock:
181         return err;
182  }
183  
184 +
185 +
186  static inline unsigned int run_filter(struct sk_buff *skb, struct sock *sk,
187                                       unsigned int res)
188  {
189         struct sk_filter *filter;
190  
191 +       if (!slice_check_and_elevate(skb, sk)) 
192 +               return 0;
193 +
194         rcu_read_lock_bh();
195         filter = rcu_dereference(sk->sk_filter);
196         if (filter != NULL)
197 @@ -1063,6 +1124,9 @@ static int packet_snd(struct socket *sock,
198         unsigned char *addr;
199         int ifindex, err, reserve = 0;
200  
201 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SEND)) 
202 +               return -EPERM;
203 +
204         /*
205          *      Get and verify the address.
206          */
207 @@ -1248,6 +1312,7 @@ static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 protoc
208  
209         po->num = protocol;
210         po->prot_hook.type = protocol;
211 +       po->prot_hook.sknid_elevator = 1;
212         po->prot_hook.dev = dev;
213  
214         po->ifindex = dev ? dev->ifindex : 0;
215 @@ -1348,8 +1413,9 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
216         __be16 proto = (__force __be16)protocol; /* weird, but documented */
217         int err;
218  
219 -       if (!capable(CAP_NET_RAW))
220 +       if (!nx_capable(CAP_NET_RAW, NXC_RAW_SOCKET))
221                 return -EPERM;
222 +               
223         if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
224             sock->type != SOCK_PACKET)
225                 return -ESOCKTNOSUPPORT;
226 @@ -1381,6 +1447,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
227         spin_lock_init(&po->bind_lock);
228         mutex_init(&po->pg_vec_lock);
229         po->prot_hook.func = packet_rcv;
230 +       po->prot_hook.sknid_elevator = 1;
231  
232         if (sock->type == SOCK_PACKET)
233                 po->prot_hook.func = packet_rcv_spkt;