2012-01-19 2 views
2

이 변환은 원본과 동일합니까?32 비트에서 8 비트로 플레처 체크섬을 다시 작성

uint8_t fletcher8(uint8_t *data, uint8_t len) 
{ 
    uint8_t sum1 = 0xff, sum2 = 0xff; 

    while (len) { 
      unsigned tlen = len > 360 ? 360 : len; 
      len -= tlen; 
      do { 
        sum1 += *data++; 
        sum2 += sum1; 
        tlen -= sizeof(uint8_t); 
      } while (tlen); 
      sum1 = (sum1 & 0xff) + (sum1 >> 4); 
      sum2 = (sum2 & 0xff) + (sum2 >> 4); 
    } 
    /* Second reduction step to reduce sums to 4 bits */ 
    sum1 = (sum1 & 0xff) + (sum1 >> 4); 
    sum2 = (sum2 & 0xff) + (sum2 >> 4); 
    return sum2 << 4 | sum1; 
    } 

원본 :

uint32_t fletcher32(uint16_t *data, size_t len) 
{ 
    uint32_t sum1 = 0xffff, sum2 = 0xffff; 

    while (len) { 
      unsigned tlen = len > 360 ? 360 : len; 
      len -= tlen; 
      do { 
        sum1 += *data++; 
        sum2 += sum1; 
        tlen -= sizeof(uint16_t); 
      } while (tlen); 
      sum1 = (sum1 & 0xffff) + (sum1 >> 16); 
      sum2 = (sum2 & 0xffff) + (sum2 >> 16); 
    } 
    /* Second reduction step to reduce sums to 16 bits */ 
    sum1 = (sum1 & 0xffff) + (sum1 >> 16); 
    sum2 = (sum2 & 0xffff) + (sum2 >> 16); 
    return sum2 << 16 | sum1; 
    } 

렌은 []의 데이터를 입력해야합니다 8. ​​

데이터가 될 것입니다 (1-8) 사실

나도 몰라 무엇 줄과 관련있다 : unsigned tlen = len> 360? 360 : len;

아마 -> int8_t TLEN = LEN> 255? 255 : len;

+0

코드가 위키 피 디아에서 온 것 같습니다. 이 자료는 [CC-BY-SA 라이센스] (http://en.wikipedia.org/wiki/Wikipedia:CC-BY-SA)의 적용을 받음에 따라이 원본을 보관해야합니다. 코드를 작성자에게 부여해야합니다. – MvG

답변

1

0xFF가 아닌 곳에서 0xF 마스크가 필요하다고 생각합니다. 32 비트는 16 비트 마스크를 사용하여, (32)의 절반하여 8 비트 8 4 비트의 절반 아닌 제

uint8_t fletcher8(uint8_t *data, uint8_t len) 
{ 
    uint8_t sum1 = 0xf, sum2 = 0xf; 

    while (len) { 
     unsigned tlen = len > 360 ? 360 : len; 
     len -= tlen; 
     do { 
       sum1 += *data++; 
       sum2 += sum1; 
       tlen -= sizeof(uint8_t); 
     } while (tlen); 
     sum1 = (sum1 & 0xf) + (sum1 >> 4); 
     sum2 = (sum2 & 0xf) + (sum2 >> 4); 
    } 
    /* Second reduction step to reduce sums to 4 bits */ 
    sum1 = (sum1 & 0xf) + (sum1 >> 4); 
    sum2 = (sum2 & 0xf) + (sum2 >> 4); 
    return sum2 << 4 | sum1; 
} 

그렇지 다른 체크섬을 만드는 절반 인 8 비트 마스크를 사용하여, 플레처가 아니야. 예를 들어 sum1은 내가 '보완 체크섬'이라고하는 것을 수행하고 있습니다. 기본적으로 이전 비트와 16 비트의 4 비트를 인터넷 프로토콜에서 사용되는 캐리 비트가 다시 추가되는 체크섬으로 사용하면 전체 패킷의 체크섬을 계산하지 않고도 패킷을 쉽게 수정할 수 있습니다. 기존 체크섬에 대한 변경 사항 만 추가 및 뺍니다.

추가 감소 단계는 corner case의 경우입니다. 4 비트 체계를 사용하여 sum1 + = * data = 0x1F의 결과가 나온다면 캐리 비트를 더하는 것은 0x01 + 0x0F = 0x10이므로 추가해야합니다 루프 0x01 + 0x00 = 0x01 외부에서 비트를 다시 운반하십시오. 그렇지 않으면 루프 합계 바깥쪽에 0이 추가됩니다. 아키텍처에 따라 if (sum1 & 0x10) sum1 = 0x01과 같이 빠르게 실행할 수 있습니다. 더 많은 지시가 필요할지도 모르는 물건을 추가하는 것보다. 두 가지가 결합 될 때 그것에서 추가 한 캐리 비트 단지 검사보다 더 많은 것을하게

는 마지막 단계입니다. 예를 들어 32 비트 플레쳐를 16 비트 체크섬으로 만 사용하는 경우 시간 낭비가 발생합니다. 결과의 하위 16 비트는 다시 캐리 비트가 추가 된 스톡 체크섬이며 특별한 것은 없습니다. sum2는 sum1 체크섬의 누적 값이므로 흥미로운 수입니다 (sum1은 데이터의 누적 값이고 sum2는 체크섬 누적 값임). 서명되지 않은 TLEN = LEN> 360 :

+0

좋은 답변, 고마워. 네,이 체크리스트로 사용합니다;) – Christian

+0

코드는 여전히 [틀린] 변수 인'tlen'의 계산을 사용합니다 (http://stackoverflow.com/a/13498354/1468366). OP가이 라인에 대한 우려를 명시 적으로 언급 했으므로 이러한 우려를 언급하지 않았다는 사실을 언급했을 수 있습니다. – MvG

0

원본 버전 sum1, sum2는 32 비트입니다. 그것이 비트가 나중에 이동하는 이유입니다. 귀하의 경우 sum1, sum2를 8 비트로 선언하므로 비트 시프트가 의미가 없습니다.

2

방법이 tlen 값 사실

난 줄 어떻게 해야할지하지 않습니다를 계산하기? 360 : len;

그 라인은 에서 오는 것으로 보입니다. talk page에 설명 된 이유와 함께 지금까지 359 개로 변경되었습니다.이 만족 최다 N

N ( N +5)/2 × (2 16 -1) < 2 는 같은 숫자는 단지 16 비트 엔티티 합산 적용 즉 32

, 이것은 당신이 모듈 감소를 수행하지 않고 블록을 추가하고, 여전히 uint32_t 오버 플로우를 방지 할 수 있습니다 시간의 라지 번호입니다. 4 비트 데이터 워드와 8 비트 누산기의 경우, 해당하는 값을 사용하여 계산 4 일 것이다

N ( N +5)/2 × (2 4 -1) < 2 8

데이터 크기를 변경하려면 해당 행을 수정해야합니다. 또한 더 큰 데이터 형식을 사용하여 코드의 합계를 유지하도록 코드를 변경하여 축소 전에 더 많은 블록을 합산 할 수 있습니다. 그러나이 경우 루프 내부에 하나 이상의 축소 단계가 필요할 수 있습니다. 당신이 sum1sum2에 대한 uint32_t를 사용한다면

는 예를 들어, 당신은 오버 플로우의 위험 전에 23,927 니블을 요약 할 수 있지만 그 이후에는 범위이 아래로 비등하는 형태 sum1 = (sum1 & 0xf) + (sum1 >> 4) 7 개 감소까지 필요 1에서 0x1e까지 원래의 방법으로 수행합니다. 이것을 (sum1 - 1)%0xf + 1으로 작성하는 것이 더 효율적일 수 있습니다. 어떤 경우에는 범위를 1에서 15까지 0에서 14까지 변경하고, 합계를 0으로 초기화하고 감소를 sum1 %= 0xf으로 작성합니다. 다른 범위를 사용하는 구현과의 호환성이 필요한 경우가 아니면

+1

"_ _ 4 비트 데이터 워드와 8 비트 누산기의 해당 값 ... _"이 올바른 값은 ** 3 ** (4가 아님)입니다. –