예제 #1
0
int main(int argc, char **argv)
{
    if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
        printf("Usage: %s [data blocks] [block size] [perf iterations]\n"
               "       This tests the Reed Solomon encoder and decoder.\n"
               "       0 < data blocks <= %d.\n"
               "       Use perf iterations for performance test.\n"
               "       Defaults: data blocks=%d, block size=%d\n", argv[0],
               RS_LIB_MAX_DATA_BLOCKS, RS_LIB_MAX_DATA_BLOCKS, (64 << 10));
        exit(0);
    }

    int i, j, k, n, m, err;
    const int N = argc > 1 ? atoi(argv[1]) : RS_LIB_MAX_DATA_BLOCKS;
    const int BLOCKSIZE = argc > 2 ? atoi(argv[2]) : (64 << 10);

    if (N <= 0 || N > RS_LIB_MAX_DATA_BLOCKS) {
        printf("0 < data blocks <= %d\n", RS_LIB_MAX_DATA_BLOCKS);
        return 1;
    }

    for (i = 0; i < N+3; i++) {
        if ((err = posix_memalign(data + i, 16, BLOCKSIZE)) ||
                (err = posix_memalign(orig + i, 16, BLOCKSIZE))) {
            printf("%s\n", strerror(err));
            return 1;
        }
        memset(data[i], 0, BLOCKSIZE);
    }

    if (argc > 3) {
        clock_t clk, tclk = 0;
        double  tbytes = 0;
        // Performance test.
        n = atoi(argv[3]);
        for (i = 0; i < N+3; i++)
            mkrand(data[i], BLOCKSIZE);
        clk = clock();
        for (i = 0; i < n; i++)
            rs_encode(N+3, BLOCKSIZE, data);
        clk = clock() - clk;
        printf("encode %.3e clocks %.3e sec %.3e bytes/sec\n",
            (double)clk, (double)clk/CLOCKS_PER_SEC,
            BLOCKSIZE * N * (double)CLOCKS_PER_SEC * n /
                ((double)clk > 0 ? (double)clk : 1e-10));
        for (i = N - (3 < N ? 3 : 0); i < N; i++) {
            for (j = i + 1; j < N + 3; j++) {
                for (k = j + 1; k < N + 3; k++) {
                    void* const p = data[k];
                    if (N <= k) {
                        data[k] = 0; /* do not encode */
                    }
                    clk = clock();
                    for (m = 0; m < n; m++)
                        rs_decode3(N + 3, BLOCKSIZE, i, j, k, data);
                    clk = clock() - clk;
                    data[k] = p;
                    printf("decode missing: %d,%d,%d"
                        " %.3e clocks %.3e sec %.3e bytes/sec\n",
                        i, j, k, (double)clk, (double)clk/CLOCKS_PER_SEC,
                        BLOCKSIZE * N * (double)CLOCKS_PER_SEC * n /
                            ((double)clk > 0 ? (double)clk : 1e-10));
                    tbytes += (double)BLOCKSIZE * N * n;
                    tclk += clk;
                    if (k < N) {
                        break;
                    }
                }
                if (j < N) {
                    break;
                }
            }
            if (i + 3 < N) {
                i++;
            }
        }
        printf("decode average:      "
            " %.3e clocks %.3e sec %.3e bytes/sec\n",
            (double)tclk, (double)tclk/CLOCKS_PER_SEC,
            tbytes * (double)CLOCKS_PER_SEC /
                ((double)tclk > 0 ? (double)tclk : 1e-10));
        return 0;
    }

    for (n = 0; n < 17; n++) {
        if (n > 0) {
            for (i = 0; i < N; i++)
                mkrand(data[i], BLOCKSIZE);
        }

        rs_encode(N+3, BLOCKSIZE, data);

        for (i = 0; i < N+3; i++)
            memmove(orig[i], data[i], BLOCKSIZE);

        // One missing block
        for (i = 0; i < N+3; i++) {
            memset(data[i], 0, BLOCKSIZE);
            rs_decode1(N+3, BLOCKSIZE, i, data);
            if (compare(N+3, BLOCKSIZE, data, orig) != 0) {
                printf("FAILED: %d missing %d\n", n, i);
                return 1;
            }
        }

        // Two missing blocks
        for (i = 0; i < N+3; i++)
            for (j = 0; j < N+3; j++) {
                if (i == j) continue;
                memset(data[i], 0, BLOCKSIZE);
                memset(data[j], 0, BLOCKSIZE);
                rs_decode2(N+3, BLOCKSIZE, i, j, data);
                if (compare(N+3, BLOCKSIZE, data, orig) != 0) {
                    printf("FAILED: %d missing: %d %d\n", n, i, j);
                    return 1;
                }
            }

        // Three missing blocks
        for (i = 0; i < N+3; i++)
            for (j = 0; j < N+3; j++) {
                if (i == j) continue;
                for (k = 0; k < N+3; k++) {
                    if (i == k || j == k) continue;
                    memset(data[i], 0, BLOCKSIZE);
                    memset(data[j], 0, BLOCKSIZE);
                    memset(data[k], 0, BLOCKSIZE);
                    rs_decode3(N+3, BLOCKSIZE, i, j, k, data);
                    if (compare(N+3, BLOCKSIZE, data, orig) != 0) {
                        printf("FAILED: %d missing %d %d %d\n", n, i, j, k);
                        return 1;
                    }
                }
            }
    }
    printf("PASS\n");
    return 0;
}
예제 #2
0
int fec_decode_manager_t::input(char *s,int len)
{
	assert(s!=0);
	assert(len+100<buf_len);//guarenteed by upper level

	int tmp_idx=0;
	int tmp_header_len=sizeof(u32_t)+sizeof(char)*4;
	if(len<tmp_header_len)
	{
		mylog(log_warn,"len =%d\n",len);
		return -1;
	}
	u32_t seq=read_u32(s+tmp_idx);
	tmp_idx+=sizeof(u32_t);
	int type=(unsigned char)s[tmp_idx++];
	int data_num=(unsigned char)s[tmp_idx++];
	int redundant_num=(unsigned char)s[tmp_idx++];
	int inner_index=(unsigned char)s[tmp_idx++];
	len=len-tmp_idx;

	//mylog(log_trace,"input\n");

	if(len<0)
	{
		mylog(log_warn,"len<0\n");
		return -1;
	}

	if(type==1)
	{
		if(len<(int)sizeof(u16_t))
		{
			mylog(log_warn,"type==1&&len<2\n");
			return -1;
		}
		if(data_num==0&&(int)( read_u16(s+tmp_idx)+sizeof(u16_t))!=len)
		{
			mylog(log_warn,"inner_index<data_num&&read_u16(s+tmp_idx)+sizeof(u16_t)!=len    %d %d\n",(int)( read_u16(s+tmp_idx)+sizeof(u16_t)),len);
			return -1;
		}
	}

	if(type==0&&data_num==0)
	{
		mylog(log_warn,"unexpected type==0&&data_num==0\n");
		return -1;
	}
	if(data_num+redundant_num>=max_fec_packet_num)
	{
		mylog(log_warn,"data_num+redundant_num>=max_fec_packet_num\n");
		return -1;
	}
	if(!anti_replay.is_vaild(seq))
	{
		mylog(log_trace,"!anti_replay.is_vaild(seq) ,seq =%u\n",seq);
		return 0;
	}

	if(mp[seq].group_mp.find(inner_index)!=mp[seq].group_mp.end() )
	{
		mylog(log_debug,"dup fec index\n");//duplicate can happen on  a normal network, so its just log_debug
		return -1;
	}


	if(mp[seq].type==-1)
		mp[seq].type=type;
	else
	{
		if(mp[seq].type!=type)
		{
			mylog(log_warn,"type mismatch\n");
			return -1;
		}
	}

	if(data_num!=0)
	{
		//mp[seq].data_counter++;

		if(mp[seq].data_num==-1)
		{
			mp[seq].data_num=data_num;
			mp[seq].redundant_num=redundant_num;
			mp[seq].len=len;
		}
		else
		{
			if(mp[seq].data_num!=data_num||mp[seq].redundant_num!=redundant_num||mp[seq].len!=len)
			{
				mylog(log_warn,"unexpected mp[seq].data_num!=data_num||mp[seq].redundant_num!=redundant_num||mp[seq].len!=len\n");
				return -1;
			}
		}
	}

	//mylog(log_info,"mp.size()=%d index=%d\n",mp.size(),index);

	if(fec_data[index].used!=0)
	{
		u32_t tmp_seq=fec_data[index].seq;
		anti_replay.set_invaild(tmp_seq);

		if(mp.find(tmp_seq)!=mp.end())
		{
			mp.erase(tmp_seq);
		}
		if(tmp_seq==seq)
		{
			mylog(log_warn,"unexpected tmp_seq==seq ,seq=%d\n",seq);
			return -1;
		}
	}

	fec_data[index].used=1;
	fec_data[index].seq=seq;
	fec_data[index].type=type;
	fec_data[index].data_num=data_num;
	fec_data[index].redundant_num=redundant_num;
	fec_data[index].idx=inner_index;
	fec_data[index].len=len;
	assert(0<=index&&index<(int)fec_buff_num);
	assert(len+100<buf_len);
	memcpy(fec_data[index].buf,s+tmp_idx,len);
	mp[seq].group_mp[inner_index]=index;
	//index++ at end of function

	map<int,int> &inner_mp=mp[seq].group_mp;


	int about_to_fec=0;
	if(type==0)
	{
		//assert((int)inner_mp.size()<=data_num);
		if((int)inner_mp.size()>data_num)
		{
			mylog(log_warn,"inner_mp.size()>data_num\n");
			anti_replay.set_invaild(seq);
			goto end;
		}
		if((int)inner_mp.size()==data_num)
			about_to_fec=1;
	}
	else
	{
		if(mp[seq].data_num!=-1)
		{
			if((int)inner_mp.size()>mp[seq].data_num+1)
			{
				mylog(log_warn,"inner_mp.size()>data_num+1\n");
				anti_replay.set_invaild(seq);
				goto end;
			}
			if((int)inner_mp.size()>=mp[seq].data_num)
			{
				about_to_fec=1;
			}
		}
	}


	if(about_to_fec)
	{
		int group_data_num=mp[seq].data_num;
		int group_redundant_num=mp[seq].redundant_num;

		//mylog(log_error,"fec here!\n");
		if(type==0)
		{
			char *fec_tmp_arr[max_fec_packet_num+5]={0};
			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
			{
				fec_tmp_arr[it->first]=fec_data[it->second].buf;
			}
			assert(rs_decode2(group_data_num,group_data_num+group_redundant_num,fec_tmp_arr,len)==0); //the input data has been modified in-place
			//this line should always succeed

			blob_decode.clear();
			for(int i=0;i<group_data_num;i++)
			{
				blob_decode.input(fec_tmp_arr[i],len);
			}
			if(blob_decode.output(output_n,output_s_arr,output_len_arr)!=0)
			{
				mylog(log_warn,"blob_decode failed\n");
				//ready_for_output=0;
				anti_replay.set_invaild(seq);
				goto end;
			}
			assert(ready_for_output==0);
			ready_for_output=1;
			anti_replay.set_invaild(seq);
		}
		else//type==1
		{


			int max_len=-1;
			int fec_result_ok=1;
			int data_check_ok=1;
			int debug_num=inner_mp.size();

			int missed_packet[max_fec_packet_num+5];
			int missed_packet_counter=0;

			//outupt_s_arr_buf[max_fec_packet_num+5]={0};

			//memset(output_s_arr_buf,0,sizeof(output_s_arr_buf));//in efficient

			for(int i=0;i<group_data_num+group_redundant_num;i++)
			{
				output_s_arr_buf[i]=0;
			}
			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
			{
				output_s_arr_buf[it->first]=fec_data[it->second].buf;
				if(fec_data[it->second].len<(int)sizeof(u16_t))
				{
					mylog(log_warn,"fec_data[it->second].len<(int)sizeof(u16_t)");
					data_check_ok=0;
				}

				if(fec_data[it->second].len > max_len)
					max_len=fec_data[it->second].len;
			}
			if(max_len!=mp[seq].len)
			{
				data_check_ok=0;
				mylog(log_warn,"max_len!=mp[seq].len");
			}
			if(data_check_ok==0)
			{
				//ready_for_output=0;
				mylog(log_warn,"data_check_ok==0\n");
				anti_replay.set_invaild(seq);
				goto end;
			}
			for(auto it=inner_mp.begin();it!=inner_mp.end();it++)
			{
				int tmp_idx=it->second;
				assert(max_len>=fec_data[tmp_idx].len);//guarenteed by data_check_ok
				memset(fec_data[tmp_idx].buf+fec_data[tmp_idx].len,0,max_len-fec_data[tmp_idx].len);
			}

			for(int i=0;i<group_data_num;i++)
			{
				if(output_s_arr_buf[i]==0 ||i==inner_index) //only missed packet +current packet
				{
					missed_packet[missed_packet_counter++]=i;
				}
			}
			mylog(log_trace,"fec done,%d %d,missed_packet_counter=%d\n",group_data_num,group_redundant_num,missed_packet_counter);

			assert(rs_decode2(group_data_num,group_data_num+group_redundant_num,output_s_arr_buf,max_len)==0);//this should always succeed

			for(int i=0;i<group_data_num;i++)
			{
				output_len_arr_buf[i]=read_u16(output_s_arr_buf[i]);
				output_s_arr_buf[i]+=sizeof(u16_t);
				if(output_len_arr_buf[i]>max_data_len)
				{
					mylog(log_warn,"invaild len %d,seq= %u,data_num= %d r_num= %d,i= %d\n",output_len_arr_buf[i],seq,group_data_num,group_redundant_num,i);
					fec_result_ok=0;
					for(int i=0;i<missed_packet_counter;i++)
					{
						log_bare(log_warn,"%d ",missed_packet[i]);
					}
					log_bare(log_warn,"\n");
					//break;
				}
			}
			if(fec_result_ok)
			{

				output_n=group_data_num;

				if(decode_fast_send)
				{
					output_n=missed_packet_counter;
					for(int i=0;i<missed_packet_counter;i++)
					{
						output_s_arr_buf[i]=output_s_arr_buf[missed_packet[i]];
						output_len_arr_buf[i]=output_len_arr_buf[missed_packet[i]];
					}
				}


				output_s_arr=output_s_arr_buf;
				output_len_arr=output_len_arr_buf;
				assert(ready_for_output==0);
				ready_for_output=1;
			}
			else
			{
				//fec_not_ok:
				ready_for_output=0;
			}
			anti_replay.set_invaild(seq);
		}// end of type==1
	}
	else //not about_to_fec
	{

		if(decode_fast_send)
		{
			if(type==1&&data_num==0)
			{
				assert(ready_for_output==0);
				output_n=1;
				int check_len=read_u16(fec_data[index].buf);
				output_s_arr_buf[0]=fec_data[index].buf+sizeof(u16_t);
				output_len_arr_buf[0]=fec_data[index].len-sizeof(u16_t);

				if(output_len_arr_buf[0]!=check_len)
				{
					mylog(log_warn,"len mismatch %d %d\n",output_len_arr_buf[0],check_len);
				}
				output_s_arr=output_s_arr_buf;
				output_len_arr=output_len_arr_buf;

				ready_for_output=1;
			}
		}
	}

	end:
	index++;
	if(index==int(fec_buff_num)) index=0;

	return 0;
}