OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

[/] [amber/] [trunk/] [sw/] [boot-loader-ethmac/] [tcp.c] - Blame information for rev 80

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 61 csantifort
/*----------------------------------------------------------------
2
//                                                              //
3
//  boot-loader-ethmac.c                                        //
4
//                                                              //
5
//  This file is part of the Amber project                      //
6
//  http://www.opencores.org/project,amber                      //
7
//                                                              //
8
//  Description                                                 //
9
//  The main functions for the boot loader application. This    //
10 80 csantifort
//  application is embedded in the FPGA's SRAM and is used      //
11 61 csantifort
//  to load larger applications into the DDR3 memory on         //
12
//  the development board.                                      //
13
//                                                              //
14
//  Author(s):                                                  //
15
//      - Conor Santifort, csantifort.amber@gmail.com           //
16
//                                                              //
17
//////////////////////////////////////////////////////////////////
18
//                                                              //
19
// Copyright (C) 2011 Authors and OPENCORES.ORG                 //
20
//                                                              //
21
// This source file may be used and distributed without         //
22
// restriction provided that this copyright statement is not    //
23
// removed from the file and that any derivative work contains  //
24
// the original copyright notice and the associated disclaimer. //
25
//                                                              //
26
// This source file is free software; you can redistribute it   //
27
// and/or modify it under the terms of the GNU Lesser General   //
28
// Public License as published by the Free Software Foundation; //
29
// either version 2.1 of the License, or (at your option) any   //
30
// later version.                                               //
31
//                                                              //
32
// This source is distributed in the hope that it will be       //
33
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
34
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
35
// PURPOSE.  See the GNU Lesser General Public License for more //
36
// details.                                                     //
37
//                                                              //
38
// You should have received a copy of the GNU Lesser General    //
39
// Public License along with this source; if not, download it   //
40
// from http://www.opencores.org/lgpl.shtml                     //
41
//                                                              //
42
----------------------------------------------------------------*/
43
 
44
 
45
#include "amber_registers.h"
46
#include "address_map.h"
47
#include "line-buffer.h"
48
#include "timer.h"
49
#include "utilities.h"
50
#include "packet.h"
51
#include "tcp.h"
52
#include "telnet.h"
53
 
54
 
55
/* Global variables */
56
int         tcp_checksum_errors_g = 0;
57 80 csantifort
socket_t*   first_socket_g;
58
socket_t*   socket1_g;
59 61 csantifort
 
60 80 csantifort
/* input argument is a pointer to the previous socket,
61
   if this is the first socket object, then it is NULL */
62
socket_t* new_socket(socket_t* prev)
63
{
64
    socket_t* socket;
65
    int i;
66 61 csantifort
 
67 80 csantifort
    socket = (socket_t*) malloc(sizeof(socket_t));
68
    socket->rx_packet = (packet_t*) malloc(sizeof(packet_t));
69
 
70
    /* Create space for an array of pointers */
71
    socket->tcp_buf = malloc (TCP_TX_BUFFERS * sizeof (void *));
72
 
73
    /* Create space for a set of buffers, each pointed to by an element of the array */
74
    for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
75
        socket->tcp_buf[i] = (packet_buffer_t*) malloc (sizeof (packet_buffer_t));
76
        socket->tcp_buf[i]->payload_valid = 0;
77
        socket->tcp_buf[i]->starting_seq = 0;
78
        socket->tcp_buf[i]->ending_seq   = 0;
79
        socket->tcp_buf[i]->len_bytes    = 0;
80
        socket->tcp_buf[i]->ack_received = 0;
81
        }
82
 
83
    socket->telnet_txbuf = init_line_buffer(0x80000);
84
    socket->telnet_rxbuf = init_line_buffer(0x1000);
85
 
86
    socket->packets_sent = 0;
87
    socket->packets_received = 0;
88
    socket->packets_resent = 0;
89
 
90
    socket->telnet_sent_opening_message = 0;
91
    socket->telnet_echo_mode = 0;
92
    socket->telnet_connection_state = TELNET_CLOSED;
93
    socket->telnet_options_sent = 0;
94
 
95
    socket->tcp_current_buf = 0;
96
    socket->tcp_reset = 0;
97
    socket->tcp_connection_state = TCP_CLOSED;
98
    socket->tcp_disconnect = 0;
99
    socket->tcp_seq = 0x100;  /* should be random initial seq number for tcp */
100
    socket->tcp_last_seq = socket->tcp_seq;
101
    socket->tcp_last_ack = 0;
102
 
103
 
104
    /* Chain the socket objects together */
105
    if (prev == NULL){
106
        socket->first = socket;
107
        socket->id = 0;
108
        }
109
    else {
110
        socket->first = prev->first;
111
        socket->id = prev->id + 1;
112
        prev->next = socket;
113
        }
114
    socket->next  = NULL;
115
 
116
    return socket;
117
}
118
 
119
 
120
/* All received tcp packets with dset ip == me arrive here */
121 61 csantifort
void parse_tcp_packet(char * buf, packet_t* rx_packet)
122
{
123
    int i;
124
    int ptr;
125
    socket_t* socket;
126 80 csantifort
    int found=0;
127
 
128 61 csantifort
    /* TCP Length */
129
    rx_packet->tcp_len         = rx_packet->ip_len - rx_packet->ip_header_len*4;
130
    rx_packet->tcp_hdr_len     = (buf[12]>>4)*4;
131 80 csantifort
 
132 61 csantifort
    // Guard against incorrect tcp_hdr_len value
133
    if (rx_packet->tcp_hdr_len < rx_packet->tcp_len)
134
        rx_packet->tcp_payload_len = rx_packet->tcp_len - rx_packet->tcp_hdr_len;
135
    else
136
        rx_packet->tcp_payload_len = 0;
137 80 csantifort
 
138 61 csantifort
    /* Verify the TCP checksum is correct */
139
    if (tcp_checksum(buf, rx_packet, 0)) {
140
        tcp_checksum_errors_g++;
141 80 csantifort
        return;
142 61 csantifort
    }
143 80 csantifort
 
144
 
145 61 csantifort
    rx_packet->tcp_src_port    = buf[0]<<8|buf[1];
146
    rx_packet->tcp_dst_port    = buf[2]<<8|buf[3];
147
    rx_packet->tcp_seq         = buf[4]<<24|buf[5]<<16|buf[6]<<8|buf[7];
148
    rx_packet->tcp_ack         = buf[8]<<24|buf[9]<<16|buf[10]<<8|buf[11];
149
    rx_packet->tcp_flags       = buf[13];
150 80 csantifort
    rx_packet->tcp_window_size = buf[14]<<8|buf[15];
151 61 csantifort
 
152 80 csantifort
 
153
    /* only interested in telnet packet to dest port xx */
154
    if (rx_packet->tcp_dst_port != 23) {
155
        return;
156
    }
157
 
158 61 csantifort
    if (rx_packet->tcp_hdr_len > 20) {
159
        /* Get the source time stamp */
160 80 csantifort
        parse_tcp_options(buf, rx_packet);
161 61 csantifort
        }
162
 
163
 
164
    /*  --------------------------------------------------
165 80 csantifort
        Assign the received packet to a socket
166 61 csantifort
        -------------------------------------------------- */
167 80 csantifort
    /*  seach for an open socket that matches the tcp connection */
168
    socket = first_socket_g;
169
    for(;;){
170
        if (socket->tcp_connection_state != TCP_CLOSED &&
171
            socket->rx_packet->tcp_src_port == rx_packet->tcp_src_port) {
172
            found=1;
173
            break;
174
            }
175
        if (socket->next!=NULL)
176
            socket=socket->next;
177
        else
178
            break;
179
        }
180 61 csantifort
 
181
 
182 80 csantifort
    /* Search for an available closed soeckt to reuse */
183
    if (!found){
184
        socket = first_socket_g;
185
        for(;;){
186
            if (socket->tcp_connection_state == TCP_CLOSED) {
187
                found=1;
188
                break;
189
                }
190
            if (socket->next!=NULL)
191
                socket=socket->next;
192
            else
193
                break;
194
            }
195
        }
196 61 csantifort
 
197
 
198 80 csantifort
    /* All available sockets being used. Add a new one to the end of the chain */
199
    if (!found) {
200
        socket = new_socket(socket);
201
    }
202 61 csantifort
 
203 80 csantifort
 
204 61 csantifort
    /* Copy the rx_packet structure into the socket */
205
    memcpy(socket->rx_packet, rx_packet, sizeof(packet_t));
206 80 csantifort
 
207 61 csantifort
    tcp_response(buf, socket);
208
}
209
 
210
 
211
/* Get the tcp source time stamp by walking through the options */
212
void parse_tcp_options(char * buf, packet_t* rx_packet)
213
{
214
    int ptr;
215
 
216
    ptr = 20;
217
    while (ptr < rx_packet->tcp_hdr_len-1) {
218
        switch (buf[ptr]) {
219
            case 0:  ptr=rx_packet->tcp_hdr_len; break; // end of options
220
            case 1:  ptr++; break;
221 80 csantifort
            case 2:  ptr = ptr + buf[ptr+1]; break;  // max segment size
222 61 csantifort
            case 3:  ptr = ptr + buf[ptr+1]; break;  // Window Scale
223
            case 4:  ptr = ptr + buf[ptr+1]; break;  // SACK Permitted
224
            case 5:  ptr = ptr + buf[ptr+1]; break;  // SACK
225 80 csantifort
            case 8:
226
                // Time Stamp Option
227 61 csantifort
                rx_packet->tcp_src_time_stamp = buf[ptr+2]<<24|buf[ptr+3]<<16|buf[ptr+4]<<8|buf[ptr+5];
228 80 csantifort
                ptr = ptr + buf[ptr+1];
229 61 csantifort
                break;
230 80 csantifort
 
231 61 csantifort
            case 28:  // User Timeout Option
232 80 csantifort
                ptr = ptr + buf[ptr+1]; break;
233
 
234 61 csantifort
            default:
235 80 csantifort
                ptr++; break;
236
            }
237 61 csantifort
        }
238
}
239
 
240
 
241
void tcp_response(char * buf, socket_t* socket)
242
{
243
    socket->packets_received++;
244 80 csantifort
 
245 61 csantifort
    /* Mark the ack in the tcp tx packet buffer so the tx packet does not get resent */
246 80 csantifort
    if (socket->rx_packet->tcp_flags & 0x10) // ack flag set ?
247 61 csantifort
        tcp_ack(socket);
248
 
249 80 csantifort
 
250 61 csantifort
    // Other side requesting to reset a connection ?
251 80 csantifort
    if (socket->rx_packet->tcp_flags & 0x04) { // RST
252 61 csantifort
        // Reset the connection
253
        socket->tcp_disconnect = 1;
254
        }
255 80 csantifort
 
256 61 csantifort
    // open a connection
257 80 csantifort
    else if (socket->tcp_connection_state == TCP_CLOSED) {
258
 
259
        if (socket->rx_packet->tcp_flags & 0x02) { // SYN
260 61 csantifort
            // Open connection
261
            tcp_open(socket);
262
            socket->tcp_connection_state = TCP_PENDING;
263
            }
264 80 csantifort
 
265 61 csantifort
        /* ACK any FIN received */
266 80 csantifort
        else if (socket->rx_packet->tcp_flags & 0x01) // FIN
267
            tcp_reply(socket, NULL, 0);
268 61 csantifort
        }
269
 
270 80 csantifort
 
271 61 csantifort
    // Sent the first ack packet to establish a connection.
272 80 csantifort
    // Have just received the second packet from the server
273
    else if (socket->tcp_connection_state == TCP_PENDING) {
274 61 csantifort
        /* Add 1 to the sequence number as a special case to open
275
           the connection */
276 80 csantifort
        socket->tcp_seq++;
277
        socket->tcp_connection_state = TCP_OPEN;
278 61 csantifort
        }
279 80 csantifort
 
280
 
281 61 csantifort
    // connection is already open
282
    else {
283 80 csantifort
 
284 61 csantifort
        /* contains tcp payload */
285
        if (socket->rx_packet->tcp_payload_len != 0) {
286
            /* Ack the packet only if the payload length is non-zero */
287
            tcp_reply(socket, NULL, 0);
288 80 csantifort
 
289 61 csantifort
            /* Process the tcp contents */
290
            if (socket->rx_packet->tcp_dst_port == TELNET_PORT)
291
                /* telnet */
292
                parse_telnet_options(&buf[socket->rx_packet->tcp_hdr_len], socket);
293 80 csantifort
            }
294 61 csantifort
        }
295
}
296
 
297
 
298
void tcp_disconnect(socket_t * socket)
299
{
300
    if (socket->tcp_connection_state != TCP_CLOSED) {
301
        socket->tcp_connection_state = TCP_CLOSED;
302
        socket->telnet_connection_state = TELNET_CLOSED;
303
        socket->telnet_options_sent = 0;
304
        socket->telnet_sent_opening_message = 0;
305
        tcp_reply(socket, NULL, 0);
306
        socket->tcp_disconnect = 0;
307
        socket->telnet_echo_mode = 0;  // reset this setting
308
    }
309
}
310
 
311
 
312
 
313
/* Transmit a string of length line_len
314 80 csantifort
   Suspend interrupts so this process does not get interrupted */
315 61 csantifort
void tcp_tx(socket_t* socket, char* buf, int len)
316
{
317 80 csantifort
    /* Disable ethmac_int interrupt */
318
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
319
 
320
    tcp_reply(socket, buf, len);
321
 
322
    /* Enable ethmac_int interrupt */
323
    *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
324 61 csantifort
}
325
 
326
 
327
 
328
/* TODO merge this into tcp_reply */
329
void tcp_open(socket_t* socket)
330
{
331
 
332
    int i, j;
333
    unsigned short header_checksum;
334
    mac_ip_t target;
335
    int ip_length;
336
    char * buf;
337
 
338 80 csantifort
 
339 61 csantifort
    buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
340 80 csantifort
 
341
 
342 61 csantifort
    target.mac[0] = socket->rx_packet->src_mac[0];
343
    target.mac[1] = socket->rx_packet->src_mac[1];
344
    target.mac[2] = socket->rx_packet->src_mac[2];
345
    target.mac[3] = socket->rx_packet->src_mac[3];
346
    target.mac[4] = socket->rx_packet->src_mac[4];
347
    target.mac[5] = socket->rx_packet->src_mac[5];
348
    target.ip[0]  = socket->rx_packet->src_ip[0];
349
    target.ip[1]  = socket->rx_packet->src_ip[1];
350
    target.ip[2]  = socket->rx_packet->src_ip[2];
351
    target.ip[3]  = socket->rx_packet->src_ip[3];
352
 
353
 
354
    /* Include 20 bytes of tcp options */
355
    ip_length = 20+20+20; /* 20 bytes ip header, 20 bytes tcp header, 20 bytes tcp options */
356 80 csantifort
 
357 61 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
358
    socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
359 80 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, 0, TCP_NEW);
360 61 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->ending_seq   = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + 1;
361
    set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
362 80 csantifort
 
363 61 csantifort
    ip_header(&buf[14], &target, ip_length, 6); /* 20 byes of tcp  options, bytes 14 to 33, ip_proto = 6, TCP*/
364
    ethernet_header(buf, &target, 0x0800);  /* bytes 0 to 13*/
365 80 csantifort
 
366 61 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
367 80 csantifort
 
368 61 csantifort
    strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
369
 
370
    tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes);  // MAC header, IP header, TCP header, TCP options
371
    socket->packets_sent++;
372
 
373
 
374 80 csantifort
    /* Pick the next tx buffer to use */
375 61 csantifort
    if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
376
        socket->tcp_current_buf=0;
377
    else
378
        socket->tcp_current_buf++;
379
}
380
 
381
 
382
 
383
void tcp_reply(socket_t* socket, char* telnet_payload, int telnet_payload_length)
384
{
385
 
386
    int i, j;
387
    mac_ip_t target;
388
    int ip_length;
389
    char * buf;
390
 
391 80 csantifort
 
392 61 csantifort
    buf = socket->tcp_buf[socket->tcp_current_buf]->buf;
393 80 csantifort
 
394 61 csantifort
    target.mac[0] = socket->rx_packet->src_mac[0];
395
    target.mac[1] = socket->rx_packet->src_mac[1];
396
    target.mac[2] = socket->rx_packet->src_mac[2];
397
    target.mac[3] = socket->rx_packet->src_mac[3];
398
    target.mac[4] = socket->rx_packet->src_mac[4];
399
    target.mac[5] = socket->rx_packet->src_mac[5];
400
    target.ip[0]  = socket->rx_packet->src_ip[0];
401
    target.ip[1]  = socket->rx_packet->src_ip[1];
402
    target.ip[2]  = socket->rx_packet->src_ip[2];
403
    target.ip[3]  = socket->rx_packet->src_ip[3];
404
 
405
    ip_length = 20+20 + telnet_payload_length;
406 80 csantifort
 
407 61 csantifort
    /* Copy the payload into the transmit buffer */
408
    if (telnet_payload_length != 0) {
409
        for (i=14+ip_length-telnet_payload_length, j=0; i<14+ip_length;i++,j++) {
410
            buf[i] = telnet_payload[j];
411
            }
412
        }
413 80 csantifort
 
414 61 csantifort
    if (telnet_payload_length)
415
        socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 1;
416
    else
417
        socket->tcp_buf[socket->tcp_current_buf]->payload_valid = 0;
418 80 csantifort
 
419 61 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->ack_received = 0;
420 80 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->starting_seq = tcp_header(&buf[34], socket, telnet_payload_length, TCP_NORMAL);
421 61 csantifort
    socket->tcp_buf[socket->tcp_current_buf]->ending_seq   = socket->tcp_buf[socket->tcp_current_buf]->starting_seq + telnet_payload_length;
422
    set_timer(&socket->tcp_buf[socket->tcp_current_buf]->resend_time, 500);
423
 
424
    ip_header(&buf[14], &target, ip_length, 6); /* 20 byes of tcp  options, bytes 14 to 33, ip_proto = 6, TCP*/
425
    ethernet_header(buf, &target, 0x0800);  /*bytes 0 to 13*/
426
 
427
    socket->tcp_buf[socket->tcp_current_buf]->len_bytes = 14+ip_length;
428 80 csantifort
 
429 61 csantifort
    strncpy((char*)ETHMAC_TX_BUFFER, buf, socket->tcp_buf[socket->tcp_current_buf]->len_bytes);
430
 
431
    tx_packet(socket->tcp_buf[socket->tcp_current_buf]->len_bytes);  // MAC header, IP header, TCP header, TCP options
432
    socket->packets_sent++;
433
 
434
 
435 80 csantifort
    /* Pick the next tx buffer to use */
436 61 csantifort
    if (socket->tcp_current_buf == TCP_TX_BUFFERS-1)
437
        socket->tcp_current_buf=0;
438
    else
439
        socket->tcp_current_buf++;
440
}
441
 
442
 
443
 
444
 
445
/* Find the packets lower than or equal to seq and mark them as acked */
446
void tcp_ack(socket_t* socket)
447
{
448
    int i, ack_valid;
449
    unsigned int ack      = socket->rx_packet->tcp_ack;
450
    unsigned int last_ack = socket->tcp_last_ack;
451 80 csantifort
 
452 61 csantifort
    for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
453
        if (socket->tcp_buf[i]->payload_valid) {
454 80 csantifort
 
455 61 csantifort
            if (ack > last_ack) {
456 80 csantifort
                ack_valid = (socket->tcp_buf[i]->ending_seq > last_ack) &&
457 61 csantifort
                            (socket->tcp_buf[i]->ending_seq <= ack);
458
                }
459
            else { /* ack is a little after 0, last_ack is a little before 0 */
460
                if (socket->tcp_buf[i]->ending_seq < last_ack)
461
                    /* ending sequence is a little after 0 */
462
                    ack_valid = socket->tcp_buf[i]->ending_seq <= ack;
463
                else
464
                    ack_valid = 1;
465
                }
466 80 csantifort
 
467 61 csantifort
            if (ack_valid)  {
468
                socket->tcp_buf[i]->ack_received = 1;
469
                if (socket->tcp_buf[i]->ending_seq == ack) break;
470
                }
471
            }
472
        }
473 80 csantifort
 
474 61 csantifort
   socket->tcp_last_ack = ack;
475
}
476
 
477
 
478
/* Check if any tcp packets need to be re-transmitted */
479 80 csantifort
void tcp_retransmit(socket_t* socket)
480 61 csantifort
{
481
    int i;
482 80 csantifort
 
483 61 csantifort
    /* Find the packet that matches seq */
484
    for (i=0;i<TCP_TX_BUFFERS;i=i+1) {
485
        if (socket->tcp_buf[i]->payload_valid && !socket->tcp_buf[i]->ack_received) {
486
            if (timer_expired(&socket->tcp_buf[i]->resend_time))  {
487 80 csantifort
 
488 61 csantifort
                /* Update the timer to trigger again in another little while */
489
                set_timer(&socket->tcp_buf[i]->resend_time, 500);
490 80 csantifort
 
491 61 csantifort
                socket->packets_resent++;
492 80 csantifort
 
493 61 csantifort
                /* Disable ethmac_int interrupt */
494
                *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
495 80 csantifort
 
496 61 csantifort
                strncpy((char*)ETHMAC_TX_BUFFER, socket->tcp_buf[i]->buf, socket->tcp_buf[i]->len_bytes);
497
                tx_packet(socket->tcp_buf[i]->len_bytes);  // MAC header, IP header, TCP header, TCP options
498
                socket->packets_sent++;
499 80 csantifort
 
500
 
501 61 csantifort
                /* Enable ethmac_int interrupt */
502
                *(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
503
                break;
504
                }
505
            }
506
        }
507
}
508
 
509
 
510
/* return the starting seq number for this packet */
511
unsigned int tcp_header(char *buf, socket_t* socket, int payload_length, int options)
512
{
513
    unsigned short header_checksum;
514
    unsigned int seq_num;
515
    unsigned int ack_num;
516
    char flags = 0;
517
    unsigned short len_tcp;
518
    unsigned int starting_seq;
519 80 csantifort
 
520 61 csantifort
    /* Source Port */
521 80 csantifort
    buf[0] = socket->rx_packet->tcp_dst_port >>8;
522
    buf[1] = socket->rx_packet->tcp_dst_port &0xff;
523 61 csantifort
 
524
    /* Destination Port */
525 80 csantifort
    buf[2] = socket->rx_packet->tcp_src_port >>8;
526
    buf[3] = socket->rx_packet->tcp_src_port &0xff;
527 61 csantifort
 
528
    /* Sequence Number */
529
    /* Increment the sequence number for the next packet */
530
    starting_seq = socket->tcp_seq;
531
    socket->tcp_last_seq = socket->tcp_seq;
532
    socket->tcp_seq += payload_length;
533 80 csantifort
 
534
 
535 61 csantifort
    buf[4] =  starting_seq>>24;
536
    buf[5] = (starting_seq>>16)&0xff;
537
    buf[6] = (starting_seq>>8)&0xff;
538
    buf[7] =  starting_seq&0xff;
539
 
540 80 csantifort
 
541 61 csantifort
    /* Ack Number */
542
    if (options == TCP_NEW)
543
        ack_num = socket->rx_packet->tcp_seq + 1;
544 80 csantifort
    else if (socket->rx_packet->tcp_flags & 0x01) // FIN
545 61 csantifort
        // +1 to the final ack
546
        ack_num = socket->rx_packet->tcp_seq + 1;
547
    else
548
        ack_num = socket->rx_packet->tcp_seq + socket->rx_packet->tcp_payload_len;
549 80 csantifort
 
550 61 csantifort
    buf[8]  =  ack_num>>24;
551
    buf[9]  = (ack_num>>16)&0xff;
552
    buf[10] = (ack_num>>8)&0xff;
553
    buf[11] =  ack_num&0xff;
554
 
555
 
556
    /* Data offset with OPTIONS */
557
    if (options == TCP_NEW)
558
        buf[12] = 0xa0;  /* upper 4 bits, min is 5 */
559
    else
560
        buf[12] = 0x50;  /* upper 4 bits, min is 5 */
561
 
562 80 csantifort
 
563 61 csantifort
    /* Flags */
564 80 csantifort
    flags = 0x10;       /* ACK */
565 61 csantifort
    if (options == TCP_NEW)    /* Valid in first reply in new connection only */
566
        flags |= 0x02;  /* SYNchronise */
567 80 csantifort
    if (socket->tcp_disconnect)
568 61 csantifort
        flags |= 0x01;  /* FINish */
569 80 csantifort
    if (socket->tcp_reset)
570 61 csantifort
        flags |= 0x04;  /* Reset */
571 80 csantifort
 
572 61 csantifort
    buf[13] = flags;
573 80 csantifort
 
574 61 csantifort
    /* Window Size */
575
    buf[14] = socket->rx_packet->tcp_window_size >> 8;
576
    buf[15] = socket->rx_packet->tcp_window_size & 0xff;
577 80 csantifort
 
578 61 csantifort
    /* Checksum */
579
    buf[16] = 0;
580
    buf[17] = 0;
581 80 csantifort
 
582 61 csantifort
    /* Urgent Pointer */
583
    buf[18] = 0;
584
    buf[19] = 0;
585 80 csantifort
 
586
 
587 61 csantifort
    if (options == TCP_NEW) {
588
        /* OPTION: max seg size */
589
        buf[20] = 0x02;
590 80 csantifort
        buf[21] = 0x04;
591 61 csantifort
        buf[22] = 0x05;
592
        buf[23] = 0xb4;
593 80 csantifort
 
594 61 csantifort
        /* OPTION Sack OK */
595
        buf[24] = 0x04;
596
        buf[25] = 0x02;
597 80 csantifort
 
598 61 csantifort
        /* OPTION Time Stamp */
599
        buf[26] = 0x08;
600
        buf[27] = 0x0a;
601
        buf[28] = 0x00;
602
        buf[29] = 0x61;
603
        buf[30] = 0x1f;
604
        buf[31] = 0xc6;
605
        buf[32] =  socket->rx_packet->tcp_src_time_stamp>>24;
606
        buf[33] = (socket->rx_packet->tcp_src_time_stamp>>16)&0xff;
607
        buf[34] = (socket->rx_packet->tcp_src_time_stamp>>8)&0xff;
608
        buf[35] =  socket->rx_packet->tcp_src_time_stamp&0xff;
609 80 csantifort
 
610 61 csantifort
        /* OPTION: NOP */
611
        buf[36] = 0x01;
612
 
613
        /* OPTION Window Scale */
614
        buf[37] = 0x03;
615
        buf[38] = 0x03;
616
        buf[39] = 0x06;
617
        }
618
 
619 80 csantifort
 
620 61 csantifort
    /* Length */
621
    if (options == TCP_NEW)
622
        len_tcp = 40+payload_length;
623
    else
624
        len_tcp = 20+payload_length;
625 80 csantifort
 
626
 
627 61 csantifort
    /* header checksum */
628 80 csantifort
    header_checksum = tcp_checksum(buf, socket->rx_packet, len_tcp);
629 61 csantifort
    buf[16] = (header_checksum>>8)&0xff;
630
    buf[17] = header_checksum&0xff;
631 80 csantifort
 
632 61 csantifort
    return starting_seq;
633
}
634
 
635
 
636
unsigned short tcp_checksum(unsigned char *buf, packet_t* rx_packet, unsigned short len_tcp)
637
{
638
    unsigned short prot_tcp=6;
639
    unsigned short word16;
640 80 csantifort
    unsigned long  sum;
641 61 csantifort
    int i;
642 80 csantifort
 
643 61 csantifort
    //initialize sum to zero
644
    sum=0;
645
    if (!len_tcp) len_tcp = rx_packet->tcp_len;
646 80 csantifort
 
647
 
648 61 csantifort
    // add the TCP pseudo header which contains:
649
    // the IP source and destinationn addresses,
650
    for (i=0;i<4;i=i+2){
651
            word16 =((rx_packet->src_ip[i]<<8)&0xFF00)+(rx_packet->src_ip[i+1]&0xFF);
652 80 csantifort
            sum=sum+word16;
653 61 csantifort
    }
654
    for (i=0;i<4;i=i+2){
655
            word16 =((rx_packet->dst_ip[i]<<8)&0xFF00)+(rx_packet->dst_ip[i+1]&0xFF);
656 80 csantifort
            sum=sum+word16;
657 61 csantifort
    }
658
    // the protocol number and the length of the TCP packet
659
    sum = sum + prot_tcp + len_tcp;
660
 
661
 
662
    return header_checksum16(buf, len_tcp, sum);
663
}
664
 
665 80 csantifort
 
666
/* handle tcp connections and process buffers
667
   Poll all sockets in turn for activity */
668
void process_tcp(socket_t* socket)
669
{
670
    /* Check if any tcp packets need to be re-transmitted */
671
    tcp_retransmit(socket);
672
 
673
    /* Handle exit command */
674
    if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
675
        tcp_disconnect(socket);
676
        }
677
 
678
    /* Reset connection */
679
    else if (socket->tcp_reset) {
680
        socket->tcp_connection_state = TCP_CLOSED;
681
        socket->telnet_connection_state = TELNET_CLOSED;
682
        socket->telnet_options_sent = 0;
683
        tcp_reply(socket, NULL, 0);
684
        socket->tcp_reset = 0;
685
        }
686
 
687
    /* handle telnet messages */
688
    else if (socket->tcp_connection_state == TCP_OPEN){
689
        process_telnet(socket);
690
    }
691
}
692
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.