I Need a Tcp Option (Ioctl) to Send Data Immediately

I need a TCP option (ioctl) to send data immediately

IIUC, setting the TCP_NODELAY option should flush all packets (i.e. tcp.c implements setting of NODELAY with a call to tcp_push_pending_frames). So if you set the socket option after each send call, you should get what you want.

Send data in separate TCP segments without being merged by the TCP stack

Your TCP stack is implementing Nagle's algorithm trying to increase efficiency by buffering data. Its a common optimization where the intent is amortize the cost of the 40+ byte (TCP + IP) header. Instead of sending multiple small packets, the stack buffers the data and combines them into a larger packet thereby reducing the header overhead.

TCP stacks don't buffer indefinitely though. As long as there is some un-acknowledged sent data on the connection, the sender continues to buffer. The next packet is sent out when:

  • A full packet worth of data is available to be sent OR
  • All previously sent data is acknowledged by the receiver

You can usually disable this by setting the TCP_NODELAY socket option.

setsockopt(sock_fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));

Still sending one message with TCP_NODELAY

There are no 'messages' end-to-end in TCP; it's a byte stream protocol. The protocol is free to combine the bytes from multiple sends as it wishes, or to split one send into multiple segments. This means that if you want discrete messages then you have to invent them. The usual methods include sending a length ahead of the actual message bytes; or having a specific terminating character (which the receiver must then scan for); or using fixed-length messages (I would advise against this as it's inflexible).

All of those would require establishing a standard approach for all students to use. But that's how it is in real life: communication requires the protocols to be agreed in advance. I don't know your teacher's opinion, but I'd award good marks if you collectively defined a message standard and wrote it up as part of submitting your work.

The "wait between messages" approach which you discovered for yourself is very much a cross-your-fingers and hope solution; you hope your wait time exceeds the time taken to transmit the message, which could be quite large if there is a network burp. And the receiver hopes that either (a) all bytes are delivered at once, or (b) that if it polls for data then a 'no more' indication means that it has read the whole message.

Ethernet frame transport layer recognition

TCP/UDP shouldn't be directly embedded into an Ethernet frame.
A TCP segment should be inside an IP packet with Type = 6, and the IP packet should be inside the Ethernet Frame with EtherType= 0x800 (for IPv4):

     Ethernet EtherType=0x800 (IPv4)
+----------------------------------+
| IP Type=6 (TCP) |
| +-------------------------+ |
| | | |
| | +---------------+ | |
| | | TCP | | |
| | | | | |
| | +---------------+ | |
| | | |
| +-------------------------+ |
| |
+----------------------------------+

For UDP, it's the same, only the IP type is 17 instead of 6.

I need to call a sockets setopt routine from kernel space

Depending on the option, you can call sock_setsockopt or tcp_setsockopt from within kernel space. There are also functions for IPv4 and IPv6 options.

Or, if you just want to manipulate particular options, you can view how these functions are implemented, and then use the same implementation for your particular options. For example, if you wanted to adjust TCP_CONGESTION directly, tcp_setsockopt does this (after validating the passed in values):

    lock_sock(sk);
err = tcp_set_congestion_control(sk, name, true, true,
ns_capable(sock_net(sk)->user_ns,
CAP_NET_ADMIN));
release_sock(sk);


Related Topics



Leave a reply



Submit