Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Jul 2020 20:21:06 +0200
From:      Bernd Walter <ticso@cicely7.cicely.de>
To:        Michael Tuexen <Michael.Tuexen@lurchi.franken.de>
Cc:        ticso@cicely.de, freebsd-net@freebsd.org, Bernd Walter <ticso@cicely7.cicely.de>
Subject:   Re: SCTP problem, how to debug?
Message-ID:  <20200717182106.GC79604@cicely7.cicely.de>
In-Reply-To: <20200717175055.GB79604@cicely7.cicely.de>
References:  <20200717160739.GA79604@cicely7.cicely.de> <EE7DEB1F-D941-4FC2-91FB-7A1A3D3E11C3@lurchi.franken.de> <20200717175055.GB79604@cicely7.cicely.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Jul 17, 2020 at 07:50:55PM +0200, Bernd Walter wrote:
> On Fri, Jul 17, 2020 at 07:27:00PM +0200, Michael Tuexen wrote:
> > 
> > 
> > > On 17. Jul 2020, at 18:07, Bernd Walter <ticso@cicely7.cicely.de> wrote:
> > > 
> > > I'm running an LED matrix with SCTP.
> > > The matrix consists from 24 raspberry pi running NFS-root FreeBSD
> > > 12.0-RELEASE (they have an SD card for u-boot and loader).
> > > A client system is running FreeBSD 12.1-RELEASE.
> > I fixed iterator related bugs and this was MFCed to stable/12 recently.
> > The problem was that the iterator stopped sending.
> 
> The client side should be easy to update.
> The modules can be a bit more tricky, but I will try.
> 
> > > 
> > > The matrix modules have a one to many service socket.
> > > The daemon regularily sends status informations (temperature, etc.) to
> > > each association and has a second thread to receive.
> > > 
> > > The client system has two deamons running.
> > > 
> > > One daemon is to control power output related to temperature states.
> > > It has one thread reestablishing associations via sctp_connectx() to
> > > each of the 24 modules using a single one to many socket.
> > > Another thread collects all regular received data and updates stored
> > > values.
> > > Yet another thread sends power control data via SCTP_SENDALL, so that all modules know
> > > the maxed allowed brightness rating.
> > > 
> > > The other daemon uses the same threads to reconnect and receive.
> > > It connects to the very same sockets on the modules.
> > > Another thread updates picture data and wanted power rating.
> > > That is sending picture data to the given matrix module and then
> > > SCTP_SENDALL an update trigger to all modules.
> > > That is reduced brightness at night times, ...
> > > 
> > > All SCTP_SENDALL are just trigger with 0 length and different ppid values.
> > Are you really sending messages of length 0? That shouldn't work...
> 
> No - I was wrong.
> Just checked and I do send a dummy byte:
> void
> apa_push_leds()
> {
>         // send dummy content, because we wouldn't send anything without
>         char message = 0;
>         send_message(&message, 1, 0, 0x00000002, SCTP_SENDALL);
> }
> 
> send_message(const void* data, size_t len, uint32_t stream, uint32_t ppid, uint32_t flags, const String& dest = "")
> {
>         Mutex::Guard mtx(sctp_mtx);
>         ssize_t remain = len;
> 
>         if (!dest.empty()) {
>                 struct addrinfo ai;
>                 struct addrinfo *lips;
>                 bzero(&ai, sizeof(ai));
>                 ai.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV;
>                 ai.ai_family = AF_INET6;
>                 ai.ai_protocol = IPPROTO_SCTP;
>                 ai.ai_socktype = SOCK_SEQPACKET;
>                 int res = 0;
>                 String sport = port;
>                 String addr = dest;
>                 res = getaddrinfo(addr.c_str(), sport.c_str(), &ai, &lips);
>                 if (res != 0) {
>                         throw Error("failed to resolve local ips");
>                 }
>                 struct addrinfo *lip;
>                 for (lip = lips; lip && remain > 0; lip = lip->ai_next) {
>                         while (remain > 0) {
>                                 ssize_t res;
>                                 res = sctp_sendmsgx(sctp_socket, ((uint8_t*)data) + (len - remain), remain, lip->ai_addr, 1, ppid, flags | SCTP_EOR, stream, 0, 0);

I know that I could use all resolved addresses in one call.
In this case it is just a single IP address.
Might change that later nonethelesss to have better example code for other needs.

>                                 if (res > 0) {
>                                         remain -= res;
>                                 } else {
>                                         if (errno != EAGAIN && errno != ENOBUFS) {

Just fixed that posssible addrinfo leak.
Don't think that is the issue here though.

>                                                 return;
>                                         } else {
>                                                 int res;
>                                                 do {
>                                                         struct pollfd pfd;
>                                                         pfd.fd = sctp_socket;
>                                                         pfd.events = POLLOUT;
>                                                         pfd.revents = 0;
>                                                         res = poll(&pfd, 1, 5000);
>                                                 } while (res == 0);
>                                         }
>                                 }
>                         }
>                 }
>                 freeaddrinfo(lips);
>         } else {
>                 while (remain > 0) {
>                         ssize_t res;
>                         res = sctp_sendmsg(sctp_socket, ((uint8_t*)data) + (len - remain), remain, NULL, 0, ppid, flags | SCTP_EOR, stream, 0, 0);
>                         if (res > 0) {
>                                 remain -= res;
>                         } else {
>                                 if (errno != EAGAIN && errno != ENOBUFS) {
>                                         return;
>                                 } else {
>                                         int res;
>                                         do {
>                                                 struct pollfd pfd;
>                                                 pfd.fd = sctp_socket;
>                                                 pfd.events = POLLOUT;
>                                                 pfd.revents = 0;
>                                                 res = poll(&pfd, 1, 5000);
>                                         } while (res == 0);
>                                 }
>                         }
>                 }
>         }
> }
> 

-- 
B.Walter <bernd@bwct.de> http://www.bwct.de
Modbus/TCP Ethernet I/O Baugruppen, ARM basierte FreeBSD Rechner uvm.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20200717182106.GC79604>