SCTP problem, how to debug?
Bernd Walter
ticso at cicely7.cicely.de
Fri Jul 17 18:21:32 UTC 2020
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 at 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 at bwct.de> http://www.bwct.de
Modbus/TCP Ethernet I/O Baugruppen, ARM basierte FreeBSD Rechner uvm.
More information about the freebsd-net
mailing list