33#include <sys/socket.h>
36#include <sys/sockopt.h>
83uint64_t cnt_skipped_oldsack = 0;
84uint64_t cnt_used_oldsack = 0;
93#define sack_blk_used(sf, i) ((1 << i) & sf->sf_bits)
94#define sack_blk_set(sf, i) ((1 << i) | sf->sf_bits)
95#define sack_blk_clr(sf, i) (~(1 << i) & sf->sf_bits)
250 struct sackblk blkboard[TCP_MAX_SACK];
259 for( i = 0, num = 0; i<numblks; i++ ) {
262 cnt_skipped_oldsack++;
270 memcpy(&blkboard[num], &in[i],
sizeof(
struct sackblk));
277 memcpy(in, blkboard, (num *
sizeof(
struct sackblk)));
307 struct sackblk blkboard[TCP_MAX_SACK];
313 for(i=0, num=0; i<numblks; i++) {
316 memcpy(&blkboard[num], &in[i],
sizeof(
struct sackblk));
331 memcpy(in, blkboard, (num *
sizeof(
struct sackblk)));
334 for(i=(num-1); i>=0; i--) {
356 if (sf->
sf_used > highest_used)
439 int32_t i, j, i_d, j_d;
475uint64_t tot_sack_blks=0;
481 fprintf(out,
" sf_ack:%u sf_bits:0x%x c:%d used:%d\n",
487 fprintf(out,
"Entry:%d start:%u end:%u\n", i,
504 if (numblks > TCP_MAX_SACK) {
506 panic(
"sf:%p sb:%p Impossible number of sack blocks %d > 4\n",
513 if ((sf->
sf_used > 1) && (no_collapse == 0))
520 if ((sf->
sf_used == 0) && numblks) {
529 for(i=(numblks-1), sf->
sf_cur=0; i >= 0; i--) {
537 if (sf->
sf_used > highest_used)
622main(
int argc,
char **argv)
625 struct sackblk blks[TCP_MAX_SACK];
627 tcp_seq th_ack, snd_una, snd_max = 0;
632 int invalid_sack_print = 0;
635 char line_buf[10][256];
640 while ((i = getopt(argc, argv,
"ndIi:o:?h")) != -1) {
649 invalid_sack_print = 1;
652 in = fopen(optarg,
"r");
654 fprintf(stderr,
"Fatal error can't open %s for input\n", optarg);
659 out = fopen(optarg,
"w");
661 fprintf(stderr,
"Fatal error can't open %s for output\n", optarg);
668 fprintf(stderr,
"Use %s [ -i infile -o outfile -I]\n", argv[0]);
674 memset(buffer, 0,
sizeof(buffer));
675 memset(blks, 0,
sizeof(blks));
677 fprintf(out,
"************************************\n");
678 while (fgets(buffer,
sizeof(buffer), in) != NULL) {
679 sprintf(line_buf[line_buf_at],
"%s", buffer);
681 if (strncmp(buffer,
"QUIT", 4) == 0) {
683 }
else if (strncmp(buffer,
"DUMP", 4) == 0) {
684 sack_filter_dump(out, &sf);
685 }
else if (strncmp(buffer,
"MAX:", 4) == 0) {
686 snd_max = strtoul(&buffer[4], NULL, 0);
687 }
else if (strncmp(buffer,
"COMMIT", 6) == 0) {
691 for(ii=0; ii<line_buf_at; ii++) {
692 fprintf(out,
"%s", line_buf[ii]);
694 fprintf(out,
"------------------------------------\n");
696 saved += numblks - nn;
697 tot_sack_blks += numblks;
698 fprintf(out,
"ACK:%u\n", sf.
sf_ack);
699 for(ii=0, tot_chg=0; ii<nn; ii++) {
700 szof = blks[ii].end - blks[ii].start;
702 fprintf(out,
"SACK:%u:%u [%u]\n",
706 fprintf(out,
"************************************\n");
707 chg_remembered = tot_chg;
709 sack_filter_dump(out, &sf);
710 fprintf(out,
"************************************\n");
713 memset(blks, 0,
sizeof(blks));
714 memset(line_buf, 0,
sizeof(line_buf));
717 }
else if (strncmp(buffer,
"CHG:", 4) == 0) {
718 sack_chg = strtoul(&buffer[4], NULL, 0);
719 if ((sack_chg != chg_remembered) &&
720 (sack_chg > chg_remembered)){
721 fprintf(out,
"***WARNING WILL RODGERS DANGER!! sack_chg:%u last:%u\n",
722 sack_chg, chg_remembered
725 sack_chg = chg_remembered = 0;
726 }
else if (strncmp(buffer,
"RXT", 3) == 0) {
728 }
else if (strncmp(buffer,
"ACK:", 4) == 0) {
729 th_ack = strtoul(&buffer[4], NULL, 0);
730 if (snd_una_set == 0) {
733 }
else if (
SEQ_GT(th_ack, snd_una)) {
736 }
else if (strncmp(buffer,
"EXIT", 4) == 0) {
738 sack_chg = chg_remembered = 0;
739 }
else if (strncmp(buffer,
"SACK:", 5) == 0) {
744 start = strtoul(&buffer[5], &end, 0);
746 endv = strtoul(&end[1], NULL, 0);
748 fprintf(out,
"--Sack invalid skip 0 start:%u : ??\n", start);
751 if (
SEQ_GT(endv, snd_max))
753 if (
SEQ_LT(endv, start)) {
754 fprintf(out,
"--Sack invalid skip 1 endv:%u < start:%u\n", endv, start);
757 if (numblks == TCP_MAX_SACK) {
758 fprintf(out,
"--Exceeded max %d\n", numblks);
761 blks[numblks].start = start;
762 blks[numblks].end = endv;
764 }
else if (strncmp(buffer,
"REJ:n:n", 4) == 0) {
768 in.start = strtoul(&buffer[4], &
end, 0);
770 in.end = strtoul(&
end[1], NULL, 0);
773 fprintf(out,
"Invalid input END:A:B\n");
774 }
else if (strncmp(buffer,
"HELP", 4) == 0) {
775 fprintf(out,
"You can input:\n");
776 fprintf(out,
"SACK:S:E -- to define a sack block\n");
777 fprintf(out,
"RXT -- to clear the filter without changing the remembered\n");
778 fprintf(out,
"EXIT -- To clear the sack filter and start all fresh\n");
779 fprintf(out,
"ACK:N -- To advance the cum-ack to N\n");
780 fprintf(out,
"MAX:N -- To set send-max to N\n");
781 fprintf(out,
"COMMIT -- To apply the sack you built to the filter and dump the filter\n");
782 fprintf(out,
"DUMP -- To display the current contents of the sack filter\n");
783 fprintf(out,
"QUIT -- To exit this program\n");
785 fprintf(out,
"Command %s unknown\n", buffer);
787 memset(buffer, 0,
sizeof(buffer));
796 b = tot_sack_blks * 1.0;
805 fprintf(err,
"Saved %lu sack blocks out of %lu (%2.3f%%) old_skip:%lu old_usd:%lu high_cnt:%d ow:%d ea:%d\n",
806 saved, tot_sack_blks, c, cnt_skipped_oldsack, cnt_used_oldsack, highest_used, over_written, empty_avail);
int sack_filter_blks(struct sack_filter *sf, struct sackblk *in, int numblks, tcp_seq th_ack)
void sack_filter_reject(struct sack_filter *sf, struct sackblk *in)
static int32_t sack_filter_new(struct sack_filter *sf, struct sackblk *in, int numblks, tcp_seq th_ack)
static int32_t is_sack_on_board(struct sack_filter *sf, struct sackblk *b)
#define sack_blk_set(sf, i)
static void sack_board_collapse(struct sack_filter *sf)
#define sack_blk_clr(sf, i)
static void sack_collapse(struct sack_filter *sf, int32_t src, int32_t into)
#define sack_blk_used(sf, i)
static int32_t sack_blocks_overlap_or_meet(struct sack_filter *sf, struct sackblk *sb, uint32_t skip)
static int32_t sack_filter_old(struct sack_filter *sf, struct sackblk *in, int numblks)
static void sack_move_to_empty(struct sack_filter *sf, uint32_t idx)
static void sack_filter_prune(struct sack_filter *sf, tcp_seq th_ack)
void sack_filter_clear(struct sack_filter *sf, tcp_seq seq)
#define SACK_FILTER_BLOCKS
struct sackblk sf_blks[SACK_FILTER_BLOCKS]