embox

Форк
0
219 строк · 4.4 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @author  Anton Kozlov
6
 * @date    21.07.2014
7
 */
8

9
#include <errno.h>
10
#include <stddef.h>
11
#include <stdio.h>
12
#include <string.h>
13
#include <sys/types.h>
14

15
#include <drivers/char_dev.h>
16
#include <embox/unit.h>
17
#include <kernel/sched/sched_lock.h>
18
#include <kernel/sched/waitq.h>
19
#include <kernel/task/resource/idesc.h>
20
#include <kernel/thread.h>
21
#include <kernel/thread/sync/mutex.h>
22
#include <kernel/thread/thread_sched_wait.h>
23
#include <net/inetdevice.h>
24
#include <net/l0/net_entry.h>
25
#include <net/l2/ethernet.h>
26
#include <net/l3/arp.h>
27
#include <net/netdevice.h>
28
#include <util/err.h>
29
#include <util/math.h>
30

31
struct tun_dev {
32
	struct char_dev cdev;
33
	struct net_device *netdev;
34
	struct mutex mtx_use;
35
	struct sk_buff_head rx_q;
36
	struct waitq wq;
37
};
38

39
EMBOX_UNIT_INIT(tun_dev_init);
40

41
static inline void tun_krnl_lock(struct tun_dev *tun) {
42
	sched_lock();
43
}
44

45
static inline void tun_krnl_unlock(struct tun_dev *tun) {
46
	sched_unlock();
47
}
48

49
static inline void tun_user_lock(struct tun_dev *tun) {
50
	mutex_lock(&tun->mtx_use);
51
}
52

53
static inline void tun_user_unlock(struct tun_dev *tun) {
54
	mutex_unlock(&tun->mtx_use);
55
}
56

57
static int tun_open(struct net_device *dev) {
58
	return 0;
59
}
60

61
static int tun_set_mac(struct net_device *dev, const void *addr) {
62
	memcpy(dev->dev_addr, addr, ETH_ALEN);
63
	return ENOERR;
64
}
65

66
static int tun_xmit(struct net_device *dev, struct sk_buff *skb) {
67
	struct tun_dev *tun = netdev_priv(dev);
68
	struct ethhdr *ethh;
69

70
	/* we don't build headers for dev with NOARP flag */
71
	ethh = eth_hdr(skb);
72
	ethh->h_proto = htons(ETH_P_IP);
73
	memcpy(ethh->h_source, skb->dev->dev_addr, ETH_ALEN);
74
	memset(ethh->h_dest, 0, ETH_ALEN);
75

76
	skb_queue_push(&tun->rx_q, skb);
77
	waitq_wakeup(&tun->wq, 1);
78
	return 0;
79
}
80

81
static const struct net_driver tun_netdrv_ops = {
82
    .xmit = tun_xmit,
83
    .start = tun_open,
84
    .set_macaddr = tun_set_mac,
85
};
86

87
static int tun_setup(struct net_device *dev) {
88
	dev->mtu = (16 * 1024) + 20 + 20 + 12;
89
	dev->hdr_len = ETH_HEADER_SIZE;
90
	dev->addr_len = ETH_ALEN;
91
	dev->type = ARP_HRD_LOOPBACK;
92
	dev->flags = IFF_NOARP | IFF_RUNNING;
93
	dev->drv_ops = &tun_netdrv_ops;
94
	dev->ops = &ethernet_ops;
95
	return 0;
96
}
97

98
static int tun_dev_open(struct char_dev *cdev, struct idesc *idesc) {
99
	assert(cdev);
100

101
	tun_user_lock((struct tun_dev *)cdev);
102

103
	return 0;
104
}
105

106
static void tun_dev_close(struct char_dev *cdev) {
107
	assert(cdev);
108

109
	tun_user_unlock((struct tun_dev *)cdev);
110
}
111

112
static ssize_t tun_dev_read(struct char_dev *cdev, void *buf, size_t nbyte) {
113
	struct waitq_link *wql = &thread_self()->schedee.waitq_link;
114
	struct tun_dev *tun;
115
	struct sk_buff *skb;
116
	int ret = 0;
117
	int min_len;
118

119
	assert(cdev);
120

121
	tun = (struct tun_dev *)cdev;
122

123
	waitq_link_init(wql);
124
	do {
125
		tun_krnl_lock(tun);
126
		{
127
			waitq_wait_prepare(&tun->wq, wql);
128
			skb = skb_queue_pop(&tun->rx_q);
129
		}
130
		tun_krnl_unlock(tun);
131

132
		if (skb) {
133
			min_len = min(skb->len, nbyte);
134
			if (min_len > 0) {
135
				memcpy(buf, skb->mac.raw, min_len);
136
				ret = min_len;
137
			}
138
			break;
139
		}
140
		else {
141
			ret = sched_wait_timeout(SCHED_TIMEOUT_INFINITE, NULL);
142
		}
143
	} while (ret == 0);
144
	waitq_wait_cleanup(&tun->wq, wql);
145

146
	return ret;
147
}
148

149
static ssize_t tun_dev_write(struct char_dev *cdev, const void *buf,
150
    size_t nbyte) {
151
	struct net_device *netdev;
152
	struct tun_dev *tun;
153
	struct sk_buff *skb;
154
	unsigned char *raw;
155
	struct ethhdr *ethh;
156

157
	assert(cdev);
158

159
	tun = (struct tun_dev *)cdev;
160
	netdev = tun->netdev;
161

162
	skb = skb_alloc(nbyte + ETH_HLEN);
163
	if (!skb) {
164
		return -ENOMEM;
165
	}
166

167
	ethh = eth_hdr(skb);
168

169
	ethh->h_proto = htons(ETH_P_IP);
170
	memcpy(ethh->h_dest, netdev->dev_addr, ETH_ALEN);
171
	memset(ethh->h_source, 0, ETH_ALEN);
172

173
	raw = skb->mac.raw + ETH_HLEN;
174
	memcpy(raw, buf, nbyte);
175

176
	skb->dev = netdev;
177
	netif_rx(skb);
178

179
	return nbyte;
180
}
181

182
static const struct char_dev_ops tun_dev_ops = {
183
    .read = tun_dev_read,
184
    .write = tun_dev_write,
185
    .open = tun_dev_open,
186
    .close = tun_dev_close,
187
};
188

189
static struct tun_dev tun_dev = {
190
    .cdev = CHAR_DEV_INIT(tun_dev.cdev, "tun0", &tun_dev_ops),
191
};
192

193
CHAR_DEV_REGISTER((struct char_dev *)&tun_dev);
194

195
static int tun_dev_init(void) {
196
	struct net_device *netdev;
197
	int err;
198

199
	assert(strlen(tun_dev.cdev.name) < IFNAMSIZ);
200

201
	netdev = netdev_alloc(tun_dev.cdev.name, &tun_setup, 0);
202
	if (netdev == NULL) {
203
		return -ENOMEM;
204
	}
205

206
	if ((err = inetdev_register_dev(netdev))) {
207
		netdev_free(netdev);
208
		return err;
209
	}
210

211
	mutex_init(&tun_dev.mtx_use);
212
	waitq_init(&tun_dev.wq);
213
	skb_queue_init(&tun_dev.rx_q);
214

215
	tun_dev.netdev = netdev;
216
	netdev->priv = &tun_dev;
217

218
	return 0;
219
}
220

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

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

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

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