8

I am sending commands to a stepper motor system using Ethernet. The commands get the motor to move, or respond with drive status, or configure the drive, etc... The stepper motor system sometimes hangs, or fails to execute the command, and the manufacturer having looked over everything I supplied has told me to turn off the PSH flag in the TCP layer.

A screenshot of Wireshark showing the use of the PSH flag by my code:

enter image description here

I am using C++11 which is running in Ubuntu (16.04).

My send function looks like so:

int sendStatusCode = send(socket , *&pointerToMessageAsCharArray , sizeOfMessage , 0);

I looked over the writeup for the function, and I understand that the last argument (which I have at 0) is a flag. What I do not understand is the value that I need to plug in to turn off the PSH flag without changing anything else (if that is even possible). Can you help?

Edit The size of the messages is quite small. for example: const char m_ME[5] = {m_HEADER_ONE, m_HEADER_TWO, m_M_HEX, m_E_HEX, m_FOOTER_HEX};

which when sent looks like so: enter image description here

The largest message I am sending is 8 chars which works out to 8 bytes.

EDIT I implemented this answer (How would one disable Nagle's algorithm in Linux?) and it looks to me that TCP_NODELAY does not turn off the PSH flag. The code I used to check:

int noDelayState = 1; // 0 means prefer bandwidth optimization over low latency

int tcpPushOptionOff = setsockopt(m_socketRight
    , IPPROTO_TCP
    , TCP_NODELAY
    ,(char *) &noDelayState
    , sizeof(int));

if (tcpPushOptionOff < 0) { /* do smth */ }
0xFACE1ECC
  • 13
  • 2
Mike
  • 371
  • 1
  • 4
  • 18
  • 1
    Are you setting the TCP_NODELAY option (via setsockopt()) on your sending socket? If so, you might try leaving that option unset. – Jeremy Friesner Mar 28 '19 at 17:43
  • 2
    Does the Wireshark output indicate that you are sending partial commands to the motor system? If not, I don't see how the `PSH` flag can cause a problem - if the motor system gets a full command packet, the `PSH` flag seems irrelevant. In that case, there's a good chance that this is just blamecasting by the manufacturer. Heck, if the motor system can't handle an incomplete packet, it's not very good anyway. TCP connections are **streams**, after all. – Andrew Henle Mar 28 '19 at 17:44
  • @JeremyFriesner Unsetting `TCP_NODELAY` would make for a pretty non-responsive control system. The "Tell me how fast you're spinning NOW" packet sits in the outgoing buffer for how long? – Andrew Henle Mar 28 '19 at 17:46
  • 1
    @AndrewHenle agreed -- the suggestion was just for testing/information-gathering purposes. I wasn't proposing it as a permanent solution. – Jeremy Friesner Mar 28 '19 at 17:53
  • @AndrewHenle the data in the messages is quite small (8 bytes max) so no partial messages are getting sent. I edited the question to include that info. If turning off this flag is possible we will find out if blamecasting is going on. – Mike Mar 28 '19 at 18:53
  • 1
    @Mike Oh, it's blamecasting, whether or not unsetting the `PSH` flag makes the motor controller behave or not. What's a motor *controller* supposed to do with an incoming packet? Sit on it and wait for another? The `PSH` flag should be irrelevant. The manufacturer's answer [smells](https://en.wikipedia.org/wiki/Code_smell). It's pure speculation, but I'd guess from your Wireshark dump that the controller can't handle the 2-3 packets/millisecond that you're sending to it, and the "Turn off the `PSH` flag!" is the manufacturer's attempt to slow the packet rate down. – Andrew Henle Mar 28 '19 at 19:04
  • (cont) Are you dropping and reopening the TCP connection rapidly? Maybe just keep it open? – Andrew Henle Mar 28 '19 at 19:05
  • @AndrewHenley I am indeed opening and closing the socket after several related commands. Since the drive automatically shuts down it's socket after 15 seconds or so of non-communication, keeping the connection alive would force me to keep sending dummy commands, and even then, it would not solve all the problems the PSH flag is supposed to solve. Thank you for your suggestions, and I really hope that it is possible to turn off the flag. – Mike Mar 28 '19 at 23:42
  • @JeremyFriesner it turns out that setting TCP_NODELAY has no effect on the PSH flag. Looks like the PSH flag pushes the data up the stack, where the TCP_NODELAY sends out more messages with less data. See: https://stackoverflow.com/questions/15294816/cant-turn-tcp-nodelay-off – Mike Apr 15 '19 at 21:59
  • @AndrewHenle, oh, sorry I forgot to mention, i implemented this answer (https://stackoverflow.com/questions/17842406/how-would-one-disable-nagles-algorithm-in-linux), and it did not turn off the PSH flag. – Mike Apr 15 '19 at 22:19
  • 3
    The manufacturer is BS-ing you. The PSH flag has no actual effect whether set or clear. It was put there because the original TCP designers envisaged a rather different programming interface from what we ended up with. TCP_NODELAY has no effect on the PSH flag, but then nobody said it does. You should ensure it is *off.* – user207421 Apr 16 '19 at 00:13
  • 1
    The PSH flag is set by the networking stack, not by the application. So in order to manipulate it, You need to make use of what the linux network stack provides You. The easiest way is to create a iptables rule to filter outgoing traffic (of interest) to NFQUEUE and then manipulate the packet in user space before actually sending it (example: https://github.com/rgerganov/nfqsed/blob/master/nfqsed.c) – Daniel Jour Apr 18 '19 at 00:12
  • Does sending packets less often help? Maybe you just send way too much commands per second? Good luck with your project! – vlp Apr 21 '19 at 20:34

1 Answers1

2

With standard linux TCP stack you don't have direct control over this. Whether or not the PSH flag gets set is controlled by send buffer and copies in the stack. With something like embedded LWIP stack you have a bit more control.

However, try setting setsockopt(SO_SNDBUF) to be a very small value and see if this makes a difference. Smaller than your packet size, i.e. a few bytes Buffer size setting doesn't work, as minimum size larger than a frame is enforced by OS.

kert
  • 2,161
  • 21
  • 22
  • You can't set it to a few bytes. There is a minimum which the platform will enforce, and it is several K in Linux. – user207421 Apr 19 '19 at 01:32
  • @kert I am really surprised that I cannot do anything about this flag. Thanks for closing the door on this issue. – Mike Apr 23 '19 at 15:43