embox

Форк
0
/
netdev.c 
355 строк · 6.3 Кб
1
/**
2
 * @file
3
 * @brief Protocol independent device support routines.
4
 *
5
 * @date 04.03.09
6
 * @author Anton Bondarev
7
 * @author Ilia Vaprol
8
 */
9

10
#include <assert.h>
11
#include <stddef.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <errno.h>
15

16

17
#include <lib/libds/hashtable.h>
18
#include <lib/libds/dlist.h>
19
#include <lib/libds/indexator.h>
20
#include <lib/libds/array.h>
21

22
#include <mem/misc/pool.h>
23
#include <mem/sysmalloc.h>
24

25
#include <net/if.h>
26
#include <net/netdevice.h>
27
#include <net/skbuff.h>
28
#include <net/netlink.h>
29

30
#include <framework/mod/options.h>
31

32
#define MODOPS_NETDEV_QUANTITY OPTION_GET(NUMBER, netdev_quantity)
33
#define MODOPS_NETDEV_TABLE_SZ OPTION_GET(NUMBER, netdev_table_sz)
34

35
POOL_DEF(netdev_pool, struct net_device, MODOPS_NETDEV_QUANTITY);
36

37
INDEX_DEF(netdev_index, 1, MODOPS_NETDEV_QUANTITY);
38

39
static size_t netdev_hash(void *key) {
40
	size_t hash;
41
	const char *name = key;
42

43
	hash = 0;
44
	while (*name != '\0') {
45
		hash ^= *name++;
46
	}
47

48
	return hash;
49
}
50

51
HASHTABLE_DEF(nd_ht, MODOPS_NETDEV_TABLE_SZ, &netdev_hash, (ht_cmp_ft)&strcmp);
52
struct hashtable *netdevs_table = &nd_ht;
53

54
POOL_DEF(netdev_htitem_pool, struct hashtable_item, MODOPS_NETDEV_QUANTITY);
55

56
static int netdev_init(struct net_device *dev, const char *name,
57
		int (*setup)(struct net_device *), size_t priv_size) {
58
	assert(dev != NULL);
59
	assert(name != NULL);
60
	assert(setup != NULL);
61

62
	dlist_head_init(&dev->rx_lnk);
63
	dlist_head_init(&dev->tx_lnk);
64
	strcpy(&dev->name[0], name);
65
	memset(&dev->stats, 0, sizeof dev->stats);
66
	skb_queue_init(&dev->dev_queue);
67
	skb_queue_init(&dev->dev_queue_tx);
68

69
	if (priv_size != 0) {
70
		dev->priv = sysmalloc(priv_size);
71
		if (dev->priv == NULL) {
72
			return -ENOMEM;
73
		}
74
	}
75
	else {
76
		dev->priv = NULL;
77
	}
78

79
	return (*setup)(dev);
80
}
81

82
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
83
void dev_net_set(struct net_device *dev, net_namespace_p net_ns) {
84
	assign_net_ns(dev->net_ns, net_ns);
85
}
86
#endif
87

88
struct net_device * netdev_alloc(const char *name,
89
		int (*setup)(struct net_device *), size_t priv_size) {
90
	int ret;
91
	struct net_device *dev;
92

93
	if ((name == NULL) || (setup == NULL)) {
94
		return NULL; /* error: invalid args */
95
	}
96

97
	if (strlen(name) >= ARRAY_SIZE(dev->name)) {
98
		return NULL; /* error: name too big */
99
	}
100

101
	dev = (struct net_device *)pool_alloc(&netdev_pool);
102
	if (dev == NULL) {
103
		return NULL; /* error: no memory */
104
	}
105

106
	dev->index = index_alloc(&netdev_index, INDEX_NEXT);
107

108
	ret = netdev_init(dev, name, setup, priv_size);
109
	if (ret != 0) {
110
		netdev_free(dev);
111
		return NULL; /* error: see return code */
112
	}
113

114
	return dev;
115
}
116

117
void netdev_free(struct net_device *dev) {
118
	if (dev != NULL) {
119
		dlist_del_init(&dev->rx_lnk);
120
		dlist_del_init(&dev->tx_lnk);
121
		skb_queue_purge(&dev->dev_queue);
122
		skb_queue_purge(&dev->dev_queue_tx);
123
		if (dev->priv) {
124
			sysfree(dev->priv);
125
		}
126
		index_free(&netdev_index, dev->index);
127
		pool_free(&netdev_pool, dev);
128
	}
129
}
130

131
int netdev_register(struct net_device *dev) {
132
	struct hashtable_item *ht_item;
133

134
	if (dev == NULL) {
135
		return -EINVAL;
136
	}
137

138
	ht_item = pool_alloc(&netdev_htitem_pool);
139
	ht_item = hashtable_item_init(ht_item, (void *)&dev->name[0], (void *)dev);
140

141
	return hashtable_put(netdevs_table, ht_item);
142
}
143

144
int netdev_unregister(struct net_device *dev) {
145
	struct hashtable_item *ht_item;
146

147
	if (dev == NULL) {
148
		return -EINVAL;
149
	}
150
	ht_item = hashtable_del(netdevs_table, (void *)&dev->name[0]);
151

152
	pool_free(&netdev_htitem_pool, ht_item);
153

154
	return 0;
155

156
}
157

158
struct net_device * netdev_get_by_name(const char *name) {
159
	if (name == NULL) {
160
		return NULL; /* error: invalid name */
161
	}
162

163
	return hashtable_get(netdevs_table, (void *)name);
164
}
165

166
int netdev_open(struct net_device *dev) {
167
	int ret;
168

169
	if (dev == NULL) {
170
		return -EINVAL;
171
	}
172

173
	if (dev->flags & IFF_UP) {
174
		return 0;
175
	}
176

177
	if (dev->drv_ops != NULL && dev->drv_ops->start != NULL) {
178
		ret = dev->drv_ops->start(dev);
179
		if (ret != 0) {
180
			return ret;
181
		}
182
	}
183

184
	dev->flags |= IFF_UP;
185

186
	return 0;
187
}
188

189
int netdev_close(struct net_device *dev) {
190
	int ret;
191

192
	if (dev == NULL) {
193
		return -EINVAL;
194
	}
195

196
	if (!(dev->flags & IFF_UP)) {
197
		return 0;
198
	}
199

200
	if (dev->drv_ops->stop != NULL) {
201
		ret = dev->drv_ops->stop(dev);
202
		if (ret != 0) {
203
			return ret;
204
		}
205
	}
206

207
	dev->flags &= ~IFF_UP;
208

209
	return 0;
210
}
211

212
int netdev_set_macaddr(struct net_device *dev, const void *addr) {
213
	int ret;
214

215
	if ((dev == NULL) || (addr == NULL)) {
216
		return -EINVAL;
217
	}
218

219
	assert(dev->ops != NULL);
220
	if ((dev->ops->check_addr != NULL)
221
			&& !dev->ops->check_addr(addr)) {
222
		return -EINVAL; /* error: bad address */
223
	}
224

225
	assert(dev->drv_ops != NULL);
226
	if (dev->drv_ops->set_macaddr != NULL) {
227
		ret = dev->drv_ops->set_macaddr(dev, addr);
228
		if (ret != 0) {
229
			return ret;
230
		}
231
	}
232

233
	memcpy(&dev->dev_addr[0], addr, dev->addr_len);
234

235
	return 0;
236
}
237

238
int netdev_set_bcastaddr(struct net_device *dev, const void *bcast_addr) {
239
	if ((dev == NULL) || (bcast_addr == NULL)) {
240
		return -EINVAL;
241
	}
242

243
	memcpy(&dev->broadcast[0], bcast_addr, dev->addr_len);
244

245
	return 0;
246
}
247

248
int netdev_flag_up(struct net_device *dev, unsigned int flag) {
249
	int ret;
250

251
	if (dev == NULL) {
252
		return -EINVAL;
253
	}
254

255
	if (dev->flags & flag) {
256
		return 0;
257
	}
258

259
	switch (flag) {
260
	case IFF_UP:
261
		ret = netdev_open(dev);
262
		if (ret != 0) {
263
			return ret;
264
		}
265
		break;
266
	}
267

268
	dev->flags |= flag;
269

270
	return 0;
271
}
272

273
int netdev_flag_down(struct net_device *dev, unsigned int flag) {
274
	int ret;
275

276
	if (dev == NULL) {
277
		return -EINVAL;
278
	}
279

280
	if (!(dev->flags & flag)) {
281
		return 0;
282
	}
283

284
	switch (flag) {
285
	case IFF_UP:
286
		ret = netdev_close(dev);
287
		if (ret != 0) {
288
			return ret;
289
		}
290
		break;
291
	}
292

293
	dev->flags &= ~flag;
294

295
	return 0;
296
}
297

298
int netdev_set_mtu(struct net_device *dev, int mtu) {
299
	if (dev == NULL) {
300
		return -EINVAL;
301
	}
302

303
	assert(dev->ops != NULL);
304
	if ((dev->ops->check_mtu != NULL)
305
			&& !dev->ops->check_mtu(mtu)) {
306
		return -EINVAL; /* error: bad mtu value */
307
	}
308

309
	dev->mtu = mtu;
310

311
	return 0;
312
}
313

314
int netdev_set_baseaddr(struct net_device *dev, unsigned long base_addr) {
315
	if (dev == NULL) {
316
		return -EINVAL;
317
	}
318

319
	dev->base_addr = base_addr;
320

321
	return 0;
322
}
323

324
int netdev_set_irq(struct net_device *dev, int irq_num) {
325
	if (dev == NULL) {
326
		return -EINVAL;
327
	}
328

329
	dev->irq = irq_num;
330

331
	return 0;
332
}
333

334
unsigned int if_nametoindex(const char *name) {
335
	struct net_device *dev;
336

337
	assert(name);
338

339
	dev = netdev_get_by_name(name);
340

341
	if (dev) {
342
		return dev->index;
343
	} else {
344
		errno = ENOENT;
345
		return 0;
346
	}
347
}
348

349
void netif_carrier_on(struct net_device *dev) {
350
	netlink_notify_newlink(dev);
351
}
352

353
void netif_carrier_off(struct net_device *dev) {
354
	netlink_notify_dellink(dev);
355
}
356

357

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.