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