Browse Source

updated UDP interface

tags/v0.9.3
Nikhil Chandru Rao 18 years ago
parent
commit
74339b3c6e
2 changed files with 282 additions and 7 deletions
  1. 57
    7
      src/include/gpxe/udp.h
  2. 225
    0
      src/net/udp.c

+ 57
- 7
src/include/gpxe/udp.h View File

@@ -11,6 +11,29 @@
11 11
 
12 12
 #include <stddef.h>
13 13
 #include <gpxe/in.h>
14
+#include <gpxe/pkbuff.h>
15
+#include <gpxe/if_ether.h>
16
+
17
+/**
18
+ * UDP constants
19
+ */
20
+
21
+#define UDP_HLEN    	8
22
+#define UDP_MAX_HLEN	72
23
+#define UDP_MAX_TXPKB	ETH_MAX_MTU
24
+#define UDP_MIN_TXPKB	ETH_ZLEN
25
+
26
+typedef uint16_t port_t;
27
+
28
+/**
29
+ * A UDP header
30
+ */
31
+struct udp_header {
32
+        port_t source_port;
33
+        port_t dest_port;
34
+        uint16_t len;
35
+        uint16_t chksum;
36
+};
14 37
 
15 38
 struct udp_connection;
16 39
 
@@ -35,15 +58,42 @@ struct udp_operations {
35 58
  *
36 59
  */
37 60
 struct udp_connection {
38
-	/** Address of the remote end of the connection */
39
-	struct sockaddr_in sin;
40
-	/** Operations table for this connection */
41
-	struct udp_operations *udp_op;
61
+       /** Address of the remote end of the connection */
62
+        struct sockaddr sin;
63
+        /** Local port on which the connection receives packets */
64
+        port_t local_port;
65
+        /** Transmit buffer */
66
+        struct pk_buff *tx_pkb;
67
+        /** List of registered connections */
68
+        struct list_head list;
69
+        /** Operations table for this connection */
70
+        struct udp_operations *udp_op;
42 71
 };
43 72
 
44
-extern void udp_connect ( struct udp_connection *conn );
45
-extern void udp_send ( struct udp_connection *conn, const void *data,
46
-		       size_t len );
73
+/**
74
+ * List of registered UDP connections
75
+ */
76
+static LIST_HEAD ( udp_conns );
77
+
78
+/**
79
+ * Functions provided to the application layer
80
+ */
81
+
82
+extern void udp_init ( struct udp_connection *conn, struct udp_operations *udp_op );
83
+extern int udp_open ( struct udp_connection *conn, uint16_t local_port );
84
+
85
+extern void udp_connect ( struct udp_connection *conn, struct sockaddr *peer );
47 86
 extern void udp_close ( struct udp_connection *conn );
48 87
 
88
+extern int udp_send ( struct udp_connection *conn, const void *data, size_t len );
89
+extern int udp_sendto ( struct udp_connection *conn, struct sockaddr *peer, const void *data, size_t len );
90
+
91
+static inline void * udp_buffer ( struct udp_connection *conn ) {
92
+	return conn->tx_pkb->data;
93
+}
94
+
95
+static inline int udp_buflen ( struct udp_connection *conn ) {
96
+	return pkb_len ( conn->tx_pkb );
97
+}
98
+
49 99
 #endif /* _GPXE_UDP_H */

+ 225
- 0
src/net/udp.c View File

@@ -0,0 +1,225 @@
1
+#include <stdint.h>
2
+#include <string.h>
3
+#include <assert.h>
4
+#include <byteswap.h>
5
+#include <latch.h>
6
+#include <errno.h>
7
+#include <gpxe/in.h>
8
+#include <gpxe/ip.h>
9
+#include <gpxe/udp.h>
10
+#include <gpxe/init.h>
11
+#include <gpxe/pkbuff.h>
12
+#include <gpxe/netdevice.h>
13
+#include <gpxe/interface.h>
14
+
15
+/** @file
16
+ *
17
+ * UDP protocol
18
+ */
19
+
20
+void copy_sockaddr ( struct sockaddr *source, struct sockaddr *dest );
21
+
22
+/**
23
+ * Open a UDP connection
24
+ *
25
+ * @v conn      UDP connection
26
+ * @v peer      Destination socket address
27
+ *
28
+ * This function stores the socket address within the connection
29
+ */
30
+void udp_connect ( struct udp_connection *conn, struct sockaddr *peer ) {
31
+        copy_sockaddr ( peer, &conn->sin );
32
+        /**
33
+         * Not sure if this should add the connection to udp_conns; If it does, uncomment the following code
34
+         */
35
+//	list_add ( &conn->list, &udp_conns );
36
+}
37
+
38
+/**
39
+ * Initialize a UDP connection
40
+ *
41
+ * @v conn      UDP connection
42
+ * @v udp_op	UDP operations
43
+ */
44
+void udp_init ( struct udp_connection *conn, struct udp_operations *udp_op ) {
45
+        conn->local_port = 0;
46
+        conn->tx_pkb = NULL;
47
+        if ( udp_op != NULL ) {
48
+                conn->udp_op = udp_op;
49
+        }
50
+}
51
+
52
+/**
53
+ * Allocate space to the UDP buffer
54
+ *
55
+ * @v conn      UDP connection
56
+ * @v len       Length to allocate
57
+ * @ret rc      Status
58
+ *
59
+ * Allocate "len" amount of space in the transmit buffer
60
+ */
61
+int udp_buf_alloc ( struct udp_connection *conn, size_t len ) {
62
+        if ( conn->tx_pkb != NULL ) {
63
+                free_pkb ( conn->tx_pkb );
64
+                conn->tx_pkb = NULL;
65
+        }
66
+        conn->tx_pkb = alloc_pkb ( len < UDP_MIN_TXPKB ? UDP_MIN_TXPKB : len );
67
+        return !conn ? -ENOMEM : 0;
68
+}
69
+
70
+/**
71
+ * Send data via a UDP connection
72
+ *
73
+ * @v conn      UDP connection
74
+ * @v data      Data to send
75
+ * @v len       Length of data
76
+ *
77
+ * This function fills up the UDP headers and sends the data. Discover the network protocol to
78
+ * use through the sa_family field in the destination socket address.
79
+ */
80
+int udp_send ( struct udp_connection *conn, const void *data, size_t len ) {
81
+       	struct udp_header *udphdr;              /* UDP header */
82
+        struct sockaddr *sock = &conn->sin;     /* Destination sockaddr */
83
+        int rc;
84
+
85
+        /* Copy data into packet buffer if necessary */
86
+        if ( data != conn->tx_pkb->data ) {
87
+                /* Allocate a buffer */
88
+                if ( ( rc = udp_buf_alloc ( conn, len + UDP_MAX_HLEN ) ) != 0 ) {
89
+                        DBG ( "Error allocating buffer" );
90
+                        return rc;
91
+                }
92
+
93
+                /* Reserve space for the headers and copy contents */
94
+                pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
95
+                memcpy ( pkb_put ( conn->tx_pkb, len ), data, len );
96
+        }
97
+
98
+        /* Add the UDP header */
99
+        udphdr = pkb_push ( conn->tx_pkb, UDP_HLEN );
100
+        if ( sock->sa_family == AF_INET )
101
+                udphdr->dest_port = sock->sin.sin_port;
102
+        else
103
+                udphdr->dest_port = sock->sin6.sin6_port;
104
+        udphdr->source_port = conn->local_port;
105
+        udphdr->len = htons ( pkb_len ( conn->tx_pkb ) );
106
+        udphdr->chksum = calc_chksum ( udphdr, UDP_HLEN );
107
+
108
+        /* Print UDP header for debugging */
109
+        DBG ( "UDP header at %#x + %d\n", udphdr, UDP_HDR_LEN  );
110
+        DBG ( "\tSource Port = %d\n", udphdr->source_port );
111
+        DBG ( "\tDestination Port = %d\n", udphdr->dest_port );
112
+        DBG ( "\tLength = %d\n", udphdr->len );
113
+        DBG ( "\tChecksum = %d\n", udphdr->chksum );
114
+        DBG ( "\tChecksum located at %#x\n", &udphdr->chksum );
115
+
116
+	return trans_tx ( conn->tx_pkb, IP_UDP, sock );
117
+}
118
+
119
+/**
120
+ * Send data to a specified address
121
+ *
122
+ * @v conn      UDP connection
123
+ * @v peer      Destination address
124
+ * @v data      Data to send
125
+ * @v len       Length of data
126
+ */
127
+int udp_sendto ( struct udp_connection *conn, struct sockaddr *peer,
128
+                        const void *data, size_t len ) {
129
+        struct sockaddr tempsock;
130
+        copy_sockaddr ( &conn->sin, &tempsock );
131
+        copy_sockaddr ( peer, &conn->sin );
132
+        int rc = udp_send ( conn, data, len );
133
+        copy_sockaddr ( &tempsock, &conn->sin );
134
+        return rc;
135
+}
136
+
137
+/**
138
+ * Close a UDP connection
139
+ *
140
+ * @v conn      UDP connection
141
+ */
142
+void udp_close ( struct udp_connection *conn ) {
143
+        list_del ( &conn->list );
144
+}
145
+
146
+/**
147
+ * Open a local port
148
+ *
149
+ * @v conn		UDP connection
150
+ * @v local_port	Local port on which to open connection
151
+ *
152
+ * This does not support the 0 port option correctly yet
153
+ */
154
+int udp_open ( struct udp_connection *conn, uint16_t local_port ) {
155
+        struct udp_connection *connr;
156
+        uint16_t min_port = 0xffff;
157
+        list_for_each_entry ( connr, &udp_conns, list ) {
158
+                if ( connr->local_port == local_port ) {
159
+                        return -EISCONN; /* CHECK THE ERROR NUMBER */
160
+                }
161
+                if ( min_port > connr->local_port ) {
162
+                        min_port = connr->local_port;
163
+                }
164
+        }
165
+        conn->local_port = local_port == 0 ? min_port > 1024 ? 1024 : min_port + 1 : local_port; // FAULTY!!!
166
+        list_add ( &conn->list, &udp_conns );
167
+        return 0;
168
+}
169
+
170
+/**
171
+ * Process a received packet
172
+ *
173
+ * @v pkb               Packet buffer
174
+ * @v src_net_addr      Source network address
175
+ * @v dest_net_addr     Destination network address
176
+ */
177
+void udp_rx ( struct pk_buff *pkb, struct in_addr *src_net_addr __unused,
178
+                        struct in_addr *dest_net_addr __unused ) {
179
+        struct udp_header *udphdr = pkb->data;
180
+        struct udp_connection *conn;
181
+
182
+        /* todo: Compute and verify checksum */
183
+
184
+        /* Print UDP header for debugging */
185
+        DBG ( "UDP header at %#x + %d\n", udphdr, UDP_HDR_LEN  );
186
+        DBG ( "\tSource Port = %d\n", udphdr->source_port );
187
+        DBG ( "\tDestination Port = %d\n", udphdr->dest_port );
188
+        DBG ( "\tLength = %d\n", udphdr->len );
189
+        DBG ( "\tChecksum = %d\n", udphdr->chksum );
190
+        DBG ( "\tChecksum located at %#x\n", &udphdr->chksum );
191
+
192
+        /* Demux the connection */
193
+        list_for_each_entry ( conn, &udp_conns, list ) {
194
+                if ( conn->local_port == udphdr->dest_port ) {
195
+                        goto conn;
196
+                }
197
+        }
198
+        return;
199
+
200
+        conn:
201
+        /** Strip off the UDP header */
202
+        pkb_pull ( pkb, UDP_HLEN );
203
+
204
+        /** Allocate max possible buffer space to the tx buffer */
205
+        conn->tx_pkb = alloc_pkb ( UDP_MAX_TXPKB );
206
+        pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
207
+
208
+        /** Call the application's callback */
209
+        conn->udp_op->newdata ( conn, pkb->data, ntohs ( udphdr->len ) - UDP_HLEN  );
210
+}
211
+
212
+struct trans_protocol udp_protocol  = {
213
+        .name = "UDP",
214
+        .rx = udp_rx,
215
+        .trans_proto = IP_UDP,
216
+};
217
+
218
+TRANS_PROTOCOL ( udp_protocol );
219
+
220
+/**
221
+ * Internal functions
222
+ */
223
+void copy_sockaddr ( struct sockaddr *source, struct sockaddr *dest ) {
224
+        memcpy ( dest, source, sizeof ( struct sockaddr ) );
225
+}

Loading…
Cancel
Save