diff options
-rw-r--r-- | include/net/inet_frag.h | 1 | ||||
-rw-r--r-- | include/net/ip.h | 1 | ||||
-rw-r--r-- | include/net/ipv6.h | 9 | ||||
-rw-r--r-- | net/ipv4/inet_fragment.c | 32 | ||||
-rw-r--r-- | net/ipv4/ip_fragment.c | 30 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_conntrack_reasm.c | 29 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 30 |
7 files changed, 52 insertions, 80 deletions
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 2dd1cd4e7f44..cf583cf7e9ef 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h | |||
@@ -49,5 +49,6 @@ void inet_frags_fini(struct inet_frags *); | |||
49 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); | 49 | void inet_frag_kill(struct inet_frag_queue *q, struct inet_frags *f); |
50 | void inet_frag_destroy(struct inet_frag_queue *q, | 50 | void inet_frag_destroy(struct inet_frag_queue *q, |
51 | struct inet_frags *f, int *work); | 51 | struct inet_frags *f, int *work); |
52 | int inet_frag_evictor(struct inet_frags *f); | ||
52 | 53 | ||
53 | #endif | 54 | #endif |
diff --git a/include/net/ip.h b/include/net/ip.h index e6aa955e241c..840dd91b513b 100644 --- a/include/net/ip.h +++ b/include/net/ip.h | |||
@@ -160,6 +160,7 @@ DECLARE_SNMP_STAT(struct ipstats_mib, ip_statistics); | |||
160 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) | 160 | #define IP_INC_STATS(field) SNMP_INC_STATS(ip_statistics, field) |
161 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) | 161 | #define IP_INC_STATS_BH(field) SNMP_INC_STATS_BH(ip_statistics, field) |
162 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) | 162 | #define IP_INC_STATS_USER(field) SNMP_INC_STATS_USER(ip_statistics, field) |
163 | #define IP_ADD_STATS_BH(field, val) SNMP_ADD_STATS_BH(ip_statistics, field, val) | ||
163 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); | 164 | DECLARE_SNMP_STAT(struct linux_mib, net_statistics); |
164 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) | 165 | #define NET_INC_STATS(field) SNMP_INC_STATS(net_statistics, field) |
165 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) | 166 | #define NET_INC_STATS_BH(field) SNMP_INC_STATS_BH(net_statistics, field) |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index b29d76c715d2..a0f1042037f2 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -120,12 +120,21 @@ extern int sysctl_mld_max_msf; | |||
120 | SNMP_INC_STATS##modifier(statname##_statistics, (field)); \ | 120 | SNMP_INC_STATS##modifier(statname##_statistics, (field)); \ |
121 | }) | 121 | }) |
122 | 122 | ||
123 | #define _DEVADD(statname, modifier, idev, field, val) \ | ||
124 | ({ \ | ||
125 | struct inet6_dev *_idev = (idev); \ | ||
126 | if (likely(_idev != NULL)) \ | ||
127 | SNMP_ADD_STATS##modifier((_idev)->stats.statname, (field), (val)); \ | ||
128 | SNMP_ADD_STATS##modifier(statname##_statistics, (field), (val));\ | ||
129 | }) | ||
130 | |||
123 | /* MIBs */ | 131 | /* MIBs */ |
124 | DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); | 132 | DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); |
125 | 133 | ||
126 | #define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field) | 134 | #define IP6_INC_STATS(idev,field) _DEVINC(ipv6, , idev, field) |
127 | #define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field) | 135 | #define IP6_INC_STATS_BH(idev,field) _DEVINC(ipv6, _BH, idev, field) |
128 | #define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field) | 136 | #define IP6_INC_STATS_USER(idev,field) _DEVINC(ipv6, _USER, idev, field) |
137 | #define IP6_ADD_STATS_BH(idev,field,val) _DEVADD(ipv6, _BH, idev, field, val) | ||
129 | 138 | ||
130 | DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); | 139 | DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); |
131 | DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics); | 140 | DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics); |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 15fb2c4a36a7..484cf512858f 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -140,3 +140,35 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | |||
140 | 140 | ||
141 | } | 141 | } |
142 | EXPORT_SYMBOL(inet_frag_destroy); | 142 | EXPORT_SYMBOL(inet_frag_destroy); |
143 | |||
144 | int inet_frag_evictor(struct inet_frags *f) | ||
145 | { | ||
146 | struct inet_frag_queue *q; | ||
147 | int work, evicted = 0; | ||
148 | |||
149 | work = atomic_read(&f->mem) - f->ctl->low_thresh; | ||
150 | while (work > 0) { | ||
151 | read_lock(&f->lock); | ||
152 | if (list_empty(&f->lru_list)) { | ||
153 | read_unlock(&f->lock); | ||
154 | break; | ||
155 | } | ||
156 | |||
157 | q = list_first_entry(&f->lru_list, | ||
158 | struct inet_frag_queue, lru_list); | ||
159 | atomic_inc(&q->refcnt); | ||
160 | read_unlock(&f->lock); | ||
161 | |||
162 | spin_lock(&q->lock); | ||
163 | if (!(q->last_in & COMPLETE)) | ||
164 | inet_frag_kill(q, f); | ||
165 | spin_unlock(&q->lock); | ||
166 | |||
167 | if (atomic_dec_and_test(&q->refcnt)) | ||
168 | inet_frag_destroy(q, f, &work); | ||
169 | evicted++; | ||
170 | } | ||
171 | |||
172 | return evicted; | ||
173 | } | ||
174 | EXPORT_SYMBOL(inet_frag_evictor); | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index e8736632094a..ee6e04159627 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -174,33 +174,11 @@ static void ipq_kill(struct ipq *ipq) | |||
174 | */ | 174 | */ |
175 | static void ip_evictor(void) | 175 | static void ip_evictor(void) |
176 | { | 176 | { |
177 | struct ipq *qp; | 177 | int evicted; |
178 | struct list_head *tmp; | ||
179 | int work; | ||
180 | |||
181 | work = atomic_read(&ip4_frags.mem) - ip4_frags_ctl.low_thresh; | ||
182 | if (work <= 0) | ||
183 | return; | ||
184 | |||
185 | while (work > 0) { | ||
186 | read_lock(&ip4_frags.lock); | ||
187 | if (list_empty(&ip4_frags.lru_list)) { | ||
188 | read_unlock(&ip4_frags.lock); | ||
189 | return; | ||
190 | } | ||
191 | tmp = ip4_frags.lru_list.next; | ||
192 | qp = list_entry(tmp, struct ipq, q.lru_list); | ||
193 | atomic_inc(&qp->q.refcnt); | ||
194 | read_unlock(&ip4_frags.lock); | ||
195 | 178 | ||
196 | spin_lock(&qp->q.lock); | 179 | evicted = inet_frag_evictor(&ip4_frags); |
197 | if (!(qp->q.last_in&COMPLETE)) | 180 | if (evicted) |
198 | ipq_kill(qp); | 181 | IP_ADD_STATS_BH(IPSTATS_MIB_REASMFAILS, evicted); |
199 | spin_unlock(&qp->q.lock); | ||
200 | |||
201 | ipq_put(qp, &work); | ||
202 | IP_INC_STATS_BH(IPSTATS_MIB_REASMFAILS); | ||
203 | } | ||
204 | } | 182 | } |
205 | 183 | ||
206 | /* | 184 | /* |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 785f5cda188e..e4fbe5ba88f1 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -163,34 +163,7 @@ static __inline__ void fq_kill(struct nf_ct_frag6_queue *fq) | |||
163 | 163 | ||
164 | static void nf_ct_frag6_evictor(void) | 164 | static void nf_ct_frag6_evictor(void) |
165 | { | 165 | { |
166 | struct nf_ct_frag6_queue *fq; | 166 | inet_frag_evictor(&nf_frags); |
167 | struct list_head *tmp; | ||
168 | unsigned int work; | ||
169 | |||
170 | work = atomic_read(&nf_frags.mem); | ||
171 | if (work <= nf_frags_ctl.low_thresh) | ||
172 | return; | ||
173 | |||
174 | work -= nf_frags_ctl.low_thresh; | ||
175 | while (work > 0) { | ||
176 | read_lock(&nf_frags.lock); | ||
177 | if (list_empty(&nf_frags.lru_list)) { | ||
178 | read_unlock(&nf_frags.lock); | ||
179 | return; | ||
180 | } | ||
181 | tmp = nf_frags.lru_list.next; | ||
182 | BUG_ON(tmp == NULL); | ||
183 | fq = list_entry(tmp, struct nf_ct_frag6_queue, q.lru_list); | ||
184 | atomic_inc(&fq->q.refcnt); | ||
185 | read_unlock(&nf_frags.lock); | ||
186 | |||
187 | spin_lock(&fq->q.lock); | ||
188 | if (!(fq->q.last_in&COMPLETE)) | ||
189 | fq_kill(fq); | ||
190 | spin_unlock(&fq->q.lock); | ||
191 | |||
192 | fq_put(fq, &work); | ||
193 | } | ||
194 | } | 167 | } |
195 | 168 | ||
196 | static void nf_ct_frag6_expire(unsigned long data) | 169 | static void nf_ct_frag6_expire(unsigned long data) |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 940b7d2383ec..02e4e855b927 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -185,33 +185,11 @@ static __inline__ void fq_kill(struct frag_queue *fq) | |||
185 | 185 | ||
186 | static void ip6_evictor(struct inet6_dev *idev) | 186 | static void ip6_evictor(struct inet6_dev *idev) |
187 | { | 187 | { |
188 | struct frag_queue *fq; | 188 | int evicted; |
189 | struct list_head *tmp; | ||
190 | int work; | ||
191 | |||
192 | work = atomic_read(&ip6_frags.mem) - ip6_frags_ctl.low_thresh; | ||
193 | if (work <= 0) | ||
194 | return; | ||
195 | |||
196 | while(work > 0) { | ||
197 | read_lock(&ip6_frags.lock); | ||
198 | if (list_empty(&ip6_frags.lru_list)) { | ||
199 | read_unlock(&ip6_frags.lock); | ||
200 | return; | ||
201 | } | ||
202 | tmp = ip6_frags.lru_list.next; | ||
203 | fq = list_entry(tmp, struct frag_queue, q.lru_list); | ||
204 | atomic_inc(&fq->q.refcnt); | ||
205 | read_unlock(&ip6_frags.lock); | ||
206 | 189 | ||
207 | spin_lock(&fq->q.lock); | 190 | evicted = inet_frag_evictor(&ip6_frags); |
208 | if (!(fq->q.last_in&COMPLETE)) | 191 | if (evicted) |
209 | fq_kill(fq); | 192 | IP6_ADD_STATS_BH(idev, IPSTATS_MIB_REASMFAILS, evicted); |
210 | spin_unlock(&fq->q.lock); | ||
211 | |||
212 | fq_put(fq, &work); | ||
213 | IP6_INC_STATS_BH(idev, IPSTATS_MIB_REASMFAILS); | ||
214 | } | ||
215 | } | 193 | } |
216 | 194 | ||
217 | static void ip6_frag_expire(unsigned long data) | 195 | static void ip6_frag_expire(unsigned long data) |