Blame view

net/atm/mpoa_caches.c 14.3 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
  #include <linux/types.h>
  #include <linux/atmmpc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
4
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
7
8
9
10
11
12
13
14
15
  #include <linux/time.h>
  
  #include "mpoa_caches.h"
  #include "mpc.h"
  
  /*
   * mpoa_caches.c: Implementation of ingress and egress cache
   * handling functions
   */
  
  #if 0
b50c2ea72   Joe Perches   net/atm: Cleanup ...
16
17
  #define dprintk(format, args...)					\
  	printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args)  /* debug */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #else
b50c2ea72   Joe Perches   net/atm: Cleanup ...
19
20
21
22
  #define dprintk(format, args...)					\
  	do { if (0)							\
  		printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
  	} while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
  #endif
  
  #if 0
b50c2ea72   Joe Perches   net/atm: Cleanup ...
26
27
  #define ddprintk(format, args...)					\
  	printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args)  /* debug */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
  #else
b50c2ea72   Joe Perches   net/atm: Cleanup ...
29
30
31
32
  #define ddprintk(format, args...)					\
  	do { if (0)							\
  		printk(KERN_DEBUG "mpoa:%s: " format, __FILE__, ##args);\
  	} while (0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  #endif
30d492da7   Al Viro   [ATM]: Annotations.
34
  static in_cache_entry *in_cache_get(__be32 dst_ip,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
  				    struct mpoa_client *client)
  {
  	in_cache_entry *entry;
  
  	read_lock_bh(&client->ingress_lock);
  	entry = client->in_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
41
42
  	while (entry != NULL) {
  		if (entry->ctrl_info.in_dst_ip == dst_ip) {
937149125   Reshetova, Elena   net, atm: convert...
43
  			refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
45
46
47
48
49
50
51
52
  			read_unlock_bh(&client->ingress_lock);
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_bh(&client->ingress_lock);
  
  	return NULL;
  }
30d492da7   Al Viro   [ATM]: Annotations.
53
  static in_cache_entry *in_cache_get_with_mask(__be32 dst_ip,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  					      struct mpoa_client *client,
30d492da7   Al Viro   [ATM]: Annotations.
55
  					      __be32 mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  {
  	in_cache_entry *entry;
  
  	read_lock_bh(&client->ingress_lock);
  	entry = client->in_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
61
62
  	while (entry != NULL) {
  		if ((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask)) {
937149125   Reshetova, Elena   net, atm: convert...
63
  			refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
65
66
67
68
69
70
71
72
73
74
75
  			read_unlock_bh(&client->ingress_lock);
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_bh(&client->ingress_lock);
  
  	return NULL;
  
  }
  
  static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
bee67d34b   Joe Perches   net/atm/mpoa_cach...
76
  					   struct mpoa_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
  {
  	in_cache_entry *entry;
  
  	read_lock_bh(&client->ingress_lock);
  	entry = client->in_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
82
83
  	while (entry != NULL) {
  		if (entry->shortcut == vcc) {
937149125   Reshetova, Elena   net, atm: convert...
84
  			refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
88
89
90
91
92
93
  			read_unlock_bh(&client->ingress_lock);
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_bh(&client->ingress_lock);
  
  	return NULL;
  }
30d492da7   Al Viro   [ATM]: Annotations.
94
  static in_cache_entry *in_cache_add_entry(__be32 dst_ip,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
  					  struct mpoa_client *client)
  {
2afe37cdf   Arnaldo Carvalho de Melo   [ATM]: Use kmemdu...
97
  	in_cache_entry *entry = kzalloc(sizeof(in_cache_entry), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
  
  	if (entry == NULL) {
bee67d34b   Joe Perches   net/atm/mpoa_cach...
100
101
  		pr_info("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  		return NULL;
  	}
b50c2ea72   Joe Perches   net/atm: Cleanup ...
104
105
  	dprintk("adding an ingress entry, ip = %pI4
  ", &dst_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106

937149125   Reshetova, Elena   net, atm: convert...
107
  	refcount_set(&entry->use, 1);
b50c2ea72   Joe Perches   net/atm: Cleanup ...
108
109
  	dprintk("new_in_cache_entry: about to lock
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  	write_lock_bh(&client->ingress_lock);
  	entry->next = client->in_cache;
  	entry->prev = NULL;
  	if (client->in_cache != NULL)
  		client->in_cache->prev = entry;
  	client->in_cache = entry;
  
  	memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
  	entry->ctrl_info.in_dst_ip = dst_ip;
  	do_gettimeofday(&(entry->tv));
  	entry->retry_time = client->parameters.mpc_p4;
  	entry->count = 1;
  	entry->entry_state = INGRESS_INVALID;
  	entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
937149125   Reshetova, Elena   net, atm: convert...
124
  	refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
  
  	write_unlock_bh(&client->ingress_lock);
b50c2ea72   Joe Perches   net/atm: Cleanup ...
127
128
  	dprintk("new_in_cache_entry: unlocked
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
132
133
134
135
136
137
138
  
  	return entry;
  }
  
  static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
  {
  	struct atm_mpoa_qos *qos;
  	struct k_message msg;
  
  	entry->count++;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
139
  	if (entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  		return OPEN;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
141
142
  	if (entry->entry_state == INGRESS_REFRESHING) {
  		if (entry->count > mpc->parameters.mpc_p1) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
146
  			msg.type = SND_MPOA_RES_RQST;
  			msg.content.in_info = entry->ctrl_info;
  			memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
  			qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
147
148
  			if (qos != NULL)
  				msg.qos = qos->qos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
152
  			msg_to_mpoad(&msg, mpc);
  			do_gettimeofday(&(entry->reply_wait));
  			entry->entry_state = INGRESS_RESOLVING;
  		}
bee67d34b   Joe Perches   net/atm/mpoa_cach...
153
  		if (entry->shortcut != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
  			return OPEN;
  		return CLOSED;
  	}
bee67d34b   Joe Perches   net/atm/mpoa_cach...
157
  	if (entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
  		return OPEN;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
159
160
  	if (entry->count > mpc->parameters.mpc_p1 &&
  	    entry->entry_state == INGRESS_INVALID) {
b50c2ea72   Joe Perches   net/atm: Cleanup ...
161
162
  		dprintk("(%s) threshold exceeded for ip %pI4, sending MPOA res req
  ",
21454aaad   Harvey Harrison   net: replace NIPQ...
163
  			mpc->dev->name, &entry->ctrl_info.in_dst_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  		entry->entry_state = INGRESS_RESOLVING;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
165
166
  		msg.type = SND_MPOA_RES_RQST;
  		memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
168
  		msg.content.in_info = entry->ctrl_info;
  		qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
169
170
171
  		if (qos != NULL)
  			msg.qos = qos->qos;
  		msg_to_mpoad(&msg, mpc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
175
176
177
178
179
  		do_gettimeofday(&(entry->reply_wait));
  	}
  
  	return CLOSED;
  }
  
  static void in_cache_put(in_cache_entry *entry)
  {
937149125   Reshetova, Elena   net, atm: convert...
180
  	if (refcount_dec_and_test(&entry->use)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
  		memset(entry, 0, sizeof(in_cache_entry));
  		kfree(entry);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
  }
  
  /*
   * This should be called with write lock on
   */
  static void in_cache_remove_entry(in_cache_entry *entry,
  				  struct mpoa_client *client)
  {
  	struct atm_vcc *vcc;
  	struct k_message msg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
  
  	vcc = entry->shortcut;
b50c2ea72   Joe Perches   net/atm: Cleanup ...
196
197
  	dprintk("removing an ingress entry, ip = %pI4
  ",
21454aaad   Harvey Harrison   net: replace NIPQ...
198
  		&entry->ctrl_info.in_dst_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
204
205
206
  
  	if (entry->prev != NULL)
  		entry->prev->next = entry->next;
  	else
  		client->in_cache = entry->next;
  	if (entry->next != NULL)
  		entry->next->prev = entry->prev;
  	client->in_ops->put(entry);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
207
  	if (client->in_cache == NULL && client->eg_cache == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  		msg.type = STOP_KEEP_ALIVE_SM;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
209
  		msg_to_mpoad(&msg, client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
  	}
  
  	/* Check if the egress side still uses this VCC */
  	if (vcc != NULL) {
bee67d34b   Joe Perches   net/atm/mpoa_cach...
214
215
  		eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc,
  								      client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
220
221
  		if (eg_entry != NULL) {
  			client->eg_ops->put(eg_entry);
  			return;
  		}
  		vcc_release_async(vcc, -EPIPE);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
  /* Call this every MPC-p2 seconds... Not exactly correct solution,
     but an easy one... */
  static void clear_count_and_expired(struct mpoa_client *client)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
230
231
232
233
  	in_cache_entry *entry, *next_entry;
  	struct timeval now;
  
  	do_gettimeofday(&now);
  
  	write_lock_bh(&client->ingress_lock);
  	entry = client->in_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
234
235
  	while (entry != NULL) {
  		entry->count = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
  		next_entry = entry->next;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
237
238
  		if ((now.tv_sec - entry->tv.tv_sec)
  		   > entry->ctrl_info.holding_time) {
b50c2ea72   Joe Perches   net/atm: Cleanup ...
239
240
  			dprintk("holding time expired, ip = %pI4
  ",
21454aaad   Harvey Harrison   net: replace NIPQ...
241
  				&entry->ctrl_info.in_dst_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
  			client->in_ops->remove_entry(entry, client);
  		}
  		entry = next_entry;
  	}
  	write_unlock_bh(&client->ingress_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
250
251
252
253
254
255
256
  }
  
  /* Call this every MPC-p4 seconds. */
  static void check_resolving_entries(struct mpoa_client *client)
  {
  
  	struct atm_mpoa_qos *qos;
  	in_cache_entry *entry;
  	struct timeval now;
  	struct k_message msg;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
257
  	do_gettimeofday(&now);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
  
  	read_lock_bh(&client->ingress_lock);
  	entry = client->in_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
261
262
263
264
265
  	while (entry != NULL) {
  		if (entry->entry_state == INGRESS_RESOLVING) {
  			if ((now.tv_sec - entry->hold_down.tv_sec) <
  			    client->parameters.mpc_p6) {
  				entry = entry->next;	/* Entry in hold down */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
266
267
  				continue;
  			}
bee67d34b   Joe Perches   net/atm/mpoa_cach...
268
269
270
271
272
273
274
275
  			if ((now.tv_sec - entry->reply_wait.tv_sec) >
  			    entry->retry_time) {
  				entry->retry_time = MPC_C1 * (entry->retry_time);
  				/*
  				 * Retry time maximum exceeded,
  				 * put entry in hold down.
  				 */
  				if (entry->retry_time > client->parameters.mpc_p5) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
  					do_gettimeofday(&(entry->hold_down));
  					entry->retry_time = client->parameters.mpc_p4;
  					entry = entry->next;
  					continue;
  				}
  				/* Ask daemon to send a resolution request. */
bee67d34b   Joe Perches   net/atm/mpoa_cach...
282
  				memset(&(entry->hold_down), 0, sizeof(struct timeval));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283
284
285
286
  				msg.type = SND_MPOA_RES_RTRY;
  				memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
  				msg.content.in_info = entry->ctrl_info;
  				qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
287
288
  				if (qos != NULL)
  					msg.qos = qos->qos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  				msg_to_mpoad(&msg, client);
  				do_gettimeofday(&(entry->reply_wait));
  			}
  		}
  		entry = entry->next;
  	}
  	read_unlock_bh(&client->ingress_lock);
  }
  
  /* Call this every MPC-p5 seconds. */
  static void refresh_entries(struct mpoa_client *client)
  {
  	struct timeval now;
  	struct in_cache_entry *entry = client->in_cache;
b50c2ea72   Joe Perches   net/atm: Cleanup ...
303
304
  	ddprintk("refresh_entries
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
307
  	do_gettimeofday(&now);
  
  	read_lock_bh(&client->ingress_lock);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
308
309
310
311
312
313
  	while (entry != NULL) {
  		if (entry->entry_state == INGRESS_RESOLVED) {
  			if (!(entry->refresh_time))
  				entry->refresh_time = (2 * (entry->ctrl_info.holding_time))/3;
  			if ((now.tv_sec - entry->reply_wait.tv_sec) >
  			    entry->refresh_time) {
b50c2ea72   Joe Perches   net/atm: Cleanup ...
314
315
  				dprintk("refreshing an entry.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
321
322
323
324
325
326
327
  				entry->entry_state = INGRESS_REFRESHING;
  
  			}
  		}
  		entry = entry->next;
  	}
  	read_unlock_bh(&client->ingress_lock);
  }
  
  static void in_destroy_cache(struct mpoa_client *mpc)
  {
  	write_lock_irq(&mpc->ingress_lock);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
328
  	while (mpc->in_cache != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
  		mpc->in_ops->remove_entry(mpc->in_cache, mpc);
  	write_unlock_irq(&mpc->ingress_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
  }
bee67d34b   Joe Perches   net/atm/mpoa_cach...
332
333
  static eg_cache_entry *eg_cache_get_by_cache_id(__be32 cache_id,
  						struct mpoa_client *mpc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
338
  {
  	eg_cache_entry *entry;
  
  	read_lock_irq(&mpc->egress_lock);
  	entry = mpc->eg_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
339
340
  	while (entry != NULL) {
  		if (entry->ctrl_info.cache_id == cache_id) {
e00bdbefa   Reshetova, Elena   net, atm: convert...
341
  			refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
342
343
344
345
346
347
348
349
350
351
352
  			read_unlock_irq(&mpc->egress_lock);
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_irq(&mpc->egress_lock);
  
  	return NULL;
  }
  
  /* This can be called from any context since it saves CPU flags */
30d492da7   Al Viro   [ATM]: Annotations.
353
  static eg_cache_entry *eg_cache_get_by_tag(__be32 tag, struct mpoa_client *mpc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
354
355
356
357
358
359
  {
  	unsigned long flags;
  	eg_cache_entry *entry;
  
  	read_lock_irqsave(&mpc->egress_lock, flags);
  	entry = mpc->eg_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
360
  	while (entry != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
361
  		if (entry->ctrl_info.tag == tag) {
e00bdbefa   Reshetova, Elena   net, atm: convert...
362
  			refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
366
367
368
369
370
371
372
373
  			read_unlock_irqrestore(&mpc->egress_lock, flags);
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_irqrestore(&mpc->egress_lock, flags);
  
  	return NULL;
  }
  
  /* This can be called from any context since it saves CPU flags */
bee67d34b   Joe Perches   net/atm/mpoa_cach...
374
375
  static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc,
  					   struct mpoa_client *mpc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
379
380
381
  {
  	unsigned long flags;
  	eg_cache_entry *entry;
  
  	read_lock_irqsave(&mpc->egress_lock, flags);
  	entry = mpc->eg_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
382
  	while (entry != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
383
  		if (entry->shortcut == vcc) {
e00bdbefa   Reshetova, Elena   net, atm: convert...
384
  			refcount_inc(&entry->use);
f7d57453d   YOSHIFUJI Hideaki   [NET] ATM: Fix wh...
385
  			read_unlock_irqrestore(&mpc->egress_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
389
390
391
392
393
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_irqrestore(&mpc->egress_lock, flags);
  
  	return NULL;
  }
bee67d34b   Joe Perches   net/atm/mpoa_cach...
394
395
  static eg_cache_entry *eg_cache_get_by_src_ip(__be32 ipaddr,
  					      struct mpoa_client *mpc)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
  {
  	eg_cache_entry *entry;
  
  	read_lock_irq(&mpc->egress_lock);
  	entry = mpc->eg_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
401
402
  	while (entry != NULL) {
  		if (entry->latest_ip_addr == ipaddr) {
e00bdbefa   Reshetova, Elena   net, atm: convert...
403
  			refcount_inc(&entry->use);
f7d57453d   YOSHIFUJI Hideaki   [NET] ATM: Fix wh...
404
  			read_unlock_irq(&mpc->egress_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
409
410
411
412
413
414
415
  			return entry;
  		}
  		entry = entry->next;
  	}
  	read_unlock_irq(&mpc->egress_lock);
  
  	return NULL;
  }
  
  static void eg_cache_put(eg_cache_entry *entry)
  {
e00bdbefa   Reshetova, Elena   net, atm: convert...
416
  	if (refcount_dec_and_test(&entry->use)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
  		memset(entry, 0, sizeof(eg_cache_entry));
  		kfree(entry);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
425
426
427
428
429
430
431
  }
  
  /*
   * This should be called with write lock on
   */
  static void eg_cache_remove_entry(eg_cache_entry *entry,
  				  struct mpoa_client *client)
  {
  	struct atm_vcc *vcc;
  	struct k_message msg;
  
  	vcc = entry->shortcut;
b50c2ea72   Joe Perches   net/atm: Cleanup ...
432
433
  	dprintk("removing an egress entry.
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
435
436
437
438
439
440
  	if (entry->prev != NULL)
  		entry->prev->next = entry->next;
  	else
  		client->eg_cache = entry->next;
  	if (entry->next != NULL)
  		entry->next->prev = entry->prev;
  	client->eg_ops->put(entry);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
441
  	if (client->in_cache == NULL && client->eg_cache == NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  		msg.type = STOP_KEEP_ALIVE_SM;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
443
  		msg_to_mpoad(&msg, client);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
449
450
451
452
453
454
  	}
  
  	/* Check if the ingress side still uses this VCC */
  	if (vcc != NULL) {
  		in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
  		if (in_entry != NULL) {
  			client->in_ops->put(in_entry);
  			return;
  		}
  		vcc_release_async(vcc, -EPIPE);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
455
  }
bee67d34b   Joe Perches   net/atm/mpoa_cach...
456
457
  static eg_cache_entry *eg_cache_add_entry(struct k_message *msg,
  					  struct mpoa_client *client)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
  {
2afe37cdf   Arnaldo Carvalho de Melo   [ATM]: Use kmemdu...
459
  	eg_cache_entry *entry = kzalloc(sizeof(eg_cache_entry), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
  
  	if (entry == NULL) {
bee67d34b   Joe Perches   net/atm/mpoa_cach...
462
463
  		pr_info("out of memory
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
  		return NULL;
  	}
b50c2ea72   Joe Perches   net/atm: Cleanup ...
466
467
  	dprintk("adding an egress entry, ip = %pI4, this should be our IP
  ",
21454aaad   Harvey Harrison   net: replace NIPQ...
468
  		&msg->content.eg_info.eg_dst_ip);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469

e00bdbefa   Reshetova, Elena   net, atm: convert...
470
  	refcount_set(&entry->use, 1);
b50c2ea72   Joe Perches   net/atm: Cleanup ...
471
472
  	dprintk("new_eg_cache_entry: about to lock
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
475
476
477
478
479
480
481
482
483
  	write_lock_irq(&client->egress_lock);
  	entry->next = client->eg_cache;
  	entry->prev = NULL;
  	if (client->eg_cache != NULL)
  		client->eg_cache->prev = entry;
  	client->eg_cache = entry;
  
  	memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
  	entry->ctrl_info = msg->content.eg_info;
  	do_gettimeofday(&(entry->tv));
  	entry->entry_state = EGRESS_RESOLVED;
b50c2ea72   Joe Perches   net/atm: Cleanup ...
484
485
  	dprintk("new_eg_cache_entry cache_id %u
  ",
bee67d34b   Joe Perches   net/atm/mpoa_cach...
486
  		ntohl(entry->ctrl_info.cache_id));
b50c2ea72   Joe Perches   net/atm: Cleanup ...
487
488
  	dprintk("mps_ip = %pI4
  ", &entry->ctrl_info.mps_ip);
e00bdbefa   Reshetova, Elena   net, atm: convert...
489
  	refcount_inc(&entry->use);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  
  	write_unlock_irq(&client->egress_lock);
b50c2ea72   Joe Perches   net/atm: Cleanup ...
492
493
  	dprintk("new_eg_cache_entry: unlocked
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
  
  	return entry;
  }
bee67d34b   Joe Perches   net/atm/mpoa_cach...
497
  static void update_eg_cache_entry(eg_cache_entry *entry, uint16_t holding_time)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498
499
500
501
  {
  	do_gettimeofday(&(entry->tv));
  	entry->entry_state = EGRESS_RESOLVED;
  	entry->ctrl_info.holding_time = holding_time;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
508
509
510
511
512
513
  }
  
  static void clear_expired(struct mpoa_client *client)
  {
  	eg_cache_entry *entry, *next_entry;
  	struct timeval now;
  	struct k_message msg;
  
  	do_gettimeofday(&now);
  
  	write_lock_irq(&client->egress_lock);
  	entry = client->eg_cache;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
514
  	while (entry != NULL) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515
  		next_entry = entry->next;
bee67d34b   Joe Perches   net/atm/mpoa_cach...
516
517
  		if ((now.tv_sec - entry->tv.tv_sec)
  		   > entry->ctrl_info.holding_time) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
  			msg.type = SND_EGRESS_PURGE;
  			msg.content.eg_info = entry->ctrl_info;
b50c2ea72   Joe Perches   net/atm: Cleanup ...
520
521
  			dprintk("egress_cache: holding time expired, cache_id = %u.
  ",
bee67d34b   Joe Perches   net/atm/mpoa_cach...
522
  				ntohl(entry->ctrl_info.cache_id));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
524
525
526
527
528
  			msg_to_mpoad(&msg, client);
  			client->eg_ops->remove_entry(entry, client);
  		}
  		entry = next_entry;
  	}
  	write_unlock_irq(&client->egress_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
531
532
533
  }
  
  static void eg_destroy_cache(struct mpoa_client *mpc)
  {
  	write_lock_irq(&mpc->egress_lock);
bee67d34b   Joe Perches   net/atm/mpoa_cach...
534
  	while (mpc->eg_cache != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
  		mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
  	write_unlock_irq(&mpc->egress_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
  }
4dd191bb6   Julia Lawall   net: atm: constif...
538
  static const struct in_cache_ops ingress_ops = {
99a5e178b   Kees Cook   ATM: use designat...
539
540
541
542
543
544
545
546
547
548
549
  	.add_entry = in_cache_add_entry,
  	.get = in_cache_get,
  	.get_with_mask = in_cache_get_with_mask,
  	.get_by_vcc = in_cache_get_by_vcc,
  	.put = in_cache_put,
  	.remove_entry = in_cache_remove_entry,
  	.cache_hit = cache_hit,
  	.clear_count = clear_count_and_expired,
  	.check_resolving = check_resolving_entries,
  	.refresh = refresh_entries,
  	.destroy_cache = in_destroy_cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
  };
4dd191bb6   Julia Lawall   net: atm: constif...
551
  static const struct eg_cache_ops egress_ops = {
99a5e178b   Kees Cook   ATM: use designat...
552
553
554
555
556
557
558
559
560
561
  	.add_entry = eg_cache_add_entry,
  	.get_by_cache_id = eg_cache_get_by_cache_id,
  	.get_by_tag = eg_cache_get_by_tag,
  	.get_by_vcc = eg_cache_get_by_vcc,
  	.get_by_src_ip = eg_cache_get_by_src_ip,
  	.put = eg_cache_put,
  	.remove_entry = eg_cache_remove_entry,
  	.update = update_eg_cache_entry,
  	.clear_expired = clear_expired,
  	.destroy_cache = eg_destroy_cache
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
  void atm_mpoa_init_cache(struct mpoa_client *mpc)
  {
  	mpc->in_ops = &ingress_ops;
  	mpc->eg_ops = &egress_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
  }