aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/reassembly.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/reassembly.c')
-rw-r--r--net/ipv6/reassembly.c89
1 files changed, 24 insertions, 65 deletions
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 4ff9af628e72..da8a4e301b1b 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -65,36 +65,8 @@ struct ip6frag_skb_cb
65#define FRAG6_CB(skb) ((struct ip6frag_skb_cb*)((skb)->cb)) 65#define FRAG6_CB(skb) ((struct ip6frag_skb_cb*)((skb)->cb))
66 66
67 67
68/*
69 * Equivalent of ipv4 struct ipq
70 */
71
72struct frag_queue
73{
74 struct inet_frag_queue q;
75
76 __be32 id; /* fragment id */
77 u32 user;
78 struct in6_addr saddr;
79 struct in6_addr daddr;
80
81 int iif;
82 unsigned int csum;
83 __u16 nhoffset;
84};
85
86static struct inet_frags ip6_frags; 68static struct inet_frags ip6_frags;
87 69
88int ip6_frag_nqueues(struct net *net)
89{
90 return net->ipv6.frags.nqueues;
91}
92
93int ip6_frag_mem(struct net *net)
94{
95 return atomic_read(&net->ipv6.frags.mem);
96}
97
98static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, 70static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
99 struct net_device *dev); 71 struct net_device *dev);
100 72
@@ -159,46 +131,18 @@ void ip6_frag_init(struct inet_frag_queue *q, void *a)
159} 131}
160EXPORT_SYMBOL(ip6_frag_init); 132EXPORT_SYMBOL(ip6_frag_init);
161 133
162/* Destruction primitives. */ 134void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq,
163 135 struct inet_frags *frags)
164static __inline__ void fq_put(struct frag_queue *fq)
165{
166 inet_frag_put(&fq->q, &ip6_frags);
167}
168
169/* Kill fq entry. It is not destroyed immediately,
170 * because caller (and someone more) holds reference count.
171 */
172static __inline__ void fq_kill(struct frag_queue *fq)
173{
174 inet_frag_kill(&fq->q, &ip6_frags);
175}
176
177static void ip6_evictor(struct net *net, struct inet6_dev *idev)
178{ 136{
179 int evicted;
180
181 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags);
182 if (evicted)
183 IP6_ADD_STATS_BH(net, idev, IPSTATS_MIB_REASMFAILS, evicted);
184}
185
186static void ip6_frag_expire(unsigned long data)
187{
188 struct frag_queue *fq;
189 struct net_device *dev = NULL; 137 struct net_device *dev = NULL;
190 struct net *net;
191
192 fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
193 138
194 spin_lock(&fq->q.lock); 139 spin_lock(&fq->q.lock);
195 140
196 if (fq->q.last_in & INET_FRAG_COMPLETE) 141 if (fq->q.last_in & INET_FRAG_COMPLETE)
197 goto out; 142 goto out;
198 143
199 fq_kill(fq); 144 inet_frag_kill(&fq->q, frags);
200 145
201 net = container_of(fq->q.net, struct net, ipv6.frags);
202 rcu_read_lock(); 146 rcu_read_lock();
203 dev = dev_get_by_index_rcu(net, fq->iif); 147 dev = dev_get_by_index_rcu(net, fq->iif);
204 if (!dev) 148 if (!dev)
@@ -222,7 +166,19 @@ out_rcu_unlock:
222 rcu_read_unlock(); 166 rcu_read_unlock();
223out: 167out:
224 spin_unlock(&fq->q.lock); 168 spin_unlock(&fq->q.lock);
225 fq_put(fq); 169 inet_frag_put(&fq->q, frags);
170}
171EXPORT_SYMBOL(ip6_expire_frag_queue);
172
173static void ip6_frag_expire(unsigned long data)
174{
175 struct frag_queue *fq;
176 struct net *net;
177
178 fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
179 net = container_of(fq->q.net, struct net, ipv6.frags);
180
181 ip6_expire_frag_queue(net, fq, &ip6_frags);
226} 182}
227 183
228static __inline__ struct frag_queue * 184static __inline__ struct frag_queue *
@@ -391,7 +347,7 @@ found:
391 return -1; 347 return -1;
392 348
393discard_fq: 349discard_fq:
394 fq_kill(fq); 350 inet_frag_kill(&fq->q, &ip6_frags);
395err: 351err:
396 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), 352 IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
397 IPSTATS_MIB_REASMFAILS); 353 IPSTATS_MIB_REASMFAILS);
@@ -417,7 +373,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
417 unsigned int nhoff; 373 unsigned int nhoff;
418 int sum_truesize; 374 int sum_truesize;
419 375
420 fq_kill(fq); 376 inet_frag_kill(&fq->q, &ip6_frags);
421 377
422 /* Make the one we just received the head. */ 378 /* Make the one we just received the head. */
423 if (prev) { 379 if (prev) {
@@ -550,6 +506,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
550 struct frag_queue *fq; 506 struct frag_queue *fq;
551 const struct ipv6hdr *hdr = ipv6_hdr(skb); 507 const struct ipv6hdr *hdr = ipv6_hdr(skb);
552 struct net *net = dev_net(skb_dst(skb)->dev); 508 struct net *net = dev_net(skb_dst(skb)->dev);
509 int evicted;
553 510
554 IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); 511 IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS);
555 512
@@ -574,8 +531,10 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
574 return 1; 531 return 1;
575 } 532 }
576 533
577 if (atomic_read(&net->ipv6.frags.mem) > net->ipv6.frags.high_thresh) 534 evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false);
578 ip6_evictor(net, ip6_dst_idev(skb_dst(skb))); 535 if (evicted)
536 IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)),
537 IPSTATS_MIB_REASMFAILS, evicted);
579 538
580 fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr); 539 fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr);
581 if (fq != NULL) { 540 if (fq != NULL) {
@@ -586,7 +545,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
586 ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff); 545 ret = ip6_frag_queue(fq, skb, fhdr, IP6CB(skb)->nhoff);
587 546
588 spin_unlock(&fq->q.lock); 547 spin_unlock(&fq->q.lock);
589 fq_put(fq); 548 inet_frag_put(&fq->q, &ip6_frags);
590 return ret; 549 return ret;
591 } 550 }
592 551