1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 *
10 * SLIP driver using uart_pipe. This is meant for network connectivity between
11 * host and qemu. The host will need to run tunslip process.
12 */
13
14 #define LOG_MODULE_NAME slip
15 #define LOG_LEVEL CONFIG_SLIP_LOG_LEVEL
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
19
20 #include <stdio.h>
21
22 #include <zephyr/kernel.h>
23
24 #include <errno.h>
25 #include <stddef.h>
26 #include <zephyr/sys/util.h>
27 #include <zephyr/net/ethernet.h>
28 #include <zephyr/net/net_core.h>
29 #include <zephyr/net/dummy.h>
30 #include <zephyr/drivers/uart_pipe.h>
31 #include <zephyr/random/random.h>
32
33 #include "slip.h"
34
35 #define SLIP_END 0300
36 #define SLIP_ESC 0333
37 #define SLIP_ESC_END 0334
38 #define SLIP_ESC_ESC 0335
39
40 enum slip_state {
41 STATE_GARBAGE,
42 STATE_OK,
43 STATE_ESC,
44 };
45
46 #if defined(CONFIG_NET_BUF_FIXED_DATA_SIZE)
47 #define SLIP_FRAG_LEN CONFIG_NET_BUF_DATA_SIZE
48 #else
49 #define SLIP_FRAG_LEN _SLIP_MTU
50 #endif /* CONFIG_NET_BUF_FIXED_DATA_SIZE */
51
slip_writeb(unsigned char c)52 static inline void slip_writeb(unsigned char c)
53 {
54 uint8_t buf[1] = { c };
55
56 uart_pipe_send(&buf[0], 1);
57 }
58
59 /**
60 * @brief Write byte to SLIP, escape if it is END or ESC character
61 *
62 * @param c a byte to write
63 */
slip_writeb_esc(unsigned char c)64 static void slip_writeb_esc(unsigned char c)
65 {
66 switch (c) {
67 case SLIP_END:
68 /* If it's the same code as an END character,
69 * we send a special two character code so as
70 * not to make the receiver think we sent
71 * an END.
72 */
73 slip_writeb(SLIP_ESC);
74 slip_writeb(SLIP_ESC_END);
75 break;
76 case SLIP_ESC:
77 /* If it's the same code as an ESC character,
78 * we send a special two character code so as
79 * not to make the receiver think we sent
80 * an ESC.
81 */
82 slip_writeb(SLIP_ESC);
83 slip_writeb(SLIP_ESC_ESC);
84 break;
85 default:
86 slip_writeb(c);
87 }
88 }
89
slip_send(const struct device * dev,struct net_pkt * pkt)90 int slip_send(const struct device *dev, struct net_pkt *pkt)
91 {
92 struct net_buf *buf;
93 uint8_t *ptr;
94 uint16_t i;
95 uint8_t c;
96
97 ARG_UNUSED(dev);
98
99 if (!pkt->buffer) {
100 /* No data? */
101 return -ENODATA;
102 }
103
104 slip_writeb(SLIP_END);
105
106 for (buf = pkt->buffer; buf; buf = buf->frags) {
107 ptr = buf->data;
108 for (i = 0U; i < buf->len; ++i) {
109 c = *ptr++;
110 slip_writeb_esc(c);
111 }
112
113 if (LOG_LEVEL >= LOG_LEVEL_DBG) {
114 LOG_DBG("sent data %d bytes", buf->len);
115
116 if (buf->len) {
117 LOG_HEXDUMP_DBG(buf->data,
118 buf->len, "<slip ");
119 }
120 }
121 }
122
123 slip_writeb(SLIP_END);
124
125 return 0;
126 }
127
slip_poll_handler(struct slip_context * slip)128 static struct net_pkt *slip_poll_handler(struct slip_context *slip)
129 {
130 if (slip->last && slip->last->len) {
131 return slip->rx;
132 }
133
134 return NULL;
135 }
136
get_iface(struct slip_context * context,uint16_t vlan_tag)137 static inline struct net_if *get_iface(struct slip_context *context,
138 uint16_t vlan_tag)
139 {
140 #if defined(CONFIG_NET_VLAN)
141 struct net_if *iface;
142
143 iface = net_eth_get_vlan_iface(context->iface, vlan_tag);
144 if (!iface) {
145 return context->iface;
146 }
147
148 return iface;
149 #else
150 ARG_UNUSED(vlan_tag);
151
152 return context->iface;
153 #endif
154 }
155
process_msg(struct slip_context * slip)156 static void process_msg(struct slip_context *slip)
157 {
158 uint16_t vlan_tag = NET_VLAN_TAG_UNSPEC;
159 struct net_pkt *pkt;
160
161 pkt = slip_poll_handler(slip);
162 if (!pkt || !pkt->buffer) {
163 return;
164 }
165
166 #if defined(CONFIG_NET_VLAN)
167 {
168 struct net_eth_hdr *hdr = NET_ETH_HDR(pkt);
169
170 if (ntohs(hdr->type) == NET_ETH_PTYPE_VLAN) {
171 struct net_eth_vlan_hdr *hdr_vlan =
172 (struct net_eth_vlan_hdr *)NET_ETH_HDR(pkt);
173
174 net_pkt_set_vlan_tci(pkt, ntohs(hdr_vlan->vlan.tci));
175 vlan_tag = net_pkt_vlan_tag(pkt);
176 }
177 }
178 #endif
179
180 if (net_recv_data(get_iface(slip, vlan_tag), pkt) < 0) {
181 net_pkt_unref(pkt);
182 }
183
184 slip->rx = NULL;
185 slip->last = NULL;
186 }
187
slip_input_byte(struct slip_context * slip,unsigned char c)188 static inline int slip_input_byte(struct slip_context *slip,
189 unsigned char c)
190 {
191 switch (slip->state) {
192 case STATE_GARBAGE:
193 if (c == SLIP_END) {
194 slip->state = STATE_OK;
195 }
196
197 return 0;
198 case STATE_ESC:
199 if (c == SLIP_ESC_END) {
200 c = SLIP_END;
201 } else if (c == SLIP_ESC_ESC) {
202 c = SLIP_ESC;
203 } else {
204 slip->state = STATE_GARBAGE;
205 SLIP_STATS(slip->garbage++);
206 return 0;
207 }
208
209 slip->state = STATE_OK;
210
211 break;
212 case STATE_OK:
213 if (c == SLIP_ESC) {
214 slip->state = STATE_ESC;
215 return 0;
216 }
217
218 if (c == SLIP_END) {
219 slip->state = STATE_OK;
220 slip->first = false;
221
222 if (slip->rx) {
223 return 1;
224 }
225
226 return 0;
227 }
228
229 if (slip->first && !slip->rx) {
230 /* Must have missed buffer allocation on first byte. */
231 return 0;
232 }
233
234 if (!slip->first) {
235 slip->first = true;
236
237 slip->rx = net_pkt_rx_alloc_on_iface(slip->iface,
238 K_NO_WAIT);
239 if (!slip->rx) {
240 LOG_ERR("[%p] cannot allocate pkt", slip);
241 return 0;
242 }
243
244 slip->last = net_pkt_get_frag(slip->rx, SLIP_FRAG_LEN,
245 K_NO_WAIT);
246 if (!slip->last) {
247 LOG_ERR("[%p] cannot allocate 1st data buffer",
248 slip);
249 net_pkt_unref(slip->rx);
250 slip->rx = NULL;
251 return 0;
252 }
253
254 net_pkt_append_buffer(slip->rx, slip->last);
255 slip->ptr = net_pkt_ip_data(slip->rx);
256 }
257
258 break;
259 }
260
261 /* It is possible that slip->last is not set during the startup
262 * of the device. If this happens do not continue and overwrite
263 * some random memory.
264 */
265 if (!slip->last) {
266 return 0;
267 }
268
269 if (!net_buf_tailroom(slip->last)) {
270 /* We need to allocate a new buffer */
271 struct net_buf *buf;
272
273 buf = net_pkt_get_reserve_rx_data(SLIP_FRAG_LEN, K_NO_WAIT);
274 if (!buf) {
275 LOG_ERR("[%p] cannot allocate next data buf", slip);
276 net_pkt_unref(slip->rx);
277 slip->rx = NULL;
278 slip->last = NULL;
279
280 return 0;
281 }
282
283 net_buf_frag_insert(slip->last, buf);
284 slip->last = buf;
285 slip->ptr = slip->last->data;
286 }
287
288 /* The net_buf_add_u8() cannot add data to ll header so we need
289 * a way to do it.
290 */
291 if (slip->ptr < slip->last->data) {
292 *slip->ptr = c;
293 } else {
294 slip->ptr = net_buf_add_u8(slip->last, c);
295 }
296
297 slip->ptr++;
298
299 return 0;
300 }
301
recv_cb(uint8_t * buf,size_t * off)302 static uint8_t *recv_cb(uint8_t *buf, size_t *off)
303 {
304 struct slip_context *slip =
305 CONTAINER_OF(buf, struct slip_context, buf[0]);
306 size_t i;
307
308 if (!slip->init_done) {
309 *off = 0;
310 return buf;
311 }
312
313 for (i = 0; i < *off; i++) {
314 if (slip_input_byte(slip, buf[i])) {
315
316 if (LOG_LEVEL >= LOG_LEVEL_DBG) {
317 struct net_buf *rx_buf = slip->rx->buffer;
318 int bytes = net_buf_frags_len(rx_buf);
319 int count = 0;
320
321 while (bytes && rx_buf) {
322 char msg[6 + 10 + 1];
323
324 snprintk(msg, sizeof(msg),
325 ">slip %2d", count);
326
327 LOG_HEXDUMP_DBG(rx_buf->data, rx_buf->len,
328 msg);
329
330 rx_buf = rx_buf->frags;
331 count++;
332 }
333
334 LOG_DBG("[%p] received data %d bytes", slip,
335 bytes);
336 }
337
338 process_msg(slip);
339 break;
340 }
341 }
342
343 *off = 0;
344
345 return buf;
346 }
347
slip_init(const struct device * dev)348 int slip_init(const struct device *dev)
349 {
350 struct slip_context *slip = dev->data;
351
352 LOG_DBG("[%p] dev %p", slip, dev);
353
354 slip->state = STATE_OK;
355 slip->rx = NULL;
356 slip->first = false;
357
358 #if defined(CONFIG_SLIP_TAP) && defined(CONFIG_NET_IPV4)
359 LOG_DBG("ARP enabled");
360 #endif
361
362 uart_pipe_register(slip->buf, sizeof(slip->buf), recv_cb);
363
364 return 0;
365 }
366
slip_get_mac(struct slip_context * slip)367 static inline struct net_linkaddr *slip_get_mac(struct slip_context *slip)
368 {
369 slip->ll_addr.addr = slip->mac_addr;
370 slip->ll_addr.len = sizeof(slip->mac_addr);
371
372 return &slip->ll_addr;
373 }
374
slip_iface_init(struct net_if * iface)375 void slip_iface_init(struct net_if *iface)
376 {
377 struct slip_context *slip = net_if_get_device(iface)->data;
378 struct net_linkaddr *ll_addr;
379
380 #if defined(CONFIG_SLIP_TAP) && defined(CONFIG_NET_L2_ETHERNET)
381 ethernet_init(iface);
382 #endif
383
384 #if defined(CONFIG_NET_LLDP)
385 net_lldp_set_lldpdu(iface);
386 #endif
387
388 if (slip->init_done) {
389 return;
390 }
391
392 ll_addr = slip_get_mac(slip);
393
394 slip->init_done = true;
395 slip->iface = iface;
396
397 if (CONFIG_SLIP_MAC_ADDR[0] != 0) {
398 if (net_bytes_from_str(slip->mac_addr, sizeof(slip->mac_addr),
399 CONFIG_SLIP_MAC_ADDR) < 0) {
400 goto use_random_mac;
401 }
402 } else {
403 use_random_mac:
404 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
405 slip->mac_addr[0] = 0x00;
406 slip->mac_addr[1] = 0x00;
407 slip->mac_addr[2] = 0x5E;
408 slip->mac_addr[3] = 0x00;
409 slip->mac_addr[4] = 0x53;
410 slip->mac_addr[5] = sys_rand8_get();
411 }
412 net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len,
413 NET_LINK_ETHERNET);
414 }
415
416
417 #if !defined(CONFIG_SLIP_TAP)
418 static struct slip_context slip_context_data;
419
420 static const struct dummy_api slip_if_api = {
421 .iface_api.init = slip_iface_init,
422
423 .send = slip_send,
424 };
425
426 #define _SLIP_L2_LAYER DUMMY_L2
427 #define _SLIP_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
428
429 NET_DEVICE_INIT(slip, CONFIG_SLIP_DRV_NAME, slip_init, NULL,
430 &slip_context_data, NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
431 &slip_if_api, _SLIP_L2_LAYER, _SLIP_L2_CTX_TYPE, _SLIP_MTU);
432 #endif
433