📄 worker.c
字号:
void to_network_layer(packet *p)
{
/* Deliver information from an inbound frame to the network layer. A check is
* made to see if the packet is in sequence. If it is not, the simulation
* is terminated with a "protocol error" message.
*/
unsigned int num;
num = pktnum(p);
if (num != last_pkt_given + 1) {
printf("Tick %u. Proc %d got protocol error. Packet delivered out of order.\n", tick/DELTA, id);
printf("Expected payload %d but got payload %d\n",last_pkt_given+1,num);
exit(0);
}
last_pkt_given = num;
payloads_accepted++;
}
void from_physical_layer (frame *r)
{
/* Copy the newly-arrived frame to the user. */
*r = last_frame;
}
void to_physical_layer(frame *s)
{
/* Pass the frame to the physical layer for writing on pipe 1 or 2.
* However, this is where bad packets are discarded: they never get written.
*/
int fd, got, k;
/* Fill in fields that that the simulator expects but some protocols do
* not fill in or use. This filling is not strictly needed, but makes the
* simulation trace look better, showing unused fields as zeros.
*/
switch(protocol) {
case 2:
s->seq = 0;
case 3:
s->kind = (id == 0 ? data : ack);
if (s->kind == ack) {
s->seq = 0;
s->info.data[0] = 0;
s->info.data[1] = 0;
s->info.data[2] = 0;
s->info.data[3] = 0;
}
break;
case 4:
case 5:
s->kind = data;
break;
case 6:
if (s->kind == nak) {
s->info.data[0] = 0;
s->info.data[1] = 0;
s->info.data[2] = 0;
s->info.data[3] = 0;
}
/* The following statement is essential to protocol 6. In that
* protocol, oldest_frame is automagically set properly to the
* sequence number of the frame that has timed out. Keeping track of
* this information is a bit tricky, since the call to start_timer()
* does not tell what the sequence number is, just the buffer. The
* simulator keeps track of sequence numbers using the array seqs[],
* which records the sequence number of each data frame sent, so on a
* timeout, knowing the buffer number makes it possible to determine
* the sequence number.
*/
if (s->kind==data) seqs[s->seq % (nseqs/2)] = s->seq; /* save seq # */
}
if (s->kind == data) data_sent++;
if (s->kind == ack) acks_sent++;
if (retransmitting) data_retransmitted++;
/* Bad transmissions (checksum errors) are simulated here. */
k = rand() & 01777; /* 0 <= k <= about 1000 (really 1023) */
if (k < pkt_loss) { /* simulate packet loss */
if (debug_flags & SENDS) {
printf("Tick %u. Proc %d sent frame that got lost: ",
tick/DELTA, id);
fr(s);
}
if (s->kind == data) data_lost++; /* statistics gathering */
if (s->kind == ack) acks_lost++; /* ditto */
return;
}
if (s->kind == data) data_not_lost++; /* statistics gathering */
if (s->kind == ack) acks_not_lost++; /* ditto */
fd = (id == 0 ? w1 : w2);
got = write(fd, s, FRAME_SIZE);
if (got != FRAME_SIZE) print_statistics(); /* must be done */
if (debug_flags & SENDS) {
printf("Tick %u. Proc %d sent frame: ", tick/DELTA, id);
fr(s);
}
}
void start_timer(seq_nr k)
{
/* Start a timer for a data frame. */
ack_timer[k] = tick + timeout_interval + offset;
offset++;
recalc_timers(); /* figure out which timer is now lowest */
}
void stop_timer(seq_nr k)
{
/* Stop a data frame timer. */
ack_timer[k] = 0;
recalc_timers(); /* figure out which timer is now lowest */
}
void start_ack_timer(void)
{
/* Start the auxiliary timer for sending separate acks. The length of the
* auxiliary timer is arbitrarily set to half the main timer. This could
* have been another simulation parameter, but that is unlikely to have
* provided much extra insight.
*/
aux_timer = tick + timeout_interval/AUX;
offset++;
}
void stop_ack_timer(void)
{
/* Stop the ack timer. */
aux_timer = 0;
}
void enable_network_layer(void)
{
/* Allow network_layer_ready events to occur. */
network_layer_status = 1;
}
void disable_network_layer(void)
{
/* Prevent network_layer_ready events from occuring. */
network_layer_status = 0;
}
int check_timers(void)
{
/* Check for possible timeout. If found, reset the timer. */
int i;
/* See if a timeout event is even possible now. */
if (lowest_timer == 0 || tick < lowest_timer) return(-1);
/* A timeout event is possible. Find the lowest timer. Note that it is
* impossible for two frame timers to have the same value, so that when a
* hit is found, it is the only possibility. The use of the offset variable
* guarantees that each successive timer set gets a higher value than the
* previous one.
*/
for (i = 0; i < NR_TIMERS; i++) {
if (ack_timer[i] == lowest_timer) {
ack_timer[i] = 0; /* turn the timer off */
recalc_timers(); /* find new lowest timer */
oldest_frame = seqs[i]; /* for protocol 6 */
return(i);
}
}
printf("Impossible. check_timers failed at %d\n", lowest_timer);
exit(1);
}
int check_ack_timer()
{
/* See if the ack timer has expired. */
if (aux_timer > 0 && tick >= aux_timer) {
aux_timer = 0;
return(1);
} else {
return(0);
}
}
unsigned int pktnum(packet *p)
{
/* Extract packet number from packet. */
unsigned int num, b0, b1, b2, b3;
b0 = p->data[0] & BYTE;
b1 = p->data[1] & BYTE;
b2 = p->data[2] & BYTE;
b3 = p->data[3] & BYTE;
num = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
return(num);
}
void fr(frame *f)
{
/* Print frame information for tracing. */
printf("type=%s seq=%d ack=%d payload=%d\n",
tag[f->kind], f->seq, f->ack, pktnum(&f->info));
}
void recalc_timers(void)
{
/* Find the lowest timer */
int i;
bigint t = UINT_MAX;
for (i = 0; i < NR_TIMERS; i++) {
if (ack_timer[i] > 0 && ack_timer[i] < t) t = ack_timer[i];
}
lowest_timer = t;
}
void print_statistics(void)
{
/* Display statistics. */
int word[3];
sleep(1);
printf("\nProcess %d:\n", id);
printf("\tTotal data frames sent: %9d\n", data_sent);
printf("\tData frames lost: %9d\n", data_lost);
printf("\tData frames not lost: %9d\n", data_not_lost);
printf("\tFrames retransmitted: %9d\n", data_retransmitted);
printf("\tGood ack frames rec'd: %9d\n", good_acks_recd);
printf("\tBad ack frames rec'd: %9d\n\n", cksum_acks_recd);
printf("\tGood data frames rec'd: %9d\n", good_data_recd);
printf("\tBad data frames rec'd: %9d\n", cksum_data_recd);
printf("\tPayloads accepted: %9d\n", payloads_accepted);
printf("\tTotal ack frames sent: %9d\n", acks_sent);
printf("\tAck frames lost: %9d\n", acks_lost);
printf("\tAck frames not lost: %9d\n", acks_not_lost);
printf("\tTimeouts: %9d\n", timeouts);
printf("\tAck timeouts: %9d\n", ack_timeouts);
fflush(stdin);
word[0] = 0;
word[1] = payloads_accepted;
word[2] = data_sent;
write(mwfd, word, 3*sizeof(int)); /* tell main we are done printing */
sleep(1);
exit(0);
}
void sim_error(char *s)
{
/* A simulator error has occurred. */
int fd;
printf("%s\n", s);
fd = (id == 0 ? w4 : w6);
write(fd, &zero, TICK_SIZE);
exit(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -