Jump to content

    

SLIP в Linux: простой обмен между устройствами

3 hours ago, Arlleex said:

Вот тут, если можно, подробнее.

а вам это действительно нужно ? у меня сложилось впечатление что нет

3 hours ago, Arlleex said:

Допустим, моя железка отправляет фрейм "C0 12 34 56 78 C0".

Какой путь проделает этот фрейм от входа UART на Linux-борде до получения буфера с данными "12 34 56 78" в линушном приложении? 

slattach зарегистрирует калбэк в драйвере tty выбранного уарта, например

 

slattach -p slip -s 115200 /dev/ttyS0 &

 

принятые данные этого уарта пойдут не в юзерспейс а в ф-цию  slip_receive_buf

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L682

эта ф-ция побайтно обработает принятый буфер

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L711

отыщет начало и конец, заменит экранированные байты и в свой внутренний буфер попадет уже 12 34 56 78, когда найдет  конец фрейма - скопирует свой внутренний буфер в буфер skb

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L968

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L319

и этот буфер вы и получите  при чтении из raw socketa

3 hours ago, Arlleex said:

И наоборот: допустим, хочу отправить с Linux-машины данные "00 AB CD EF" на свой девайс.

Какой путь проделают эти данные до инкапсуляции в кадр "C0 00 AB CD EF C0" и вывода его на лапку Tx UART-модуля этой самой Linux-борды? 

 

при записи в raw socket буфер skb минует сетевой стек и попадёт на вход ф-ции sl_xmit без обработки

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L499

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L520

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L375

тут непосредственно инкапсуляция в SLIP

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L397

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L918

тут запись в в порт tty уже готового фрейма SLIP

https://elixir.bootlin.com/linux/v5.5.6/source/drivers/net/slip/slip.c#L408

 

ключевой момент - надо биндить raw socket на конкретный сетевой интерфейс

 

http://www.microhowto.info/howto/capture_ethernet_frames_using_an_af_packet_socket_in_c.html#idp61712

 

в примере в общем все что надо есть правда там не raw socket а packet socket называют

Edited by sasamy

Share this post


Link to post
Share on other sites
9 часов назад, Arlleex сказал:

Потому что к текущему моменту уже написали (вроде как) самописный парсер SLIP.

Я читаю и честно никак не могу понять: Участники этого треда - прикалываются что-ль? :sarcastic_hand:  Уже пошла 4-я страница обсуждения. В то время как сам парсер SLIP - это 10 строчек кода на передачу и немного больше на приём. Что уже больше чем в 10 раз меньше здесь понаписали.

А если кто-то там не может реализовать такой элементарный парсер, то такого человека даже программистом назвать нельзя. Ну что-ж поделать - не всем дано.  :unknw:

Share this post


Link to post
Share on other sites
8 часов назад, sasamy сказал:

...slattach зарегистрирует калбэк в драйвере tty выбранного уарта, например...

Полагаю, заказчику это должно было быть известно...

Я бы ради интереса уже сам потестировал, будь у меня какая-нибудь борда с Linux-ой и свободное время.

Спасибо за пояснения.

 

1 час назад, jcxz сказал:

...В то время как сам парсер SLIP - это 10 строчек кода на передачу и немного больше на приём...

Я это прекрасно понимаю.

 

1 час назад, jcxz сказал:

А если кто-то там не может реализовать такой элементарный парсер, то такого человека даже программистом назвать нельзя...

И это понимаю. Но от того, что кого-то там нельзя назвать программистом лично мне лучше не станет.

Ваше недоумение вполне понятно. У меня тоже быстро припекает с таких раскладов, но что есть то есть.

Share this post


Link to post
Share on other sites
1 час назад, Arlleex сказал:

Я бы ради интереса уже сам потестировал, будь у меня какая-нибудь борда с Linux-ой и свободное время.

Virtualbox ставится за 15 минут вместе со скачиванием. Еще 15 минут туда ставится линух со скачанного образа установочного диска (из них 14 минут процесс идет сам по себе). Имеете практически полноценный комп с линухом в отдельном окне. В виртуальную машину пробрасывается либо "железный" последовательный порт компа, либо USB и воткнутый в него переходник USB-RS232. Экспериментируйте по самое "не хочу". В любой момент можно делать снимки работающей системы, чтобы при необходимости в любой момент откатиться к любому из них.

Share this post


Link to post
Share on other sites
On 2/25/2020 at 9:38 AM, Arlleex said:

Я бы ради интереса уже сам потестировал, будь у меня какая-нибудь борда с Linux-ой и свободное время.

Потестировал у себя, если еще интересно. Чтение SLIP

sl_read.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
	struct ifreq ifr = {0};
	struct sockaddr_ll addr = {0};
	char buf[4096];
	ssize_t n;

	int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (fd == -1) {
		perror("socket");
		exit(1);
	}

	strncpy(ifr.ifr_name, "sl0", sizeof(ifr.ifr_name));
	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
		perror("ioctl");
		exit(1);
	}

	addr.sll_family = AF_PACKET;
	addr.sll_ifindex = ifr.ifr_ifindex;
	addr.sll_protocol = htons(ETH_P_ALL);
	if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		perror("bind");
		exit(1);
	}

	while (1) {
		n = read(fd, buf, sizeof(buf) - 1);
		if (n == -1) {
			perror("read");
			exit(1);
		}
		buf[n] = 0;
		printf("received %li bytes: %s\n", n, buf);
	}

	return 0;
}

 

Передача SLIP

sl_write.c

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
	struct ifreq ifr = {0};
	struct sockaddr_ll addr = {0};
	char buf[4096];
	ssize_t n;

	int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (fd == -1) {
		perror("socket");
		exit(1);
	}

	strncpy(ifr.ifr_name, "sl0", sizeof(ifr.ifr_name));
	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
		perror("ioctl");
		exit(1);
	}

	addr.sll_family = AF_PACKET;
	addr.sll_ifindex = ifr.ifr_ifindex;
	addr.sll_protocol = htons(ETH_P_ALL);
	if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
		perror("bind");
		exit(1);
	}

	n = read(STDIN_FILENO, buf, sizeof(buf));
	if (n == -1) {
		perror("read");
		exit(1);
	}
	
	if (write(fd, buf, n) == -1) {
		perror("write");
		exit(1);
	}

	return 0;
}

Команды выполняются с правами root

На стороне передачи пакетов - плата с imx8mm.

В терминале настроил SLIP для uart-a ttymxc1

# slattach -p slip -s 115200 /dev/ttymxc1 &
# ifconfig sl0 up

Передавал данные такой командой

# printf "123456" | sl_write

На стороне приема пакетов - PC с преобразователем USB-serial

Сначала чтение  "сырых" данных напрямую с uarta

# cat /dev/ttyUSB0 | xxd -g1 -c8
00000000: c0 31 32 33 34 35 36 c0  .123456.

Потом настроил  SLIP для uart-a ttyUSB0

# slattach -p slip -s 115200 /dev/ttyUSB0 &
# ifconfig sl0 up

Прием декапсулированных данных

# sl_read
received 6 bytes: 123456
received 6 bytes: 123456

 

Share this post


Link to post
Share on other sites
5 минут назад, sasamy сказал:

Потестировал у себя, если еще интересно. Чтение SLIP...

Пока что самописное у товарища работает. Ваш вариант сохраню как резервный путь.

Если до этого еще раз дойдет, лично все потестирую и покажу (товарищу), что все работает.

Вам персонально выражаю благодарность за потраченное время:smile:

Share this post


Link to post
Share on other sites
On 2/22/2020 at 6:38 PM, Arlleex said:

В том и дело...

 

Опыта. Я на МК написал, на ПК написал и проверил, что все огонь. За кого-то писать не собираюсь, максимум - вразумить каким-то образом и направить в нужное русло.

К сожалению, система построена так, что прогнуться придется мне, если товарищ линуксоид не поднимет сраный UART на своей борде.

Это, конечно, жутко бесит, но деваться некуда. Как оказалось, "я доверяю всему готовому и не доверяю самодельному коду" (с):biggrin::buba:

Ппц, у меня панический смех:focus:

не уверен, но SLIP это кажется практически то же самое, что и Wake, :acute:реализация которого описана Леонидом  Ивановичем, правда для МК и для РС под виндой. Если это так, могу прислать свою версию (правильнее сказать, что она практически его, Леонида Ивановича, я внес незначительные правки), для линукса, Qt.

Edited by nanorobot

Share this post


Link to post
Share on other sites
4 часа назад, nanorobot сказал:

не уверен, но SLIP это кажется практически то же самое, что и Wake...

Wake это небольшой протокол над SLIP-ом, реализующий адресный обмен.

Мне оно не надо, тем более sasamy привел вменяемый пример. Спасибо:smile:

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now