RIOT-OS / RIOT

RIOT - The friendly OS for IoT
https://riot-os.org
GNU Lesser General Public License v2.1
4.94k stars 1.99k forks source link

Send message from host PC to networking boards via border_router #11534

Closed talalong closed 5 years ago

talalong commented 5 years ago

Setup description:

I have two samr21-xpro boards

I have pinged sam_router <-> sam_node back and forth successfully. And also ping from my host PC <->sam_node via sam_router worked as well.

using ping6 2001:db8::blah::blah

My goal is to send a message from my host PC via sam_router to serveral sam_node(s).

Here is my first though: using udp server start 8080, I can start my sam_nodes to listen to messages from client.(That means sam_nodes are going to burn more power from power supply, prove me wrong pls!)-> First question

Update!

Now, I can send message from host PC to sam_node via sam_router using netcat like nc -6uv 2001:db8::blah::blah 8808 (because ping6 to fe80::ccf5:blah:blah%tap0 8080 did not work for me) And the output from sam_node (server udp) looks like this:

2019-05-18 10:07:27,434 - INFO # 00000000 48 61 6C 6C 6F 6F 6F 6F 6F 6F 6F 6F 6F 6F
6F 2C 2019-05-18 10:07:27,441 - INFO # 00000010 20 77 61 75 72 6D 20 62 69 73 74 20 64 75 20 73 2019-05-18 10:07:27,447 - INFO # 00000020 6F 20 73 63 68 77 65 72 20 7A 75 20 76 65 72 73 2019-05-18 10:07:27,450 - INFO # 00000030 74 65 68 65 6E 0A 2019-05-18 10:07:27,455 - INFO # ~~ SNIP 1 - size: 8 byte, type: NETTYPE_UDP (4) 2019-05-18 10:07:27,458 - INFO # src-port: 49550 dst-port: 8080 2019-05-18 10:07:27,461 - INFO # length: 62 cksum: 0xd823 2019-05-18 10:07:27,465 - INFO # ~~ SNIP 2 - size: 40 byte, type: NETTYPE_IPV6 (2) 2019-05-18 10:07:27,469 - INFO # traffic class: 0x00 (ECN: 0x0, DSCP: 0x00) 2019-05-18 10:07:27,471 - INFO # flow label: 0xf4f20 2019-05-18 10:07:27,475 - INFO # length: 62 next header: 17 hop limit: 63 2019-05-18 10:07:27,478 - INFO # source address: fd00:dead:beef::1 2019-05-18 10:07:27,482 - INFO # destination address: 2001:db8::7b62:311b:efa4:9f9e 2019-05-18 10:07:27,487 - INFO # ~~ SNIP 3 - size: 24 byte, type: NETTYPE_NETIF (-1) 2019-05-18 10:07:27,490 - INFO # if_pid: 7 rssi: -66 lqi: 255 2019-05-18 10:07:27,491 - INFO # flags: 0x0 2019-05-18 10:07:27,494 - INFO # src_l2addr: 79:7D:02:37:27:53:32:B2 2019-05-18 10:07:27,498 - INFO # dst_l2addr: 79:62:31:1B:EF:A4:9F:9E 2019-05-18 10:07:27,501 - INFO # ~~ PKT - 4 snips, total size: 126 byte

-> My second question is: how do I get these messages in main.c ?

If my though is wrong, I would appreciate if you could tell me how I can do it. Thank you! Ps: Im a beginner level at this. :(

taherrera commented 5 years ago

On the first question: I think the consumption is the same, I am not entirelly sure, but I think by default the state of the AT86RF233 (in RIOT implementation) is RX_AACK_ON

Second: The files here should give you a clue on how to get this information on your application: RIOT/sys/net/gnrc/pktdump/*

PeterKietzmann commented 5 years ago

@talalong consumption wise it doesn't make a big difference to open a UDP server or not. If you have strict energy requirements you might rethink some other components though.

ping6 to fe80::ccf5:blah:blah%tap0 8080 did not work

Are you sure that %tap0 is the correct network interface? @smlng didn't we face problems with link local IPv6 Linux - RIOT recently?

how do I get these messages in main.c

You register a UDP server. Have a look at the sock API or the implementation of the gnrc_pktdump module whichw as mentioned by @taherrera. I'd recomment the first option though!

PeterKietzmann commented 5 years ago

PS: Please indicate when your question was answered!

talalong commented 5 years ago

First of all, thank you all for your answers:

Are you sure that %tap0 is the correct network interface?

@PeterKietzmann yes. after connecting sam_border(border_router) to my host pc and calling make term.

using ifconfig here is what I got from my host pc network interface:

ep0s3: ... lo: ... tap0 Link encap:Ethernet HWaddr fa:f8:65:43:2a:a0
inet6 addr: fe80::f8f8:65ff:fe43:2aa0/64 Scope:Link inet6 addr: fe80::1/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:3 errors:0 dropped:0 overruns:0 frame:0 TX packets:11 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:240 (240.0 B) TX bytes:1296 (1.2 KB)

Secondly:

You register a UDP server. Have a look at the sock API or the implementation of the gnrc_pktdump module whichw as mentioned by @taherrera. I'd recomment the first option though!

adding A Simple UDP Echo Server into /gnrc_networking/udp.c, I am able to start my custom server via shell_commands and getting message from udp.c is possible for now. BUT again I have to run this (command below) on my host maschine instead of using fe80::%tap0 in order to send the message successfully. -> Am I wrong? nc -6uv 2001:db8::7b62:311b:efa4:9f9e 8080 And using netcat is also not my goal. I tried to create a client on my host maschine to send a message to the server what I have created on sam_node(gnrc_networking). using this sample code I have found on the internet, but no success. Is it wrong, how I bind the address ?

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <string.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <netinet/in.h> 

#define PORT     8080 
#define MAXLINE 1024 
int main() { 
    int sockfd; 
    char buffer[MAXLINE]; 
    char *hello = "Hello from client"; 
    struct sockaddr_in     servaddr;   
    if ( (sockfd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ) { 
        perror("socket creation failed"); 
        exit(EXIT_FAILURE); 
    } 
    memset(&servaddr, 0, sizeof(servaddr));     
    // Filling server information 
    servaddr.sin_family = AF_INET6; 
    servaddr.sin_port = htons(PORT); 
    //inet_aton("2001:db8::7b62:311b:efa4:9f9e", &servaddr.sin_addr.s_addr);
    servaddr.sin_addr.s_addr = inet_addr("2001:db8::7b62:311b:efa4:9f9e");
    //servaddr.sin_addr.s_addr = //INADDR_ANY;       
    int n, len;      
    sendto(sockfd, (const char *)hello, strlen(hello), 
        MSG_CONFIRM, (const struct sockaddr *) &servaddr,  
            sizeof(servaddr)); 
    printf("Hello message sent.\n");       
    n = recvfrom(sockfd, (char *)buffer, MAXLINE,  
                MSG_WAITALL, (struct sockaddr *) &servaddr, 
                &len); 
    buffer[n] = '\0'; 
    printf("Server : %s\n", buffer);  
    close(sockfd); 
    return 0; 
} 
smlng commented 5 years ago

@talalong your setups sounds good and you got many things right and working all ready.

First, it is correct that you can only ping from host to samr21 node using addresses like 2001:db8::7b62:311b:efa4:9f9e and not fe80::<xyz>. The latter once starting with fe80 are link local addresses and can only be used to communicate a single hop, i.e. from host to router or router to samr21, but not from host to samr21. Addresses like 2001:<abc> are global addresses and hence are routable. I hope that clarifies the addressing.

TL;DR: try to use only global addresses or ULAs (IPv6 addresses for private and testing usage, starting with fc or fd and avoid link local addresses in real deployments. The latter should only be used for network configuration and discovery.

To receive UDP directly in your app you should use thegnrc_sock_udp API, have a look at the test application for some example code. That should get you startet.

talalong commented 5 years ago

@smlng Thank you for making the addressing clear. I have no more questions at this topic, now. So it's time to close it. Thanks again for making this great os.

talalong commented 5 years ago

@PeterKietzmann, @smlng , @taherrera I am sorry, but I have to reopen this question again. Because I have another problem using border_router and networking base on my setup above. I was saying that:

... And also ping from my host PC <-> sam_node via sam_router worked as well.

using ping6 2001:db8::7b62:311b:efa4:9f9e Is not working anymore. Or at least it does not work partially. same setup and same code from gnrc_border_router/ gnrc_networking. What I can do is ping6 to sam_node via sam_routeron my vagrant virtual maschine and NOT from my macOS terminal interface anymore (or was I dreamingT_T ). But I am 70% sure that I was able to ping6 to sam_node on vagrant VM AND on macOS terminal. here is ifconfig on vagrant VM.

vagrant@vagrant:~/Tutorials$ ifconfig enp0s3 Link encap:Ethernet HWaddr 08:00:27:70:75:6c
inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe70:756c/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:4440 errors:0 dropped:0 overruns:0 frame:0 TX packets:3607 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:345724 (345.7 KB) TX bytes:368816 (368.8 KB)

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host inet6 addr: fd00:dead:beef::1/128 Scope:Global UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:9 errors:0 dropped:0 overruns:0 frame:0 TX packets:9 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1 RX bytes:1162 (1.1 KB) TX bytes:1162 (1.1 KB)

tap0 Link encap:Ethernet HWaddr aa:91:87:9f:41:22
inet6 addr: fe80::a891:87ff:fe9f:4122/64 Scope:Link inet6 addr: fe80::1/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:342 errors:0 dropped:0 overruns:0 frame:0 TX packets:349 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:27202 (27.2 KB) TX bytes:29220 (29.2 KB)

Here ifconfig on MacOS:

Tutorials talalong$ ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP> inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=201<PERFORMNUD,DAD> gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 XHC20: flags=0<> mtu 0 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether b8:e8:56:4a:89:1c inet6 fe80::f5:564f:178d:df48%en0 prefixlen 64 secured scopeid 0x5 inet 192.168.1.20 netmask 0xffffff00 broadcast 192.168.1.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active

p2p0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 2304 ether 0a:e8:56:4a:89:1c media: autoselect status: inactive

awdl0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1484 ether da:4a:52:e3:08:4d inet6 fe80::d84a:52ff:fee3:84d%awdl0 prefixlen 64 scopeid 0x7 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active

en1: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=60<TSO4,TSO6> ether 72:00:01:34:03:10 media: autoselect status: inactive

en2: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500 options=60<TSO4,TSO6> ether 72:00:01:34:03:11 media: autoselect status: inactive

bridge0: flags=8822<BROADCAST,SMART,SIMPLEX,MULTICAST> mtu 1500 options=63<RXCSUM,TXCSUM,TSO4,TSO6> ether 72:00:01:34:03:10 Configuration: id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0 maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200 root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0 ipfilter disabled flags 0x2 member: en1 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 8 priority 0 path cost 0 member: en2 flags=3<LEARNING,DISCOVER> ifmaxaddr 0 port 9 priority 0 path cost 0 media: status: inactive --> why is that inactive?

utun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 2000 inet6 fe80::221e:b0b6:37e7:49f4%utun0 prefixlen 64 scopeid 0xb nd6 options=201<PERFORMNUD,DAD> utun2: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380 inet6 fe80::1324:90a6:d38e:2b56%utun2 prefixlen 64 scopeid 0xd nd6 options=201<PERFORMNUD,DAD> utun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1380 inet6 fe80::4275:2137:d490:2794%utun1 prefixlen 64 scopeid 0xe nd6 options=201<PERFORMNUD,DAD>

benemorius commented 5 years ago

I don't think you'd have ever been able to ping the border router or end device from macos unless you added a route to macos to tell it to reach 2001:db8::/64 via fe80::a00:27ff:fe70:756c on whichever interface in macos corresponds to that address on the vagrant side. I'm less familiar with vagrant and macos and it isn't obvious to me from the list of macos interfaces which is the right one. If you can successfully ping fe80::a00:27ff:fe70:756c%interface from macos then you've found the right interface.

Adding a route on macos goes something like route add -inet6 2001:db8::/64 fe80::a00:27ff:fe70:756c -interface <interface> but I don't have a macos accessible to test that syntax right now.

I've assumed that interface enp0s3 on vagrant is the correct interface to reach macos. If that's wrong then the correct interface is actually missing.

Also it's helpful in addition to ifconfig output to have the routing tables from each host. It's ip -6 r on linux and netstat -r -f inet6 on macos.

Take note that the addresses I've quoted from you may have changed next time you restart things.

talalong commented 5 years ago

@benemorius thanks for your answer. I did try to ping to fe80::a00:27ff:fe70:756c% with all interfaces I have on macOS. But I failed. Let me explain you a little bit what I wanted to do: The reason why I want to ping6 to my end devices via border_router which running on vagrant VM from macOS, is that I have nodeJS application, which send a text message (using udp program) to end device (sam_node) via border_router. The problem is NodeJs is running on macOS and Riot-Os is running on vagrant VM. (because running Riot-os on macOs was failed to me) So that's why I need the connection between vagrant and macOS. Would It be much easier, if I install linux and run both RIOT-OS and NodeJs, so that they can be on the same network?

benemorius commented 5 years ago

I was not satisfied to encourage you to fundamentally change your setup just because I didn't understand your setup. I have duplicated your vagrant/macos setup to find out just what a working vagrant setup is actually supposed to look like in the first place.

Would It be much easier, if I install linux and run both RIOT-OS and NodeJs, so that they can be on the same network?

Actually, yes. I found that Riot's vagrant configuration isn't compatible to support routing traffic past the vagrant guest linux to the vagrant host OS, thus it is not compatible to use with a border router. Probably this is just a little oversight that no one has taken notice of yet. For now, I'd recommend a setup that has nodejs and Riot's start_network.sh both running on the same linux machine, at least initially so that you can minimize the variables to arrive at a working prototype before converting it as necessary into something that better suits your needs.

However in order to come to that conclusion it was necessary to understand what was actually keeping the setup from working, and indeed I was able to get the setup working with two important changes:

1) Add config.vm.network "public_network" to RIOT/Vagrantfile (see here). By default vagrant only sets up a NAT interface from guest to host, and in fact this is managed/routed/nat'd internally within virtualbox and this is why we could find no macos interface that was able to pass traffic to the vagrant guest linux. (Confusing! But actually normal for all virtualization softwares as a safe/secure default.) Adding this line to the configuration results in an additional interface being configured in the vagrant guest linux which is bridged to whichever macos interface is connected to your LAN (in your case en0 which I believe is the wifi interface) which will make the vagrant guest linux appear on the LAN as if it had its own wifi interface. Now you can ping6 fe80::a00:27ff:fe70:756c%en0 from macos (indeed from anywhere on the LAN) and it should work, although surely the address will be different this time.

1) Enable ipv6 forwarding on the vagrant guest linux with sysctl net.ipv6.conf.all.forwarding=1. Actually the start_network.sh script should be doing this and until now I was sure that it did. In the linux kernel we can't actually enable ipv6 forwarding on only select interfaces as start_network.sh appears to be trying to do. Forwarding is always disabled if all.forwarding isn't enabled, no matter whether it's enabled for specific interfaces. If you think that's counterintuitive, you aren't alone.

With these changes, it should put you in the situation which I believed you were in when I first replied, which is that you need only to configure a couple of routes: 1) On macos route add -inet6 2001:db8::/64 fe80::a00:27ff:fe70:756c%en0 1) On vagrant linux: Since your ISP (or at least your LAN) has no ipv6 it might be easiest (my setup was not a 100% duplicate of yours unfortunately, as I have ipv6) to just put a default route back to macos with something like ip route add default via fe80::f5:564f:178d:df48 dev enp0s8. Also I've just realized you'll probably need to add a non-link-local ipv6 address to macos or else it will not have a source ip address to use when sending packets past the vagrant guest linux to the samr21 Riot border router node.

I didn't double-check all of these commands and statements as well as I'd have liked. Please don't assume I made no errors or omissions.

Also apparently the ubuntu version we're using for vagrant is so old that we must indeed use ping6 instead of ping which took me quite too long to realize.

talalong commented 5 years ago

Hi @benemorius I am very appreciate your help. And also sorry for the late response, because I did try to understand what you pointed at. I did follow your steps and realized that I could only ping to fe80::a891:87ff:fe9f:4122 via tap0 interface instead of fe80::a00:27ff:fe70:756c. But the next steps were not successful with some weird errors. So to make my life easier I installed Ubuntu and I works like expected. Again thank you so much for your partically comments.