/* * The following routine will be called once (only) before any other * entity B routines are called. You can use it to do any initialization */ void B_init() { struct pkt packet; packet.seqnum = 0; packet.acknum = ACK; packet.checksum = 0; packet.checksum = genchecksum(packet); Bpastack = packet; }
/* entity A routines are called. You can use it to do any initialization */ void A_init() { /////new stuff struct pkt packet; packet.seqnum = 0; packet.acknum = ACK; packet.checksum = 0; packet.checksum = genchecksum(packet); Apastack = packet; /////old stuff }
/* * The following functions generates a checksum for the packet by using fletchers algorithms on the binary data of the structure, using blocks of 2 bytes*/ int iscorrupt(struct pkt packet) { int checksum1 = packet.checksum; packet.checksum = 0; int checksum2 = genchecksum(packet); //printf("checksum1: %d checksum2: %d\n",checksum1,checksum2); if (checksum1 != checksum2) { //printf("Packet is corrupted\n"); //printf("Total packets corrupted %d\n",corrupted); return TRUE; } packet.checksum = checksum1; return FALSE; }
/* * B_input(packet),where packet is a structure of type pkt. This routine * will be called whenever a packet sent from the A-side (i.e., as a result * of a tolayer3() being done by a A-side procedure) arrives at the B-side. * packet is the (possibly corrupted) packet sent from the A-side. */ void B_input(struct pkt packet) { struct pkt ack; if (iscorrupt(packet)) { return; } if (packet.acknum == DATAACK) { if (!iscorrupt(packet) && packet.seqnum != Bexpectedseqnum) { //wrong seq num ack = Bpastack; tolayer3(BEntity,ack); return; } if (!iscorrupt(packet) && packet.seqnum == Bexpectedseqnum) { //right seqnum ack.checksum = 0; ack.seqnum = packet.seqnum; ack.acknum = ACK; memcpy(ack.payload,packet.payload,MESSAGE_LENGTH); ack.checksum = genchecksum(ack); Bpastack = ack; tolayer3(BEntity,ack); struct msg message; memcpy(message.data,packet.payload,MESSAGE_LENGTH); tolayer5(BEntity,message); Bexpectedseqnum++; return; } } ////new stuff if (packet.acknum == ACK) { if (Bbase >= (packet.seqnum + 1)) { if (packet.seqnum + 1 == Bnextseqnum) { stopTimer(BEntity); } return; } Bbase = packet.seqnum + 1; if (Bbase == Bnextseqnum) { stopTimer(BEntity); } else { stopTimer(BEntity); startTimer(BEntity,TIMERAMT); } } ////old stuff }
void A_output(struct msg message) { Atemp = (struct pkt*) malloc(sizeof(struct pkt)); memcpy(Atemp->payload,message.data,MESSAGE_LENGTH); Atemp->seqnum = Anextseqnum; Atemp->acknum = DATAACK; Atemp->checksum = 0; Atemp->checksum = genchecksum(*Atemp); Aglobalarray[Anextseqnum] = Atemp; if (Anextseqnum < (Abase + WINDOW_SIZE)) { //(!getTimerStatus( AEntity )) { //will succeed if timer is off tolayer3(AEntity,*Atemp); if (Abase == Anextseqnum) { startTimer(AEntity,TIMERAMT); } } Anextseqnum++; return; }
/* * Just like A_output, but residing on the B side. USED only when the * implementation is bi-directional. */ void B_output(struct msg message) { //////new stuff Btemp = (struct pkt*) malloc(sizeof(struct pkt)); memcpy(Btemp->payload,message.data,MESSAGE_LENGTH); Btemp->seqnum = Bnextseqnum; Btemp->acknum = DATAACK; Btemp->checksum = 0; Btemp->checksum = genchecksum(*Btemp); Bglobalarray[Bnextseqnum] = Btemp; if (Bnextseqnum < (Bbase + WINDOW_SIZE)) { //(!getTimerStatus( AEntity )) { //will succeed if timer is off tolayer3(BEntity,*Btemp); if (Bbase == Bnextseqnum) { startTimer(BEntity,TIMERAMT); } } Bnextseqnum++; return; /////old stuff }
static int replay_line(mr_unit_t *un, raid_rplylst_t *eachp, raid_rplybuf_t *rplybuf) { raid_pwhdr_t *pwhdr1, *pwhdr2; raid_rplylst_t *eachpn; int i; int cnt; diskaddr_t blkno; uint_t blkcnt; long long id; int dsum; int error; int colcnt, col, col2; int down; if (eachp->rpl_id == 0) return (0); /* * check: 1 - enough equal ids * 2 - all have same columncnt * 3 - all have same blkno * 4 - all have same blkcnt * * read each and check the checksum * write each */ cnt = eachp->rpl_colcnt; id = eachp->rpl_id; pwhdr1 = &eachp->rpl_pwhdr1; blkno = pwhdr1->rpw_blkno; blkcnt = pwhdr1->rpw_blkcnt; error = raid_pw_read(un, eachp->rpl_column1, eachp->rpl_slot1, rplybuf); dsum = genchecksum(rplybuf->rpl_data + DEV_BSIZE, dbtob(pwhdr1->rpw_blkcnt)); if (dsum != pwhdr1->rpw_sum) return (0); if (error) { if (error == RAID_RPLY_COMPREPLAY) return (0); else return (1); } eachpn = eachp->rpl_next; for (i = 1; i < cnt; i++) { if (eachpn == NULL) break; col2 = eachpn->rpl_column1; ASSERT(col2 < un->un_totalcolumncnt); pwhdr2 = &eachpn->rpl_pwhdr1; if ((pwhdr2->rpw_blkno != blkno) || (pwhdr2->rpw_blkcnt != blkcnt) || (eachpn->rpl_id != id) || (pwhdr2->rpw_colcount != cnt)) { return (0); } error = raid_pw_read(un, col2, eachpn->rpl_slot1, rplybuf); dsum = genchecksum(rplybuf->rpl_data + DEV_BSIZE, dbtob(pwhdr2->rpw_blkcnt)); if (dsum != pwhdr2->rpw_sum) return (0); eachpn = eachpn->rpl_next; } colcnt = i; if (error) return (0); down = raid_state_cnt(un, RCS_ERRED); if ((i != un->un_totalcolumncnt) && (i != (un->un_totalcolumncnt - down))) return (0); /* there ara enough columns to write correctly */ eachpn = eachp; for (i = 0; i < colcnt; i++) { col = eachpn->rpl_column1; error = raid_pw_read(un, col, eachpn->rpl_slot1, rplybuf); error = raid_pw_write(un, col, &eachpn->rpl_pwhdr1, rplybuf); eachpn->rpl_id = 0; if (error && (error != RAID_RPLY_COMPREPLAY)) return (1); eachpn = eachpn->rpl_next; } return (0); }
/* * NAMES: raid_rplyeach * DESCRIPTION: issue a syncronous read to read a pre-write header * PARAMETERS: mr_unit_t *un - pointer to the unit structure * raid_rplylst_t *eachp - pointer to the replay list entry * raid_rplybuf_t *rwbuf1 - pointer to the replay buffer structure * raid_rplybuf_t *rwbuf2 - pointer to the replay buffer structure * RETURNS: */ static int raid_rplyeach( mr_unit_t *un, raid_rplylst_t *eachp, raid_rplybuf_t *rwbuf1, raid_rplybuf_t *rwbuf2 ) { raid_pwhdr_t *pwhp1; raid_pwhdr_t *pwhp2; uint_t dsum1 = 0; uint_t dsum2 = 0; int good_pw1 = 0; int good_pw2 = 0; int do_1 = 0; int do_2 = 0; int error = 0; /* First verify the normal case - two pre-write entries are all good */ if ((eachp->rpl_pwhdr1.rpw_magic == RAID_PWMAGIC && eachp->rpl_pwhdr2.rpw_magic == RAID_PWMAGIC) && (eachp->rpl_pwhdr1.rpw_blkcnt == eachp->rpl_pwhdr2.rpw_blkcnt)) { ASSERT(eachp->rpl_pwhdr1.rpw_id == eachp->rpl_pwhdr2.rpw_id); /* read the pre-write entries */ error = raid_pw_read(un, eachp->rpl_column1, eachp->rpl_slot1, rwbuf1); pwhp1 = &eachp->rpl_pwhdr1; if (error) { if (error != RAID_RPLY_COMPREPLAY) return (error); good_pw1 = FALSE; } else { /* generate checksum for each pre-write entry */ dsum1 = genchecksum(rwbuf1->rpl_data + DEV_BSIZE, dbtob(pwhp1->rpw_blkcnt)); good_pw1 = (dsum1 == pwhp1->rpw_sum); } error = raid_pw_read(un, eachp->rpl_column2, eachp->rpl_slot2, rwbuf2); pwhp2 = &eachp->rpl_pwhdr2; if (error) { if (error != RAID_RPLY_COMPREPLAY) return (error); good_pw2 = FALSE; } else { /* generate checksum for pre-write entry */ dsum2 = genchecksum(rwbuf2->rpl_data + DEV_BSIZE, dbtob(pwhp2->rpw_blkcnt)); good_pw2 = (dsum2 == pwhp2->rpw_sum); } /* verify the checksums and states */ raid_rply_verify(un, eachp->rpl_column1, good_pw1, &do_1, eachp->rpl_column2, good_pw2, &do_2); /* write (replay) the pre-write entries */ if (do_1) { error = raid_pw_write(un, eachp->rpl_column1, &eachp->rpl_pwhdr1, rwbuf1); if (error && (error != RAID_RPLY_COMPREPLAY)) { return (error); } } if (do_2) { error = raid_pw_write(un, eachp->rpl_column2, &eachp->rpl_pwhdr2, rwbuf2); if (error && (error != RAID_RPLY_COMPREPLAY)) { return (error); } } return (0); } if (eachp->rpl_pwhdr1.rpw_magic == RAID_PWMAGIC) { /* * if partner was errored at time of write * or due to open or replay, replay this entry */ if ((eachp->rpl_pwhdr1.rpw_columnnum == -1) || (! COLUMN_ISUP(un, eachp->rpl_pwhdr1.rpw_columnnum))) { /* read the pre-write entry */ error = raid_pw_read(un, eachp->rpl_column1, eachp->rpl_slot1, rwbuf1); if (error) return (error); /* generate checksum for the pre-write entry */ pwhp1 = &eachp->rpl_pwhdr1; dsum1 = genchecksum(rwbuf1->rpl_data + DEV_BSIZE, dbtob(pwhp1->rpw_blkcnt)); if (dsum1 == pwhp1->rpw_sum) { error = raid_pw_write(un, eachp->rpl_column1, &eachp->rpl_pwhdr1, rwbuf1); if (error && (error != RAID_RPLY_COMPREPLAY)) { return (error); } } } return (0); } return (0); }