STCP tutorial(from stanford)
Download
Report
Transcript STCP tutorial(from stanford)
CS244A Review Session #3
Assignment #2 (STCP)
Friday, January 24, 2003
Matthew Holliman
Assignment overview
• Write your own reliable transport layer
• Three parts:
– Basic STCP functionality
• Delivery over reliable network
– Connection setup/teardown, windows, ACKs…
– No dropped packets, reordering, retransmissions
• Due one week from today
– Support missequenced/lost packets
• Reliable delivery over unreliable network
– Retransmissions (timeouts, Go-back N), buffering…
• Due in a fortnight (Fri, Feb 7th)
– FTP client from HW#1 running over STCP
• Modify your HW#1 or use our object files
• Due Wed, Feb 12th
• Get started early!
Assignment overview
•
•
•
•
Client/server (client.c, server.c)
– File download application
“Mysocket” layer (mysock.c)
– Replacement for socket API
(myopen, myread, etc.)
STCP (transport.c)
– Transport layer: You fill this
in!
Network layer (network.c)
– Simulates random packet
loss, delay, duplication
– network_send(),
network_recv()—datagram
service used by STCP
client
server
mysocket
mysocket
transport
transport
network
network
What is STCP?
• TCP Lite
– Simplified connection setup
• Two-way handshake
– No piggybacking of data with acknowledgement
packets
– No congestion control
– No slow-start, fast retransmissions, delayed ACKs, etc.
• Still provides reliable, connection-based, byteoriented transport between two endpoints
– Flow control (sliding sender/receiver window)
– Go-back N
– Retransmissions
STCP packets
• Simplified version of TCP segments
– SYN packet: start a connection
– ACK packet: acknowledge reception of data (next seq)
• No data payload permitted in STCP
• SYN-ACK: passive side completes connection
– FIN packet: end a connection
• FIN-ACK: passive side closed connection
– Data packet: Any packet without these flags set
– SYN/data packets: sequence numbers
– No advertised window
STCP model
• Each side of connection: two processes
– Parent (application/mysocket layer)
– Child (your STCP implementation/network layer)
• Why this model?
– Simulates real O/S implementation
• User-level socket library interfaces to kernel functionality
• Network data arrival is asynchronous
• Protocol stack is idle until packet arrives
– H/W interruptO/S context switch, kernel packet
processing, data passed up stack to app
– STCP implementation can sleep until an “interesting”
event happens
• Timeout, packet arrival, etc.
STCP model
Parent
Child
client
server
mysocket
mysocket
transport
interface
transport
interface
transport
implementation
transport
implementation
network
network
STCP transport layer initiation
myconnect(), myaccept()
transport_init()
• transport_init() creates two
socket pairs, forks; parent
blocks until connected
– In STCP, a SYN received
from peer by child
• Parent/child communicate
via local sockets (a la pipe)
– syn_sd[]—notify parent of
connection completion
– data_sd[]—pass data
between app/transport layer
– Application end of data pipe
returned by transport_init()
fork
Parent (app)
syn_sd[0]
data_sd[0]
syn_sd[1]
data_sd[1]
Data
pipe
(syn pipe)
(data pipe)
IPC
Syn
pipe
Child (transport)
syn_sd[0]
data_sd[0]
syn_sd[1]
(syn pipe)
data_sd[1] (data pipe)
comm_sd (peer socket)
STCP IPC details
• Forking, IPC is provided already in transport.c
– You shouldn’t need to touch much of transport_init(),
except to
• Add your SYN/SYN-ACK handling
• Change/add the transport layer state setup as needed
– Sockets created in transport_init() (using
localsocketpair()) before forking
• Descriptors valid in both parent/child processes
• Syn_sd[] used only for connection setup
• Data_sd[] used for all data sent between application and
transport layer
• Only one of each socket is used in parent/child to
communicate, a la pipe/FIFO
– transport_init() closes unneeded sockets in parent and
child
STCP/application interaction
• Connection establishment (myconnect, myaccept)
– Application blocks until SYN received
• STCP wakes up blocked parent process using “syn pipe”
– Use network_peer_name(&peeraddr…), write to its syn_sd socket
• syn_sd is finished with at this point
– See select(3c), poll(2)
• Data read/write (myread, mywrite)
– Application reads from/writes to its end of the “data pipe”
(the socket returned by transport_init() in the parent
process)
– STCP writes to/reads from its end of the “data pipe”
• Whenever data is available (from app or peer) and you have
space in your window
• Just assume data written to application has been read
STCP/application interaction
• Connection teardown (myclose)
– Application closes stream socket returned by transport_init()
– Pay attention to delivery semantics in assignment handout
• Parent blocks in transport_close(), waiting for child to exit
• Child waits for all outstanding data to be ACKed before sending
FIN
• Child process exits on FIN-ACK, unblocking parent
– Passive end closes connection immediately on
receiving FIN
• Multiple connections
– A unique child process is forked by transport_init(), so
you don’t have to worry about session demultiplexing
STCP main control loop
• Stub transport.c talks about “callbacks”
– You can ignore this if it’s confusing (I did)
– You will probably want to split out functionality for
handling data from the app (e.g., transport_appl_io)
and functionality for handling data from the peer (e.g.,
transport_sock_io)
– This is all handled in the child process by your
transport layer
• Main loop repeatedly waits for event on application
socket (local_data_sd), peer socket (comm_sd),
timeout (in part B onwards)
– Select/poll to see which event happened
– Be sure not to wake up on application socket unless
your sender window is open!
Select
•
Online information
– man –s 3c select
• Looks in section 3c of manual (C library)
• Also useful: section 2 (system calls), 3socket (socket calls)
•
Select semantics
– Wait for file descriptor(s) to become readable/writable/error state
– select(fd_range, &readfds, &writefds, &errfds, &timeout)
• fd_range—range of file descriptors to test (0..fd_range-1)
• readfs (writefds/errfds)—description of file descriptors of interest
• timeout—time interval for which select() blocks if no socket becomes
readable/writable/error state (NULLinfinite)
Be careful! These are common
fd_set readfds;
FD_ZERO(&readfds);
problem areas…
FD_SET(my_sock_fd, &readfds);
…
switch (select(my_sock_fd+1, &readfs, NULL, NULL, &timeout))
{…
Poll
• “Newer” system call
– More efficient kernel implementation than select
– No need to scan through all open file descriptors
– You explicitly specify the descriptors of interest
• Poll semantics
– poll(struct pollfd fds[], int nfds, int timeout);
– pollfd structure contains file descriptor, events of
interest
struct pollfd fds[] = { { my_socket, POLLIN, 0 } };
switch (poll(fds, sizeof(fds)/sizeof(fds[0]),
timeout_interval) { …
Part 2.a—STCP in reliable mode
• Network layer refrains from any mischief
• All packets delivered in sequence, no losses
• You implement connection setup/teardown,
acknowledgements, send/receive windows
• Client/server pair should be able to download
files after you’ve finished this
• For testing and submitting code, we need
(and accept) only transport.c
– No auxiliary files
Part 2.a—STCP in reliable mode
• Window example
– Other side received through
seq #999, responded with
ACK for seq #1000
– We’ve sent through seq
#2999
– Sender window is 30722000 = 1072 bytes
Client: mywrite(…, 2048)
Last seq # acked
1000
2000
…
STCP ACK packet
th_ack=2000
Seq #
3000
Seq #
4072
Part 2.b—STCP in unreliable mode
• Network layer becomes obnoxious
– Packets reordered, dropped, duplicated
– See network_send() in network.c
• You must handle retransmissions, timeouts, Go-back
N, buffering of data, …
–
–
–
–
No exponential back-off
Minimum RTT estimate is 20 ms
Five retransmissions of any segment
Careful about packets crossing ends of receive window
• Client, server pair should now work with –U flags
• Your modified transport.c is the only file needed (and
accepted) for testing and the final submission
Part 2.c—STCP-based ftpcopy
• You can either modify your HW#1 to use STCP, or
you can use the provided object files (libftpcopy.a
etc.)
– Should just be a few minutes of work
– Change the provided Makefile as needed
– If linking your transport layer against the STCP-talking
libftpd.a, there is a caveat…
• Don’t write anything to stdout!
• Disable debugging messages, or write to stderr
– Another caveat…
• libftpcopy.a works only against localhost
General comments
• See Peterson & Davie for TCP FSM diagram
– Keep track of SYN_SENT, SYN_WAITING, etc.
– STCP state machine is simpler
• Network layer uses UDP datagrams
– Treat it like an IP implementation
– Packet-oriented rather than byte-oriented service
– Be sure to read the maximum length datagram!
• Unread bytes in a datagram are discarded by recv()
• Portability
– Don’t forget to use htonX()/ntohX() as appropriate in
STCP header fields
General comments
• Efficiency
– Required: Be sure not to wake up unnecessarily/sit in
tight loops waiting for things to happen
• Use select(), poll() appropriately
• Don’t select() on app socket unless you can really send
data
– Pedantic (optional, but encouraged): If you can avoid
unnecessary memcpy()s, you’ll get a lot more out of
the assignment—but you’ll probably spend more time
on it, too
• See the book’s description of mbufs if interested
• Don’t worry about this if you don’t care too much—
correctness is more important
General comments
• Yes, for part (a), the lazy STCP implementer
could just send data directly to/from the app,
no need to buffer
– You still need to pay attention to the windows
• But you can’t get away with this for part (b)
– It’s worth the extra time to plan ahead rather
than wasting effort
– Be aware of design changes/additions you’ll
need to make to handle unreliable mode
Debugging
• Don’t forget to Purify!
– It can save you a lot of time on this assignment
– Bad select() calls, invalid pointers in network_recv(),
can cause some mysterious behaviour in your code
• gdb
– Normal approach is to place ‘set follow-fork-mode child’
in your .gdbinit
– This doesn’t work for me now (?!)
– Ugly hack: add sleep(N) in your child after the fork(),
run the client/server pair outside of gdb, do ‘ps’ and
attach to the child process (larger PID) of interest with
‘gdb {server|client} PID’
– If you have better ideas, please post them to the
newsgroup!
General nagging
• Start early and test often
– This assignment is trickier than it looks!
• The earlier you can get to part (b), the better…
– This will probably be the toughest two week
stretch of the quarter (for everyone…)
• Please remember to submit to the right TA!
– Steve received only five submissions for
HW#1; 26 people incorrectly submitted to
Guido or me, despite having been reassigned!