source: edk_user_repository/WARP/sw_services/WARPxilnet_v3_02_a/src/xilnet_xilsock.c

Last change on this file was 2068, checked in by welsh, 11 years ago

WARPxilnet update to fix bugs associated with repeat transfers on large packets. Includes a performance boost because we no longer calculate UDP checksums. Includes updates to allow performance monitoring for TX on GPIOs.

File size: 12.1 KB
Line 
1////////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2004 Xilinx, Inc.  All rights reserved.
3//
4// Xilinx, Inc.
5// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
6// COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
7// ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
8// STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
9// IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
10// FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
11// XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
12// THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
13// ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
14// FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS FOR A PARTICULAR PURPOSE.
16//
17// File   : xilsock.c
18// Date   : 2002, March 20.
19// Author : Sathya Thammanur
20// Company: Xilinx
21// Group  : Emerging Software Technologies
22//
23// Summary:
24// Xilinx internal socket related functions (xilsock functions)
25//
26// $Id: xilsock.c,v 1.2.8.6 2005/11/15 23:41:10 salindac Exp $
27//
28////////////////////////////////////////////////////////////////////////////////
29
30////////////////////////////////////////////////////////////////////////////////
31// see copyright.txt for Rice University/Mango Communications modifications
32////////////////////////////////////////////////////////////////////////////////
33
34#include <xilnet_config.h>
35
36/*
37 * Initialization of xilsock_sockets
38 */
39
40int xilsock_init (unsigned int eth_dev_num) {
41
42    int i;
43
44    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
45
46    if (!eth_device[eth_dev_num].is_xilsock_init) {
47        for (i = 0; i < NO_OF_XILSOCKS; i++) {
48            sockets[i].type          = 0;
49            sockets[i].domain        = 0;
50            sockets[i].proto         = 0;
51            sockets[i].listen        = 0;
52            sockets[i].bound         = 0;
53            sockets[i].accept        = 0;
54            sockets[i].connect       = 0;
55            sockets[i].closing       = 0;
56            sockets[i].closed        = 0;
57            sockets[i].free          = 1;
58            sockets[i].conn.tcp_conn = NULL;
59            sockets[i].recvbuf.buf   = NULL;
60            sockets[i].recvbuf.size  = 0;
61        }
62        eth_device[eth_dev_num].is_xilsock_init = 1;
63    }
64    return eth_device[eth_dev_num].is_xilsock_init;
65}
66
67
68/*
69 * Release a socket
70 */
71
72void xilsock_rel_socket (int sd, unsigned int eth_dev_num) {
73
74    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
75
76    if (sockets[sd].type == SOCK_STREAM) {
77        sockets[sd].conn.tcp_conn = NULL;
78    }
79    else {
80        sockets[sd].conn.udp_conn = NULL;
81    }
82    sockets[sd].type         = 0;
83    sockets[sd].domain       = 0;
84    sockets[sd].proto        = 0;
85    sockets[sd].listen       = 0;
86    sockets[sd].bound        = 0;
87    sockets[sd].accept       = 0;
88    sockets[sd].connect      = 0;
89    sockets[sd].closing      = 0;
90    sockets[sd].closed       = 0;
91    sockets[sd].free         = 1;
92    sockets[sd].recvbuf.buf  = NULL;
93    sockets[sd].recvbuf.size = 0;
94
95}
96
97
98/*
99 * Allocate a xilsock_socket and return socket descriptor
100 * if not able to alloc socket, return -1
101 */
102
103int xilsock_socket(int domain, int type, int proto, unsigned int eth_dev_num) {
104
105    int sd;
106    struct xilsock_socket * sockets = (struct xilsock_socket *)eth_device[eth_dev_num].xilsock_sockets;
107
108    // find a free xilsock_socket
109    if (!xilsock_init(eth_dev_num)){
110        xil_printf("xilsock is not initialized\n");
111        return (-1);
112    }
113    for (sd = 0; sd < NO_OF_XILSOCKS; sd++) {
114        if (sockets[sd].free) {
115            // initialise the socket & make it unavailable
116            sockets[sd].domain = domain;
117            sockets[sd].type   = type;
118            sockets[sd].proto  = proto;
119            sockets[sd].free   = 0;
120            return sd;
121        }
122    }
123    // return as no sockets available
124    return -1;
125}
126
127
128/*
129 * bind a socket to the specified address.
130 * binds addr to socket sd. returns 1 if bound
131 * returns -1 if not able to bind
132 */
133
134int xilsock_bind(int sd, struct sockaddr* addr, int addrlen, void (*callback) (), unsigned int eth_dev_num) {
135
136    int connd;
137    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
138    struct xilnet_udp_conn * conns   = (struct xilnet_udp_conn *)eth_device[eth_dev_num].xilnet_udp_conns;
139
140    // open a tcp conn/udp conn
141    if (sockets[sd].type == SOCK_STREAM) {
142        xil_printf("*** Error xilsock_bind: tcp sockets not available \n");
143        xilsock_rel_socket(sd, eth_dev_num);
144        return -1;
145    }
146    else if (sockets[sd].type == SOCK_DGRAM) {
147        if ( (connd = xilnet_udp_open_conn (((struct sockaddr_in*)addr)->sin_port, callback, eth_dev_num)) == -1) {
148            xil_printf("*** Error xilsock_bind: udp sockets not available \n");
149            xilsock_rel_socket(sd, eth_dev_num);
150            return -1;
151        }
152        sockets[sd].conn.udp_conn = (conns + connd);
153        // update fd of udp conn
154        conns[connd].fd = sd;
155    }
156
157    return 1;
158}
159
160
161/*
162 * listen on a socket
163 * called from listen()
164 */
165
166int xilsock_listen(int s, int backlog, unsigned int eth_dev_num) {
167
168    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
169
170    sockets[s].listen = 1;
171    return 1;
172}
173
174
175
176/*
177 * recv data on socket
178 * called from recv()
179 * returns -1 if no data recvd for "s" (non_blocking call) or
180 * number of bytes recvd for "s"
181 */
182
183int xilsock_recv(int s, unsigned char *buf, unsigned int len, unsigned int eth_dev_num) {
184
185    unsigned int n;
186    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
187    int bytes_recvd = 0;
188
189    if (s > NO_OF_XILSOCKS) {
190        xil_printf("*** Error xilsock_recv: invalid socket descriptor %d \n", s);
191        return -1;
192    }
193
194   n = xilnet_eth_recv_frame(eth_dev_num);
195
196   // Return if data not for socket s
197   if ((n == -1) || (sockets[s].recvbuf.buf == NULL))
198      return -1;
199
200   // Copy data if required onto buf
201   if (sockets[s].recvbuf.buf != buf)
202   {
203      memcpy(buf, sockets[s].recvbuf.buf, len);
204      bytes_recvd = sockets[s].recvbuf.size;
205
206      //reset socket buffer and size
207      sockets[s].recvbuf.buf  = NULL;
208      sockets[s].recvbuf.size = 0;
209   }
210
211   // return no of bytes recvd for this conn
212   return bytes_recvd;
213}
214
215
216/*
217 * send data on socket
218 * called from send()
219 */
220
221int xilsock_send(int s,  unsigned char* buf, unsigned int len, unsigned int eth_dev_num) {
222
223    xil_printf("*** Error xilsock_send: TCP connections are not supported\n");
224    return -1;
225
226#if 0
227    struct xilnet_tcp_conn *conn;
228    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
229    unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
230
231
232    conn = sockets[s].conn.tcp_conn;
233
234    if (!conn) {
235        xil_printf("*** Error xilsock_send: no such socket %d \n", conn);
236        return -1;
237    }
238
239    if (buf != sendbuf) {
240        memset(sendbuf, 0, eth_device[eth_dev_num].buf_size);
241        memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+(TCP_HDR_LEN*4), buf, len);
242    }
243
244     xilnet_tcp_send_pkt(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len, TCP_ACK, eth_dev_num);
245     xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4, IP_PROTO_TCP, conn->dst_ip, eth_dev_num);
246
247     xilnet_eth_send_frame(sendbuf, len+(TCP_HDR_LEN*4)+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
248
249     return len;
250#endif
251}
252
253
254/*
255 * recvfrom socket
256 * Data recvd on any UDP socket
257 * return -1 if data not for socket "s" [non-blocking call]
258 */
259int xilsock_recvfrom(int s, unsigned char *buf, unsigned int len,
260                     struct sockaddr* from, unsigned int *fromlen, unsigned int eth_dev_num)
261{
262    int n;
263    int bytes_recvd = 0;
264    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
265    struct xilnet_udp_conn * conn    = sockets[s].conn.udp_conn;
266
267    if (s > NO_OF_XILSOCKS) {
268        xil_printf("*** Error xilsock_recvfrom: invalid socket descriptor %d \n", s);
269        return -1;
270    }
271
272    n = xilnet_eth_recv_frame(eth_dev_num);
273
274    // Return if data not for socket s
275    if ((n < 0 ) || (sockets[s].recvbuf.buf == NULL))
276        return -1;
277
278   // Copy data if required onto buf
279   if (sockets[s].recvbuf.buf != buf)
280   {
281      memcpy(buf, sockets[s].recvbuf.buf, len);
282      bytes_recvd = sockets[s].recvbuf.size;
283
284      //reset socket buffer and size
285      sockets[s].recvbuf.buf = NULL;
286      sockets[s].recvbuf.size = 0;
287   }
288
289   // Copy the source address onto "to"
290   ((struct sockaddr_in*)from)->sin_addr.s_addr =
291      (conn->dst_ip[0] << 24) + (conn->dst_ip[1] << 16) + (conn->dst_ip[2] << 8) + conn->dst_ip[3];
292   ((struct sockaddr_in*)from)->sin_port = conn->dst_port;
293   *fromlen = sizeof(from);
294
295   // return no of bytes recvd for this conn
296   return bytes_recvd;
297}
298
299
300/*
301 * sendto socket
302 * called from sendto()
303 */
304
305int xilsock_sendto(int s,  unsigned char* buf, unsigned int len, struct sockaddr* to, unsigned int eth_dev_num)
306{
307
308    struct xilnet_udp_conn * conn;
309    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
310    unsigned int             dstaddr = ((struct sockaddr_in*)to)->sin_addr.s_addr;
311    unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
312
313
314    conn = sockets[s].conn.udp_conn;
315    conn->dst_ip[0] = (unsigned char) ((dstaddr >> 24) & 0xFF);
316    conn->dst_ip[1] = (unsigned char) ((dstaddr >> 16) & 0xFF);
317    conn->dst_ip[2] = (unsigned char) ((dstaddr >> 8) & 0xFF);
318    conn->dst_ip[3] = (unsigned char) ((dstaddr) & 0xFF);
319    conn->dst_port  = ((struct sockaddr_in*)to)->sin_port;
320
321    if (!conn) {
322        xil_printf("*** Error xilsock_sendto: no such socket %d \n", conn);
323        return -1;
324    }
325
326    if (buf != sendbuf) {
327        memset(sendbuf, 0, eth_device[eth_dev_num].buf_size);
328        memcpy(sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4+UDP_HDR_LEN, buf, len);
329    }
330
331    // calls to udp stack
332    xilnet_udp_header(conn, sendbuf+LINK_HDR_LEN+IP_HDR_LEN*4, len+UDP_HDR_LEN, eth_dev_num);
333
334    xilnet_ip_header(sendbuf+LINK_HDR_LEN, len+UDP_HDR_LEN+IP_HDR_LEN*4, IP_PROTO_UDP, conn->dst_ip, eth_dev_num);
335
336    xilnet_eth_send_frame(sendbuf, len+UDP_HDR_LEN+IP_HDR_LEN*4+ETH_HDR_LEN, conn->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
337
338    return len;
339}
340
341
342/*
343 * close socket
344 */
345
346void xilsock_close(int s, unsigned int eth_dev_num) {
347
348#if 0
349    unsigned char flags = 0;
350    unsigned short check = 0;
351    unsigned char *tcp_reply;
352    unsigned char          * sendbuf = (unsigned char *)eth_device[eth_dev_num].sendbuf;
353#endif
354    struct xilsock_socket  * sockets = (struct xilsock_socket  *)eth_device[eth_dev_num].xilsock_sockets;
355
356    if (sockets[s].type == SOCK_STREAM) {
357
358        xil_printf("*** Error xilsock_close: TCP connections are not supported\n");
359
360#if 0
361        struct xilnet_tcp_conn *conn = sockets[s].conn.tcp_conn;
362
363        // construct the FIN and wait for ack & FIN from client
364        flags = (TCP_FIN | TCP_ACK);
365        ((struct xilnet_tcp_conn*)conn)->state = TCP_FIN_WAIT1;
366        memset(sendbuf, 0, LINK_FRAME_LEN);
367        tcp_reply = sendbuf+ETH_HDR_LEN+(IP_HDR_LEN*4);
368
369        xilnet_tcp_header(((struct xilnet_tcp_conn*)conn), tcp_reply, 1, flags, eth_dev_num);
370
371        // calculate tcp checksum
372        check = xilnet_udp_tcp_calc_chksum(tcp_reply, (TCP_HDR_LEN*4), eth_device[eth_dev_num].node_ip_addr, ((struct xilnet_tcp_conn*)conn)->dst_ip, IP_PROTO_TCP);
373        tcp_reply[TCP_CHECK_OFF]   = (check & 0xff00) >> 8;
374        tcp_reply[TCP_CHECK_OFF+1] = (check & 0x00ff);
375
376        xilnet_ip_header(sendbuf+ETH_HDR_LEN,(IP_HDR_LEN*4)+(TCP_HDR_LEN*4), IP_PROTO_TCP, ((struct xilnet_tcp_conn*)conn)->dst_ip, eth_dev_num);
377        xilnet_eth_send_frame(sendbuf, (TCP_HDR_LEN*4)+(IP_HDR_LEN*4)+ETH_HDR_LEN, ((struct xilnet_tcp_conn*)conn)->dst_ip, NULL, ETH_PROTO_IP, eth_dev_num);
378#endif
379
380    }
381    else if (sockets[s].type == SOCK_DGRAM) {
382        xilnet_udp_close_conn(sockets[s].conn.udp_conn, eth_dev_num);
383        // close the socket
384        xilsock_rel_socket(s, eth_dev_num);
385    }
386}
Note: See TracBrowser for help on using the repository browser.