docs: Added note to curvetun doc
[netsniff-ng.git] / src / cpusched.c
blobe92bf9b06bfd0aaebe473d2ba8efe15c51f17737
1 /*
2 * netsniff-ng - the packet sniffing beast
3 * By Daniel Borkmann <daniel@netsniff-ng.org>
4 * Copyright 2011 Daniel Borkmann.
5 * Subject to the GPL, version 2.
6 */
8 #define _GNU_SOURCE
9 #include <search.h>
10 #include <limits.h>
11 #include <errno.h>
12 #include <string.h>
14 #include "locking.h"
15 #include "cpusched.h"
16 #include "xmalloc.h"
17 #include "hash.h"
19 /* Flow to CPU mapper / scheduler to keep connection CPU-local */
20 struct map_entry {
21 int fd;
22 unsigned int cpu;
23 struct map_entry *next;
26 static struct hash_table mapper;
28 static unsigned int *cpu_assigned = NULL;
30 static unsigned int cpu_len = 0;
32 static struct rwlock map_lock;
34 void init_cpusched(unsigned int cpus)
36 rwlock_init(&map_lock);
37 rwlock_wr_lock(&map_lock);
38 cpu_len = cpus;
39 cpu_assigned = xzmalloc(cpus * sizeof(*cpu_assigned));
40 memset(&mapper, 0, sizeof(mapper));
41 init_hash(&mapper);
42 rwlock_unlock(&map_lock);
45 static int get_appropriate_cpu(void)
47 int i, cpu = 0;
48 int work = INT_MAX;
49 for (i = 0; i < cpu_len; ++i) {
50 if (cpu_assigned[i] < work) {
51 work = cpu_assigned[i];
52 cpu = i;
55 return cpu;
58 unsigned int socket_to_cpu(int fd)
60 int cpu = 0;
61 struct map_entry *entry;
63 errno = 0;
64 rwlock_rd_lock(&map_lock);
65 entry = lookup_hash(fd, &mapper);
66 while (entry && fd != entry->fd)
67 entry = entry->next;
68 if (entry && fd == entry->fd)
69 cpu = entry->cpu;
70 else
71 errno = ENOENT;
72 rwlock_unlock(&map_lock);
74 return cpu;
77 unsigned int register_socket(int fd)
79 void **pos;
80 struct map_entry *entry;
82 rwlock_wr_lock(&map_lock);
83 entry = xzmalloc(sizeof(*entry));
84 entry->fd = fd;
85 entry->cpu = get_appropriate_cpu();
86 cpu_assigned[entry->cpu]++;
87 pos = insert_hash(entry->fd, entry, &mapper);
88 if (pos) {
89 entry->next = (*pos);
90 (*pos) = entry;
92 rwlock_unlock(&map_lock);
94 return entry->cpu;
97 static struct map_entry *socket_to_map_entry(int fd)
99 struct map_entry *entry, *ret = NULL;
101 errno = 0;
102 rwlock_rd_lock(&map_lock);
103 entry = lookup_hash(fd, &mapper);
104 while (entry && fd != entry->fd)
105 entry = entry->next;
106 if (entry && fd == entry->fd)
107 ret = entry;
108 else
109 errno = ENOENT;
110 rwlock_unlock(&map_lock);
112 return ret;
115 void unregister_socket(int fd)
117 struct map_entry *pos;
118 struct map_entry *entry = socket_to_map_entry(fd);
120 if (!entry == 0 && errno == ENOENT)
121 return;
122 rwlock_wr_lock(&map_lock);
123 cpu_assigned[entry->cpu]--;
124 pos = remove_hash(entry->fd, entry, entry->next, &mapper);
125 while (pos && pos->next && pos->next != entry)
126 pos = pos->next;
127 if (pos && pos->next && pos->next == entry)
128 pos->next = entry->next;
129 entry->next = NULL;
130 xfree(entry);
131 rwlock_unlock(&map_lock);
134 static int cleanup_batch(void *ptr)
136 struct map_entry *next;
137 struct map_entry *e = ptr;
139 if (!e)
140 return 0;
141 while ((next = e->next)) {
142 e->next = NULL;
143 xfree(e);
144 e = next;
146 xfree(e);
147 return 0;
150 void destroy_cpusched(void)
152 rwlock_wr_lock(&map_lock);
153 xfree(cpu_assigned);
154 cpu_len = 0;
155 for_each_hash(&mapper, cleanup_batch);
156 free_hash(&mapper);
157 rwlock_unlock(&map_lock);
158 rwlock_destroy(&map_lock);