和网络层/物理层的接口是由库函数提供,所以只是把数据链路层对包的处理贴上 /* file: datalink.c */ /* use: complete protocol 6, the selective repeat */ /* date: 2009 11 22 11:55:21 CST */ /* */ /* */ /* */ #include"protocol.h" #include"datalink.h" //no nak has been send yet boolean no_nak = true; static int phl_ready = 0; /* check if the coming frame falls into the window */ static boolean between(seq_nr a, seq_nr b, seq_nr c) { return ((a <= b) && (b < c)) || ((c < a) && (a <= b)) || ((b < c) && (c < a)); } /* send frame throught pysical layer */ /* frame kind can be data/ack/nak */ static void send_out_frame(frame_kind fk, seq_nr frame_nr, seq_nr frame_expected, packet buffer[]) { frame s; unsigned int hold; s.kind = fk; if (fk == data) { s.info = buffer[frame_nr % NR_BUFS]; dbg_frame("Send DATA %u %u, ID %d/n", s.seq, s.ack, *(short *)&(s.info)); } s.seq = frame_nr; s.ack = (frame_expected + MAX_SEQ) % (MAX_SEQ + 1); //ack the last received one if (fk == nak) { no_nak = false; } *((unsigned int *)((unsigned char *)&s + PKT_LEN + 12)) = crc32((unsigned char *)&s, PKT_LEN + 12); send_frame((unsigned char *)&s, PKT_LEN + 12 + 4); phl_ready = 0; if (fk == data) { start_timer(frame_nr % NR_BUFS, DATA_TIMER); } stop_ack_timer(); //no need for separate ack frame } /* main part, protocol 6, selective repeat */ int main(int argc, char **argv) { seq_nr ack_expected; //sender window lower edge seq_nr next_frame_to_send; //sender window upper edge seq_nr frame_expected; //receiver window lower edge seq_nr too_far; //receiver window upper edge+1 int i, len, arg; //len->the length received from pysical layer, arg->who's data-timer is out frame r; packet out_buf[NR_BUFS]; packet in_buf[NR_BUFS]; boolean arrived[NR_BUFS]; //in bound bit map seq_nr nbuffered; //how many output buffers currently used int event; //initialize, begin protocol_init(argc, argv); disable_network_layer(); lprintf("Designed by GuoZan && Luo Yaqun && MiYan BUPT-SCS, build:" __DATE__ "" __TIME__ "/n"); ack_expected = 0; next_frame_to_send = 0; frame_expected = 0; too_far = NR_BUFS; nbuffered = 0; for (i = 0; i < NR_BUFS; ++i) { arrived[i] = false; } //initialize end while (true) { event = wait_for_event(&arg); switch (event) { case NETWORK_LAYER_READY: //get one packet from network layer, then transimit to physical layer ++nbuffered; //expend the window get_packet((unsigned char *)&(out_buf[next_frame_to_send % NR_BUFS])); send_out_frame(data, next_frame_to_send, frame_expected, out_buf);//through physical layer inc(next_frame_to_send); //advance upper window edge break; case FRAME_RECEIVED: //get from physical layer, put to network layer len = recv_frame((unsigned char *)&r, sizeof(r)); if (len < 5 || (crc32((unsigned char *)&r, len) != 0)) { dbg_event("****ReceiverError,BadCRCChecksum/n"); break; } if (r.kind == data) { dbg_frame("Recv DATA %u %u,ID %d/n", r.seq, r.ack, *(short *) &(r.info)); if ((r.seq != frame_expected) && no_nak) { send_out_frame(nak, 0, frame_expected, out_buf); } else { start_ack_timer(ACK_TIMER); } if (between(frame_expected, r.seq, too_far) && ((arrived[r.seq % NR_BUFS]) == false)) { //frames can be accepted in any order arrived[r.seq % NR_BUFS] = true; in_buf[r.seq % NR_BUFS] = r.info; while (arrived[frame_expected % NR_BUFS]) { //pass packet to network layer in order, and must be in order put_packet((unsigned char *)&(in_buf[frame_expected % NR_BUFS]), len - 4 - 12); no_nak = true; arrived[frame_expected%NR_BUFS] = false; inc(frame_expected); //reciver window low ++; inc(too_far); //reciver windwo up ++ start_ack_timer(ACK_TIMER); //to see if seperate ack is needed } } } //the other side didn't want this packet, want another one, send him if ((r.kind == nak) && between(ack_expected, (r.ack+1) % (MAX_SEQ+1), next_frame_to_send)) { send_out_frame(data, (r.ack+1) % (MAX_SEQ+1), frame_expected, out_buf); } if (r.kind == ack) { //seperate ack received dbg_frame("Recv ACK %d/n", r.ack); } //handle the acks while (between(ack_expected, r.ack, next_frame_to_send)) { --nbuffered; //window size decrease stop_timer(ack_expected % NR_BUFS); //yeah, he received this packet, we can go forward now inc(ack_expected); //sender window low ++ } break; case PHYSICAL_LAYER_READY: phl_ready = 1; break; case DATA_TIMEOUT: dbg_event("----DATA %d timeout/n", arg); send_out_frame(data, arg, frame_expected, out_buf); break; case ACK_TIMEOUT: send_out_frame(ack, 0, frame_expected, out_buf); dbg_frame("Send ACK %d/n", r.ack); break; default: lprintf("what? another event, there must be some fatal wrong!!!/n"); break; } //decide whether to receive more packet from network layer (nbuffered < NR_BUFS) && phl_ready ? enable_network_layer() : disable_network_layer(); } return 0; }