credit system, reverse_connid_table insert bugfix
[cor_2_6_31.git] / net / cor / common.c
blob82e2d7e839c5477a86215bbeed20b44588d42e36
1 /*
2 * Connection oriented routing
3 * Copyright (C) 2007-2008 Michael Blizek
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
21 #include <linux/mutex.h>
23 #include "cor.h"
25 DEFINE_MUTEX(cor_bindnodes);
26 DEFINE_SPINLOCK(conn_free);
28 DEFINE_MUTEX(connid_gen);
30 LIST_HEAD(openports);
33 struct cell_hdr{
34 spinlock_t lock;
39 struct kmem_cache *conn_slab;
41 struct htable connid_table;
42 struct htable reverse_connid_table;
44 struct kmem_cache *bindnode_slab;
45 struct kmem_cache *connlistener_slab;
47 /* see cor.h/KP_ACK_CONN */
48 static const __u32 window_sizes[] = {0,
49 64, 68, 73, 77, 82, 88, 93, 99, 106, 113, 120,
50 128, 136, 145, 155, 165, 175, 187, 199, 212, 226, 240,
51 256, 273, 290, 309, 329, 351, 374, 398, 424, 451, 481,
52 512, 545, 581, 619, 659, 702, 747, 796, 848, 903, 961,
53 1024, 1091, 1162, 1237, 1318, 1403, 1495, 1592, 1695, 1805,
54 1923,
55 2048, 2181, 2323, 2474, 2635, 2806, 2989, 3183, 3390, 3611,
56 3846,
57 4096, 4362, 4646, 4948, 5270, 5613, 5978, 6367, 6781, 7222,
58 7692,
59 8192, 8725, 9292, 9897, 10540, 11226, 11956, 12734, 13562,
60 14444, 15383,
61 16384, 17450, 18585, 19793, 21081, 22452, 23912, 25467, 27124,
62 28888, 30767,
63 32768, 34899, 37169, 39587, 42161, 44904, 47824, 50935, 54248,
64 57776, 61534,
65 65536, 69799, 74338, 79173, 84323, 89807, 95648, 101870, 108495,
66 115552, 123068,
67 131072, 139597, 148677, 158347, 168646, 179615, 191297, 203739,
68 216991, 231104, 246135,
69 262144, 279194, 297353, 316693, 337291, 359229, 382594, 407478,
70 433981, 462208, 492270,
71 524288, 558388, 594706, 633387, 674583, 718459, 765188, 814957,
72 867962, 924415, 984540,
73 1048576, 1116777, 1189413, 1266774, 1349166, 1436917, 1530376,
74 1629913, 1735924, 1848831, 1969081,
75 2097152, 2233553, 2378826, 2533547, 2698332, 2873834, 3060752,
76 3259826, 3471849, 3697662, 3938162,
77 4194304, 4467106, 4757652, 5067094, 5396664, 5747669, 6121503,
78 6519652, 6943698, 7395323, 7876323,
79 8388608, 8934212, 9515303, 10134189, 10793327, 11495337,
80 12243006, 13039305, 13887396, 14790647,
81 15752647,
82 16777216, 17868424, 19030606, 20268378, 21586655, 22990674,
83 24486013, 26078610, 27774791, 29581294,
84 31505293,
85 33554432, 35736849, 38061212, 40536755, 43173310, 45981349,
86 48972026, 52157220, 55549582, 59162588,
87 63010587,
88 67108864, 71473698, 76122425, 81073510, 86346620, 91962698,
89 97944052, 104314440, 111099165, 118325175,
90 126021174,
91 134217728, 142947395, 152244850, 162147020, 172693239,
92 183925396, 195888104, 208628880, 222198329,
93 236650351, 252042347,
94 268435456, 285894791, 304489699, 324294041, 345386479,
95 367850791, 391776208, 417257759, 444396658,
96 473300701, 504084694,
97 536870912, 571789581};
99 __u8 enc_window(__u32 window_bytes)
101 int i;
102 BUG_ON(window_sizes[255] != 571789581);
103 for (i=1;i<256;i++) {
104 if (window_sizes[i] > window_bytes)
105 break;
108 return (__u8)(i-1); /* round down */
111 __u32 dec_window(__u8 window)
113 BUG_ON(window_sizes[255] != 571789581);
114 return window_sizes[window];
117 static inline int hdr_size(void)
119 return ((sizeof(struct cell_hdr) + sizeof(void *) - 1) / sizeof(void *)
120 ) * sizeof(void *);
123 static inline int elements_per_cell(int cell_size)
125 return (cell_size - hdr_size())/sizeof(void *);
128 static inline struct cell_hdr *cell_addr(struct htable *ht, __u32 id)
130 int idx = (id%ht->htable_size) / (elements_per_cell(ht->cell_size));
131 return (struct cell_hdr *) (((char *)ht->htable) + ht->cell_size * idx);
134 static inline char **element_addr(struct htable *ht, __u32 id)
136 int idx = (id%ht->htable_size) % (elements_per_cell(ht->cell_size));
137 return (char **)
138 ( ((char *)cell_addr(ht, id)) +
139 hdr_size() + idx*sizeof(void *) );
143 static inline char **next_element(struct htable *ht, char *element)
145 return (char **)(element + ht->entry_offset);
148 static inline struct kref *element_kref(struct htable *ht, char *element)
150 return (struct kref *)(element + ht->kref_offset);
154 static inline void unlock_element(struct htable *ht, __u32 key)
156 struct cell_hdr *hdr = cell_addr(ht, key);
157 spin_unlock( &(hdr->lock) );
161 static char **get_element_nounlock(struct htable *ht, __u32 key,
162 void *searcheditem)
164 struct cell_hdr *hdr = cell_addr(ht, key);
165 char **element = element_addr(ht, key);
167 BUG_ON(0 == element);
169 spin_lock( &(hdr->lock) );
171 while (1) {
172 if (*element == 0)
173 break;
174 if (searcheditem != 0 && ht->matches(*element, searcheditem))
175 break;
176 element = next_element(ht, *element);
179 return element;
182 char *htable_get(struct htable *ht, __u32 key, void *searcheditem)
184 unsigned long iflags;
185 char *element;
187 if (unlikely(ht->htable == 0))
188 return 0;
190 local_irq_save(iflags);
191 element = *(get_element_nounlock(ht, key, searcheditem));
192 if (likely(element != 0))
193 kref_get(element_kref(ht, element));
194 unlock_element(ht, key);
195 local_irq_restore(iflags);
197 return element;
200 int htable_delete(struct htable *ht, __u32 key,
201 void *searcheditem, void (*free) (struct kref *ref))
203 unsigned long iflags;
204 char **element;
205 char **next;
206 int rc = 0;
208 if (unlikely(ht->htable == 0))
209 return 1;
211 local_irq_save(iflags);
213 element = get_element_nounlock(ht, key, searcheditem);
214 BUG_ON(0 == element);
216 if (unlikely(*element == 0)) {
217 /* key not in table */
218 rc = 1;
219 goto out;
222 next = next_element(ht, *element);
223 kref_put(element_kref(ht, *element), free);
224 *element = *next;
226 out:
227 unlock_element(ht, key);
228 local_irq_restore(iflags);
230 return rc;
233 void htable_insert(struct htable *ht, char *newelement, __u32 key)
235 unsigned long iflags;
236 char **element;
238 if (unlikely(ht->htable == 0))
239 return;
241 BUG_ON(*next_element(ht, newelement) != 0);
242 local_irq_save(iflags);
244 element = get_element_nounlock(ht, key, 0);
246 BUG_ON(element == 0);
247 BUG_ON(*element != 0);
249 *element = newelement;
250 kref_get(element_kref(ht, newelement));
252 unlock_element(ht, key);
253 local_irq_restore(iflags);
257 void htable_init(struct htable *ht, int (*matches)(void *htentry,
258 void *searcheditem), __u32 entry_offset, __u32 kref_offset)
260 int num_cells;
261 int j;
263 BUG_ON(0 == ht);
265 ht->htable = kmalloc(PAGE_SIZE, GFP_KERNEL);
266 if (unlikely(ht->htable == 0)) {
267 printk(KERN_CRIT "cor: error allocating htable (out of "
268 "memory?)");
269 return;
271 memset(ht->htable, 0, PAGE_SIZE);
272 ht->cell_size = 256;
274 num_cells = PAGE_SIZE/ht->cell_size;
276 for (j=0;j<num_cells;j++) {
277 struct cell_hdr *hdr = (struct cell_hdr *)
278 ( ((char *) ht->htable) + j * ht->cell_size );
279 spin_lock_init(&(hdr->lock));
282 ht->htable_size = num_cells * elements_per_cell(ht->cell_size);
283 ht->num_elements = 0;
285 ht->matches = matches;
286 ht->entry_offset = entry_offset;
287 ht->kref_offset = kref_offset;
290 struct reverse_connid_matchparam {
291 struct neighbor *nb;
292 __u32 conn_id;
295 static __u32 rcm_to_key(struct reverse_connid_matchparam *rcm)
297 return (((__u32) rcm->nb) ^ rcm->conn_id);
300 static int matches_reverse_connid(void *htentry, void *searcheditem)
302 struct conn *conn = (struct conn *) htentry;
303 struct reverse_connid_matchparam *rcm =
304 (struct reverse_connid_matchparam *) searcheditem;
305 BUG_ON(conn->targettype != TARGET_OUT);
306 return (conn->target.out.nb == rcm->nb) &&
307 (conn->target.out.conn_id == rcm->conn_id);
310 struct conn *get_conn_reverse(struct neighbor *nb, __u32 conn_id)
312 struct reverse_connid_matchparam rcm;
313 rcm.nb = nb;
314 rcm.conn_id = conn_id;
316 return (struct conn *) htable_get(&reverse_connid_table,
317 rcm_to_key(&rcm), &rcm);
320 void insert_reverse_connid(struct conn *rconn)
322 struct reverse_connid_matchparam rcm;
324 BUG_ON(rconn->targettype != TARGET_OUT);
326 rcm.nb = rconn->target.out.nb;
327 rcm.conn_id = rconn->target.out.conn_id;
328 htable_insert(&reverse_connid_table, (char *) rconn, rcm_to_key(&rcm));
331 struct conn *get_conn(__u32 conn_id)
333 return (struct conn *) htable_get(&connid_table, conn_id, &conn_id);
336 static int connid_alloc(struct conn *sconn)
338 __u32 conn_id;
339 int i;
341 BUG_ON(sconn->sourcetype != SOURCE_IN);
343 mutex_lock(&connid_gen);
344 for(i=0;i<16;i++) {
345 struct conn *tmp;
347 conn_id = 0;
348 get_random_bytes((char *) &conn_id, sizeof(conn_id));
350 if (unlikely(conn_id == 0))
351 continue;
353 tmp = get_conn(conn_id);
354 if (unlikely(tmp != 0)) {
355 kref_put(&(tmp->ref), free_conn);
356 continue;
359 goto found;
361 mutex_unlock(&connid_gen);
363 return 1;
365 found:
366 sconn->source.in.conn_id = conn_id;
367 htable_insert(&connid_table, (char *) sconn, conn_id);
368 mutex_unlock(&connid_gen);
369 return 0;
372 void free_conn(struct kref *ref)
374 unsigned long iflags;
375 struct conn *conn = container_of(ref, struct conn, ref);
376 struct conn *reversedir = 0;
378 BUG_ON(atomic_read(&(conn->isreset)) == 0);
380 spin_lock_irqsave(&conn_free, iflags);
382 if (conn->reversedir != 0)
383 atomic_set(&(conn->reversedir->isreset), 3);
385 if (atomic_read(&(conn->isreset)) != 3)
386 goto out;
388 if (conn->reversedir != 0) {
389 conn->reversedir->reversedir = 0;
390 reversedir = conn->reversedir;
391 conn->reversedir = 0;
394 if (conn->sourcetype == SOURCE_IN) {
395 kref_put(&(conn->source.in.nb->ref), neighbor_free);
396 conn->source.in.nb = 0;
399 if (conn->targettype == TARGET_OUT) {
400 kref_put(&(conn->target.out.nb->ref), neighbor_free);
401 conn->target.out.nb = 0;
404 databuf_free(&(conn->buf));
406 kmem_cache_free(conn_slab, conn);
408 out:
409 spin_unlock_irqrestore(&conn_free, iflags);
411 if (reversedir != 0)
412 free_conn(&(reversedir->ref));
416 * rconn ==> the connection we received the commend from
417 * ==> init rconn->target.out + rconn->reversedir->source.in
418 * rc == 0 ==> ok
419 * rc == 1 ==> connid allocation failed
421 * NOTE: call to this func *must* be protected by rcv_lock
423 int conn_init_out(struct conn *rconn, struct neighbor *nb)
425 int rc = 0;
426 struct conn *sconn = rconn->reversedir;
427 __u32 stall_timeout_ms = rconn->target.unconnected.stall_timeout_ms;
429 mutex_lock(&(sconn->rcv_lock));
431 BUG_ON(rconn->targettype != TARGET_UNCONNECTED);
432 BUG_ON(sconn == 0);
433 BUG_ON(sconn->sourcetype != SOURCE_NONE);
435 memset(&(rconn->target.out), 0, sizeof(rconn->target.out));
436 memset(&(sconn->source.in), 0, sizeof(sconn->source.in));
438 rconn->targettype = TARGET_OUT;
439 sconn->sourcetype = SOURCE_IN;
441 rconn->target.out.nb = nb;
442 sconn->source.in.nb = nb;
444 /* neighbor pointer */
445 kref_get(&(nb->ref));
446 kref_get(&(nb->ref));
448 rconn->target.out.stall_timeout_ms = stall_timeout_ms;
449 skb_queue_head_init(&(sconn->source.in.reorder_queue));
450 atomic_set(&(sconn->source.in.pong_awaiting), 0);
452 if (unlikely(connid_alloc(sconn))) {
453 rc = 1;
454 goto out;
457 INIT_LIST_HEAD(&(rconn->target.out.retrans_list));
459 reset_seqno(&(rconn->buf));
461 mutex_lock(&(nb->conn_list_lock));
462 list_add_tail(&(sconn->source.in.nb_list), &(nb->rcv_conn_list));
463 list_add_tail(&(rconn->target.out.nb_list), &(nb->snd_conn_list));
464 nb->num_send_conns++;
465 mutex_unlock(&(nb->conn_list_lock));
467 /* neighbor lists */
468 kref_get(&(rconn->ref));
469 kref_get(&(sconn->ref));
471 out:
472 mutex_unlock(&(sconn->rcv_lock));
474 return rc;
477 void conn_init_sock_source(struct conn *conn)
479 BUG_ON(conn == 0);
480 conn->sourcetype = SOURCE_SOCK;
481 memset(&(conn->source.sock), 0, sizeof(conn->source.sock));
482 init_waitqueue_head(&(conn->source.sock.wait));
485 void conn_init_sock_target(struct conn *conn)
487 BUG_ON(conn == 0);
488 conn->targettype = TARGET_SOCK;
489 memset(&(conn->target.sock), 0, sizeof(conn->target.sock));
490 init_waitqueue_head(&(conn->target.sock.wait));
491 reset_seqno(&(conn->buf));
494 struct conn* alloc_conn(gfp_t allocflags)
496 struct conn *rconn = 0;
497 struct conn *sconn = 0;
499 rconn = kmem_cache_alloc(conn_slab, allocflags);
500 if (unlikely(rconn == 0))
501 goto out_err0;
503 sconn = kmem_cache_alloc(conn_slab, allocflags);
504 if (unlikely(sconn == 0))
505 goto out_err1;
507 memset(rconn, 0, sizeof(struct conn));
508 memset(sconn, 0, sizeof(struct conn));
510 rconn->reversedir = sconn;
511 sconn->reversedir = rconn;
513 kref_init(&(rconn->ref));
514 kref_init(&(sconn->ref));
516 rconn->sockstate = SOCKSTATE_CONN;
517 sconn->sockstate = SOCKSTATE_CONN;
519 rconn->sourcetype = SOURCE_NONE;
520 sconn->sourcetype = SOURCE_NONE;
521 rconn->targettype = TARGET_UNCONNECTED;
522 sconn->targettype = TARGET_UNCONNECTED;
524 mutex_init(&(rconn->rcv_lock));
525 mutex_init(&(sconn->rcv_lock));
527 rconn->target.unconnected.stall_timeout_ms =
528 CONN_STALL_DEFAULT_TIMEOUT_MS;
529 sconn->target.unconnected.stall_timeout_ms =
530 CONN_STALL_DEFAULT_TIMEOUT_MS;
532 databuf_init(&(rconn->buf));
533 databuf_init(&(sconn->buf));
535 rconn->jiffies_credit_update = jiffies;
536 rconn->jiffies_credit_update = rconn->jiffies_credit_update;
538 return rconn;
540 out_err1:
541 kmem_cache_free(conn_slab, rconn);
542 out_err0:
543 return 0;
546 static struct connlistener *get_connlistener(__be64 port)
548 struct list_head *curr = openports.next;
550 while (curr != &openports) {
551 struct bindnode *currnode = ((struct bindnode *)
552 (((char *)curr) - offsetof(struct bindnode, lh)));
553 if (currnode->port == port) {
554 BUG_ON(currnode->owner == 0);
555 return currnode->owner;
558 curr = curr->next;
561 return 0;
564 void close_port(struct connlistener *listener)
566 mutex_lock(&cor_bindnodes);
568 if (listener->bn != 0) {
569 list_del(&(listener->bn->lh));
570 kmem_cache_free(bindnode_slab, listener->bn);
571 listener->bn = 0;
574 while (list_empty(&(listener->conn_queue)) == 0) {
575 struct conn *rconn = container_of(listener->conn_queue.next,
576 struct conn, source.sock.cl_list);
577 list_del(&(rconn->source.sock.cl_list));
578 atomic_cmpxchg(&(rconn->reversedir->isreset), 0, 1);
579 reset_conn(rconn);
580 kref_put(&(rconn->ref), free_conn);
583 kmem_cache_free(connlistener_slab, listener);
585 mutex_unlock(&cor_bindnodes);
588 struct connlistener *open_port(__be64 port)
591 struct bindnode *bn = 0;
592 struct connlistener *listener = 0;
594 mutex_lock(&cor_bindnodes);
595 if (get_connlistener(port) != 0)
596 goto out;
599 bn = kmem_cache_alloc(bindnode_slab, GFP_KERNEL);
600 listener = kmem_cache_alloc(connlistener_slab, GFP_KERNEL);
602 memset(bn, 0, sizeof(struct bindnode));
603 memset(listener, 0, sizeof(struct connlistener));
605 bn->owner = listener;
606 bn->port = port;
608 /* kref is not actually used */
609 listener->sockstate = SOCKSTATE_LISTENER;
610 listener->bn = bn;
611 mutex_init(&(listener->lock));
612 INIT_LIST_HEAD(&(listener->conn_queue));
613 init_waitqueue_head(&(listener->wait));
615 list_add_tail((struct list_head *) &(bn->lh), &openports);
617 out:
618 mutex_unlock(&cor_bindnodes);
620 return listener;
624 * rc == 0 connected
625 * rc == 2 port not open
626 * rc == 3 listener queue full
628 int connect_port(struct conn *rconn, __be64 port)
631 struct connlistener *listener;
632 int rc = 0;
634 mutex_lock(&cor_bindnodes);
636 listener = get_connlistener(port);
637 if (listener == 0) {
638 rc = 2;
639 goto out;
642 mutex_lock(&(listener->lock));
644 if (unlikely(listener->queue_len >= listener->queue_maxlen)) {
645 if (listener->queue_maxlen <= 0)
646 rc = 2;
647 else
648 rc = 3;
650 goto out2;
653 kref_get(&(rconn->reversedir->ref));
655 mutex_lock(&(rconn->rcv_lock));
656 mutex_lock(&(rconn->reversedir->rcv_lock));
657 conn_init_sock_target(rconn);
658 conn_init_sock_source(rconn->reversedir);
659 mutex_unlock(&(rconn->reversedir->rcv_lock));
660 mutex_unlock(&(rconn->rcv_lock));
662 list_add_tail(&(rconn->reversedir->source.sock.cl_list),
663 &(listener->conn_queue));
664 listener->queue_len++;
665 wake_up_interruptible(&(listener->wait));
667 out2:
668 mutex_unlock(&(listener->lock));
670 out:
671 mutex_unlock(&cor_bindnodes);
672 return rc;
676 * rc == 0 connected
677 * rc == 2 addrtype not found
678 * rc == 3 addr not found
679 * rc == 4 ==> connid allocation failed
680 * rc == 5 ==> control msg alloc failed
682 int connect_neigh(struct conn *rconn,
683 __u16 addrtypelen, __u8 *addrtype,
684 __u16 addrlen, __u8 *addr)
686 int rc = 0;
687 struct control_msg_out *cm;
688 struct neighbor *nb = find_neigh(addrtypelen, addrtype, addrlen, addr);
689 if (nb == 0)
690 return 3;
691 if (unlikely(conn_init_out(rconn, nb))) {
692 rc = 4;
693 goto neigh_kref;
696 cm = alloc_control_msg(nb, ACM_PRIORITY_HIGH);
697 if (unlikely(cm == 0)) {
698 rc = 5;
699 goto neigh_kref;
702 send_connect_nb(cm, rconn->reversedir->source.in.conn_id);
704 neigh_kref:
705 kref_put(&(nb->ref), neighbor_free);
707 return rc;
710 static int _reset_conn(struct conn *conn)
713 * aktive conns have an additional ref to make sure that they are not
714 * freed when only one direction is referenced by the connid hashtable
716 int krefput = 1;
717 int isreset = atomic_cmpxchg(&(conn->isreset), 0, 2);
718 if (isreset == 1)
719 isreset = atomic_cmpxchg(&(conn->isreset), 1, 2);
721 if (isreset == 2 || isreset == 3)
722 return 0;
724 /* lock sourcetype/targettype */
725 mutex_lock(&(conn->rcv_lock));
727 if (conn->sourcetype == SOURCE_IN) {
728 mutex_lock(&(conn->source.in.nb->conn_list_lock));
729 list_del(&(conn->source.in.nb_list));
730 mutex_unlock(&(conn->source.in.nb->conn_list_lock));
732 krefput++;
734 if (conn->source.in.conn_id != 0) {
735 if (htable_delete(&connid_table,
736 conn->source.in.conn_id,
737 &(conn->source.in.conn_id), free_conn)){
738 printk(KERN_ERR "error in _reset_conn: "
739 "htable_delete src_in failed");
741 conn->source.in.conn_id = 0;
743 } else if (conn->sourcetype == SOURCE_SOCK) {
744 wake_up_interruptible(&(conn->source.sock.wait));
747 if (conn->targettype == TARGET_OUT) {
748 mutex_lock(&(conn->target.out.nb->conn_list_lock));
749 list_del(&(conn->target.out.nb_list));
750 conn->target.out.nb->num_send_conns--;
751 BUG_ON(conn->target.out.nb->num_send_conns < 0);
752 mutex_unlock(&(conn->target.out.nb->conn_list_lock));
754 krefput++;
756 if (conn->target.out.conn_id != 0) {
757 struct reverse_connid_matchparam rcm;
758 rcm.nb = conn->target.out.nb;
759 rcm.conn_id = conn->target.out.conn_id;
760 if (htable_delete(&reverse_connid_table,
761 rcm_to_key(&rcm),
762 &rcm, free_conn)){
763 printk(KERN_ERR "error in _reset_conn: "
764 "htable_delete target_out "
765 "failed");
769 if (isreset == 0 && conn->target.out.conn_id != 0) {
770 struct control_msg_out *cm = alloc_control_msg(
771 conn->target.out.nb, ACM_PRIORITY_HIGH);
772 if (unlikely(cm == 0))
773 send_ping_all_conns(conn->target.out.nb);
774 else
775 send_reset_conn(cm, conn->target.out.conn_id);
778 conn->target.out.conn_id = 0;
780 cancel_retrans(conn);
781 } else if (conn->targettype == TARGET_SOCK) {
782 wake_up_interruptible(&(conn->target.sock.wait));
785 databuf_free(&(conn->buf));
787 mutex_unlock(&(conn->rcv_lock));
789 return krefput;
792 /* warning: do not hold the rcv_lock while calling this! */
793 void reset_conn(struct conn *conn)
795 int put1 = _reset_conn(conn);
796 int put2 = _reset_conn(conn->reversedir);
798 /*free_conn may not be called, before both _reset_conn have finished */
799 while (put1 > 0) {
800 kref_put(&(conn->ref), free_conn);
801 put1--;
804 while (put2 > 0) {
805 kref_put(&(conn->reversedir->ref), free_conn);
806 put2--;
810 static int matches_connid_in(void *htentry, void *searcheditem)
812 struct conn *conn = (struct conn *) htentry;
813 __u32 conn_id = *((__u32 *) searcheditem);
814 BUG_ON(conn->sourcetype != SOURCE_IN);
815 return (conn->source.in.conn_id == conn_id);
818 static int __init cor_common_init(void)
820 int rc;
822 struct conn c;
824 printk(KERN_ERR "sizeof conn: %d", sizeof(c));
825 printk(KERN_ERR " conn.source: %d", sizeof(c.source));
826 printk(KERN_ERR " conn.target: %d", sizeof(c.target));
827 printk(KERN_ERR " conn.target.out: %d", sizeof(c.target.out));
828 printk(KERN_ERR " conn.buf: %d", sizeof(c.buf));
830 printk(KERN_ERR " mutex: %d", sizeof(struct mutex));
831 printk(KERN_ERR " spinlock: %d", sizeof(spinlock_t));
832 printk(KERN_ERR " kref: %d", sizeof(struct kref));
834 conn_slab = kmem_cache_create("cor_conn", sizeof(struct conn), 8, 0, 0);
835 htable_init(&connid_table, matches_connid_in,
836 offsetof(struct conn, source.in.htab_entry),
837 offsetof(struct conn, ref));
839 htable_init(&reverse_connid_table, matches_reverse_connid,
840 offsetof(struct conn, source.in.htab_entry),
841 offsetof(struct conn, ref));
843 bindnode_slab = kmem_cache_create("cor_bindnode",
844 sizeof(struct bindnode), 8, 0, 0);
845 connlistener_slab = kmem_cache_create("cor_connlistener",
846 sizeof(struct connlistener), 8, 0, 0);
848 forward_init();
850 cor_kgen_init();
852 rc = cor_snd_init();
853 if (unlikely(rc != 0))
854 return rc;
856 rc = cor_neighbor_init();
857 if (unlikely(rc != 0))
858 return rc;
860 rc = cor_rcv_init();
861 if (unlikely(rc != 0))
862 return rc;
864 return 0;
867 module_init(cor_common_init);
868 MODULE_LICENSE("GPL");