Ethernet UDP packets won't send more often than 100ms

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
ccrome
Active Member
Posts: 62
Joined: Wed Sep 23, 2015 1:15 am

Ethernet UDP packets won't send more often than 100ms

Post by ccrome »

Hello,
I'm working with a 100BT ethernet board (the DSP4You AVB-DG board), and for some reason, I can't seem to send packets any more often than 100 milliseconds.

I have a setup that should be flooding the network with packets (intentionally), but I only get 10 packets/second.

Here is my xtcp switch statement:

Code: Select all

    switch (conn.event) {
    case XTCP_NEW_CONNECTION:
        if (XTCP_IPADDR_CMP(conn.remote_addr, broadcast_addr)) {
            broadcast_connection = conn;
            xtcp_init_send(c_xtcp, broadcast_connection);
            broadcast_send_flag = 1;
        }
        break;
    case XTCP_RECV_DATA:
        n_received = xtcp_recv(c_xtcp, received_data);
        break;
    case XTCP_PUSH_DATA:
        break;
    case XTCP_REQUEST_DATA:
        if (conn.id == broadcast_connection.id) {
            xtcp_send(c_xtcp, broadcast_buffer, broadcast_len);
        }
        break;
    case XTCP_RESEND_DATA:
        if (conn.id == broadcast_connection.id) {
            xtcp_send(c_xtcp, broadcast_buffer, broadcast_len);
        }
        break;
    case XTCP_SENT_DATA:
        xtcp_complete_send(c_xtcp);
        if (conn.id == broadcast_connection.id) {
          xtcp_init_send(c_xtcp, broadcast_connection);
          broadcast_send_flag = 0;
        }
        break;
    case XTCP_ABORTED:
    case XTCP_CLOSED:
    case XTCP_TIMED_OUT:
    case XTCP_POLL:
    case XTCP_ALREADY_HANDLED:
        break;
    case XTCP_IFUP:
        xtcp_connect(c_xtcp,
                     BROADCAST_PORT,
                     broadcast_addr,
                     XTCP_PROTOCOL_UDP);
        break;
    case XTCP_IFDOWN:
        xtcp_close(c_xtcp, broadcast_connection);
        broadcast_connection.id = INIT_VAL;
        break;
    default:
        break;
    }
It works, but sends packets only at exactly 100 millisecond intervals. I have tried it 2 ways: one with xtcp_complete_send + xtcp_init_send in the XTCP_SENT_DATA slot, and also tried it with just xtcp_send, without the 'complete + init' sequence. Both ways, I still only get packets at 100ms intervals.

What can I do to send UDP packets quickly?

Thanks,
-Caleb
User avatar
ccrome
Active Member
Posts: 62
Joined: Wed Sep 23, 2015 1:15 am

Post by ccrome »

Just a little further information:

In looking into the xtcp code, in lib_xtcp/src/xtcp.xc there is a timeout that's set to 100milliseconds. It appears that the xtcp code only will send packets on this interval, and it's polled rather than event driven.

I don't really understand why that would be. Shouldn't xtcp_init_send start a send immediately? It appears not.

I can reduce the timeout, but polling doesn't seem like a great answer. Is there some way to make xtcp sending event driven?

The select statement in xtcp.xc has only 3 cases:

Code: Select all

    case !isnull(i_mii) => mii_incoming_packet(mii_info):
    case !isnull(i_eth_rx) => i_eth_rx.packet_ready():
    case tmr when timerafter(timeout) :> timeout:
So, it appears from this code that it's event driven when receiving an MII packet, receiving an eth_rx packet, but polled (on timeout) otherwise, so sending a packet happens in that timeout case.

I must be missing something...

-Caleb
User avatar
Andy
Respected Member
Posts: 279
Joined: Fri Dec 11, 2009 1:34 pm

Post by Andy »

User avatar
ccrome
Active Member
Posts: 62
Joined: Wed Sep 23, 2015 1:15 am

Post by ccrome »

Hi Andy, thanks for the reply.

That patch sure looked promising, but that patch actually has (virtually) no effect because even when you move that code outside the case statement, it simply means that the code

Code: Select all

    xtcpd_service_clients(xtcp, n);
    xtcpd_check_connection_poll();
    uip_xtcp_checkstate();
    xtcp_process_udp_acks();
is still only called every 100ms, plus whenever the other 2 cases happen, which is not very often.

So, performance when sending UDP packets is still terrible with lib_xtcp. (maximum of 10 packets/second).

Shouldn't there be a case statement in there that responds to a send event so it's event driven, rather than polled?

I'd like to add something like this:

Code: Select all

        case (size_t i = 0; i < n; i++)
           testct(xtcp[i]):
        xtcpd_service_clients(xtcp, n);
        xtcpd_check_connection_poll();
        uip_xtcp_checkstate();
        xtcp_process_udp_acks();
        break;

so that the code reacts whenever something comes in on the xtcp, but this code won't compile. I get:

Code: Select all


/Users/caleb/workspace/lib_xtcp/lib_xtcp/src/xtcp.xc:143:19: error: passing transactor to function which is not a transaction function
           testct(xtcp[i]):
                  ^~~~~~~
/Applications/XMOS_xTIMEcomposer_Community_14.1.2/target/include/xs1.h:1246:63: note: expanded from macro 'testct'
#define testct(c)                            __builtin_testct(c)
                                                              ^
xmake[1]: *** [.build/_l_xtcp/src//xtcp.xc.pca.xml] Error 1
xmake: *** [analyze] Error 2
Thanks,
-Caleb
User avatar
ccrome
Active Member
Posts: 62
Joined: Wed Sep 23, 2015 1:15 am

Post by ccrome »

I put the lines in question into a default: case statement, which seems to make performance tolerable but still not great. I created a pull request here:

https://github.com/xmos/lib_xtcp/pull/12

and the diff is here:

https://github.com/xmos/lib_xtcp/pull/12/files


As stated in the pull request, this is definitely far from ideal because it's polling rather than event driven, and still doesn't have as good of performance as it should. It will probably slow down response times to other events to some degree.

This really should be event driven, shouldn't it? But I can't figure out how to make the select statement actually operate on the xtcp chanend array.

Thanks,
-Caleb