Lines 73-78
Link Here
|
73 |
struct ipq { |
73 |
struct ipq { |
74 |
struct ipq *next; /* linked list pointers */ |
74 |
struct ipq *next; /* linked list pointers */ |
75 |
struct list_head lru_list; /* lru list member */ |
75 |
struct list_head lru_list; /* lru list member */ |
|
|
76 |
u32 user; |
76 |
u32 saddr; |
77 |
u32 saddr; |
77 |
u32 daddr; |
78 |
u32 daddr; |
78 |
u16 id; |
79 |
u16 id; |
Lines 243-255
Link Here
|
243 |
/* Memory limiting on fragments. Evictor trashes the oldest |
244 |
/* Memory limiting on fragments. Evictor trashes the oldest |
244 |
* fragment queue until we are back under the threshold. |
245 |
* fragment queue until we are back under the threshold. |
245 |
*/ |
246 |
*/ |
246 |
static void __ip_evictor(int threshold) |
247 |
static void ip_evictor(void) |
247 |
{ |
248 |
{ |
248 |
struct ipq *qp; |
249 |
struct ipq *qp; |
249 |
struct list_head *tmp; |
250 |
struct list_head *tmp; |
250 |
int work; |
251 |
int work; |
251 |
|
252 |
|
252 |
work = atomic_read(&ip_frag_mem) - threshold; |
253 |
work = atomic_read(&ip_frag_mem) - sysctl_ipfrag_low_thresh; |
253 |
if (work <= 0) |
254 |
if (work <= 0) |
254 |
return; |
255 |
return; |
255 |
|
256 |
|
Lines 274-284
Link Here
|
274 |
} |
275 |
} |
275 |
} |
276 |
} |
276 |
|
277 |
|
277 |
static inline void ip_evictor(void) |
|
|
278 |
{ |
279 |
__ip_evictor(sysctl_ipfrag_low_thresh); |
280 |
} |
281 |
|
282 |
/* |
278 |
/* |
283 |
* Oops, a fragment queue timed out. Kill it and send an ICMP reply. |
279 |
* Oops, a fragment queue timed out. Kill it and send an ICMP reply. |
284 |
*/ |
280 |
*/ |
Lines 325-331
Link Here
|
325 |
if(qp->id == qp_in->id && |
321 |
if(qp->id == qp_in->id && |
326 |
qp->saddr == qp_in->saddr && |
322 |
qp->saddr == qp_in->saddr && |
327 |
qp->daddr == qp_in->daddr && |
323 |
qp->daddr == qp_in->daddr && |
328 |
qp->protocol == qp_in->protocol) { |
324 |
qp->protocol == qp_in->protocol && |
|
|
325 |
qp->user == qp_in->user) { |
329 |
atomic_inc(&qp->refcnt); |
326 |
atomic_inc(&qp->refcnt); |
330 |
write_unlock(&ipfrag_lock); |
327 |
write_unlock(&ipfrag_lock); |
331 |
qp_in->last_in |= COMPLETE; |
328 |
qp_in->last_in |= COMPLETE; |
Lines 352-358
Link Here
|
352 |
} |
349 |
} |
353 |
|
350 |
|
354 |
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ |
351 |
/* Add an entry to the 'ipq' queue for a newly received IP datagram. */ |
355 |
static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph) |
352 |
static struct ipq *ip_frag_create(unsigned hash, struct iphdr *iph, u32 user) |
356 |
{ |
353 |
{ |
357 |
struct ipq *qp; |
354 |
struct ipq *qp; |
358 |
|
355 |
|
Lines 364-369
Link Here
|
364 |
qp->id = iph->id; |
361 |
qp->id = iph->id; |
365 |
qp->saddr = iph->saddr; |
362 |
qp->saddr = iph->saddr; |
366 |
qp->daddr = iph->daddr; |
363 |
qp->daddr = iph->daddr; |
|
|
364 |
qp->user = user; |
367 |
qp->len = 0; |
365 |
qp->len = 0; |
368 |
qp->meat = 0; |
366 |
qp->meat = 0; |
369 |
qp->fragments = NULL; |
367 |
qp->fragments = NULL; |
Lines 386-392
Link Here
|
386 |
/* Find the correct entry in the "incomplete datagrams" queue for |
384 |
/* Find the correct entry in the "incomplete datagrams" queue for |
387 |
* this IP datagram, and create new one, if nothing is found. |
385 |
* this IP datagram, and create new one, if nothing is found. |
388 |
*/ |
386 |
*/ |
389 |
static inline struct ipq *ip_find(struct iphdr *iph) |
387 |
static inline struct ipq *ip_find(struct iphdr *iph, u32 user) |
390 |
{ |
388 |
{ |
391 |
__u16 id = iph->id; |
389 |
__u16 id = iph->id; |
392 |
__u32 saddr = iph->saddr; |
390 |
__u32 saddr = iph->saddr; |
Lines 400-406
Link Here
|
400 |
if(qp->id == id && |
398 |
if(qp->id == id && |
401 |
qp->saddr == saddr && |
399 |
qp->saddr == saddr && |
402 |
qp->daddr == daddr && |
400 |
qp->daddr == daddr && |
403 |
qp->protocol == protocol) { |
401 |
qp->protocol == protocol && |
|
|
402 |
qp->user == user) { |
404 |
atomic_inc(&qp->refcnt); |
403 |
atomic_inc(&qp->refcnt); |
405 |
read_unlock(&ipfrag_lock); |
404 |
read_unlock(&ipfrag_lock); |
406 |
return qp; |
405 |
return qp; |
Lines 408-414
Link Here
|
408 |
} |
407 |
} |
409 |
read_unlock(&ipfrag_lock); |
408 |
read_unlock(&ipfrag_lock); |
410 |
|
409 |
|
411 |
return ip_frag_create(hash, iph); |
410 |
return ip_frag_create(hash, iph, user); |
412 |
} |
411 |
} |
413 |
|
412 |
|
414 |
/* Add new segment to existing queue. */ |
413 |
/* Add new segment to existing queue. */ |
Lines 642-648
Link Here
|
642 |
} |
641 |
} |
643 |
|
642 |
|
644 |
/* Process an incoming IP datagram fragment. */ |
643 |
/* Process an incoming IP datagram fragment. */ |
645 |
struct sk_buff *ip_defrag(struct sk_buff *skb) |
644 |
struct sk_buff *ip_defrag(struct sk_buff *skb, u32 user) |
646 |
{ |
645 |
{ |
647 |
struct iphdr *iph = skb->nh.iph; |
646 |
struct iphdr *iph = skb->nh.iph; |
648 |
struct ipq *qp; |
647 |
struct ipq *qp; |
Lines 657-663
Link Here
|
657 |
dev = skb->dev; |
656 |
dev = skb->dev; |
658 |
|
657 |
|
659 |
/* Lookup (or create) queue header */ |
658 |
/* Lookup (or create) queue header */ |
660 |
if ((qp = ip_find(iph)) != NULL) { |
659 |
if ((qp = ip_find(iph, user)) != NULL) { |
661 |
struct sk_buff *ret = NULL; |
660 |
struct sk_buff *ret = NULL; |
662 |
|
661 |
|
663 |
spin_lock(&qp->lock); |
662 |
spin_lock(&qp->lock); |
Lines 689-698
Link Here
|
689 |
add_timer(&ipfrag_secret_timer); |
688 |
add_timer(&ipfrag_secret_timer); |
690 |
} |
689 |
} |
691 |
|
690 |
|
692 |
void ipfrag_flush(void) |
|
|
693 |
{ |
694 |
__ip_evictor(0); |
695 |
} |
696 |
|
697 |
EXPORT_SYMBOL(ip_defrag); |
691 |
EXPORT_SYMBOL(ip_defrag); |
698 |
EXPORT_SYMBOL(ipfrag_flush); |
|
|