RFC 1071 — Расчет контрольных сумм в Internet
Статус документа
В этом документе дается обзор эффективности методов и алгоритмов расчета контрольных сумм Internet. Документ не является стандартом, но описывает ряд полезных методов реализации. Документ может распространяться свободно.
1. Введение
В этом документе обсуждаются методы эффективного расчета контрольных сумм, используемых стандартными протоколами Internet — IP, UDP и TCP.
Эффективность расчета контрольных сумм очень важна с точки зрения производительности. В результате эффективной реализации остальных компонент протокольной обработки расчет контрольных сумм стал, например, одним из факторов, ограничивающих производительность TCP. Обычно для процедур расчета контрольных сумм используется ручная оптимизация с учетом особенностей работы конкретного процессора — экономия доли микросекунды в расчете на один байт данных TCP может привести к существенному снижению суммарного расхода процессорного времени.
В общих чертах алгоритм расчета контрольной суммы очень прост:
Соседние октеты информации, для которой создается контрольная сумма, объединяются в 16-битовые целые числа и для этих чисел формируется 16-битовое поразрядное дополнение до 1.
При расчете контрольной суммы значение самого поля контрольной суммы принимается нулевым. Для 16-битовых поразрядных дополнений вычисляется сумма. Для полученного в результате 16-битового целого числа создается 16-битовое поразрядное дополнение до 1 и помещается в поле контрольной суммы.
Для проверки контрольной суммы вычисляется сумма поразрядных дополнений до 1 для того же набора октетов, включая поле контрольной суммы. Если в результате получается значение, все биты которого равны 1 (-0 в арифметике дополнений до 1), это говорит о корректности контрольной суммы.
Предположим, что контрольная сумма определяется для последовательности октетов A, B, C, D, ... , Y, Z. Будем использовать обозначение [a,b] для 16-битовых целых чисел a*256+b, где a и b являются байтами. Тогда сумма 16-битовых дополнений до 1 для этих байтов будет задаваться одним из выражений:
[A,B] +' [C,D] +' ... +' [Y,Z] [1] [A,B] +' [C,D] +' ... +' [Z,0] [2]
где +' указывает сложение поразрядных дополнений до 1. Приведенные выше выражения относятся к последовательностям с четным и нечетным количеством байтов, соответственно.
В двоичных машинах сумма поразрядных дополнений до единицы должна вычисляться с использованием «кругового переноса», т. е, при переполнении старшего бита значение переносится в младший, как показано в примерах ниже.
В параграфе 2 рассматриваются свойства контрольной суммы, которые могут использоваться для ускорения расчетов. Параграф 3 содержит несколько числовых примеров для наиболее важных методов реализации. В параграфе 4 приведены несколько конкретных алгоритмов для использования с распространенными типами процессоров. Авторы признательны Van Jacobson и Charley Kline за их вклад в алгоритмы, опубликованные в этом параграфе.
Свойства контрольных сумм Internet изначально были рассмотрены Биллом Пламмером (Bill Plummer) в документе IEN-45, названном «Checksum Function Design». Поскольку до^мент IEN-45 не получил широкого распространения, он включен в качестве приложения к данному RFC.
2. Расчет контрольной суммы
Эта простая контрольная сумма имеет множество чудесных математических свойств, которые могут быть использованы для вычисления расчетов. Эти свойства обсуждаются ниже.
- A. Кумулятивность и ассоциативность
После того, как байты были распределены на четные и нечетные, суммирование может проводиться в любом порядке с возможностью разбиения на произвольные группы.
Например, сумму [1] можно представить в форме:
( [A,B] +' [C,D] +' ... +' [J,0] ) +' ( [0,K] +' ... +' [Y,Z] ) [3]- B. Независимость от порядка байтов
-
Сумма 16-битовых целых чисел может вычисляться для любого порядка байтов. Т. е., если мы рассчитаем сумму, сменив порядок байтов:
[B,A] +' [D,C] +' ... +' [Z,Y] [4]
результат будет отличаться от значения [1] только сменой порядка байтов! Для того, чтобы это стало более понятным, отметим, что в обоих случаях перенос происходит из бита 15 в бит 0 и из бита 7 в бит 8. Иными словами, смена порядка суммируемых байтов лишь приводит к смене порядка байтов результата, но сохраняет порядок битов в каждом байте результата.
Следовательно, сумма может рассчитываться одинаково, независимо от используемого оборудованием порядка байтов («big-endian» или «little-endian»). В качестве примера предположим, что машина «little-endian» вычисляет контрольную сумму данных, хранящихся в памяти с использованием сетевого («big-endian») порядка байтов. Выборка каждого 16-битового слова будет приводить к смене мест байт в словах, что приведет к суммирования [4]; однако при сохранении результата в памяти снова произойдет смена мест байтов и будет восстановлен сетевой порядок.
Смена мест байтов может явно использоваться для решения проблем, связанных с выравниванием по границе. Например, вторая группа в [3] может быть рассчитана, как:
[K,L] +' ... +' [Z,0]
если байты результата поменять местами до того, как они будут добавлены к сумме первой группы (см. пример ниже).
- C. Параллельное суммирование
-
На машинах с размером слова, кратным 16 битам, можно использовать дополнительное увеличение скорости расчетов. Поскольку сложение ассоциативно, мы не обязаны складывать целые числа в порядке их следования в сообщении. Вместо этого мы можем складывать их «параллельно» используя более длинные машинные слова.
Для параллельного расчета контрольной суммы просто выполняется операция поразрядного дополнения до 1 для стандартного размера машинного слова. Например, на 32-разрядных машинах мы можем складывать одновременно по 4 байта : [A,B,C,D]+'... После завершения расчета результат более длинное слово «вталкивается» в 16 битов путем сложения 16-битовых сегментов. При каждом сложении могут происходить переносы битов, которые следует учитывать.
Поскольку порядок байтов не имеет значения, мы можем посчитать 32-битовых слов [D,C,B,A]+'... или [B,A,D,C]+'... и потом поменять местами байты окончательной 16-битовой суммы (см. примеры ниже). Допускаются любые перестановки, которые будут обеспечивать сложение всех четных байтов в один байт суммы, а всех нечетных — в другой байт.
Ниже описано еще несколько методов ускорения расчета контрольных сумм:
- Отложенные переносы
Для некоторых типов процессоров эффективность расчета контрольных сумм может быть повышена за счет того, что добавление битов переноса осуществляется после завершения цикла суммирования.
Можно складывать 16-битовые слова в 32-битовую переменную, чтобы все биты переноса складывались в старших 16 битах. Этот вариант позволяет отказаться от использования команд, понимающих перенос битов, но требует удвоенного числа операций сложения, поскольку складываются 32-битовые сегменты. Который из вариантов будет быстрее, зависит от системной архитектуры.
- Использование циклов
- Для повышения эффективности часто бывает полезно создание внутреннего цикла суммирования, выполняющего серию команд сложения за один проход. Этот метод часто дает существенное повышение эффективности, хотя может значительно усложнить логику программы.
- Объединение суммирования и копирования данных
- Кроме вычисления суммы время расходуется также на копирование данных из одного места памяти в другое. В обоих случаях узким местом является скорость шины памяти (например, скорость выборки данных из памяти). На некоторых машинах (особенно на сравнительно медленных и простых микрокомпьютерах) производительность можно существенно повысить за счет объединения операций суммирования и копирования при котором происходит только одна выборка из памяти для обеих операций.
- Нарастающие обновления
В некоторых случаях можно избежать повторного вычисления всей контрольной суммы, если сменился только заголовок. Наиболее ярким примером может служить изменение поля TTL в заголовке IP при пересылке пакетов шлюзом, но есть и другие примеры (скажем, обновление source route). В таких случаях можно обновить контрольную сумму даже без просмотра сообщения или дейтаграммы.
Для обновления контрольной суммы достаточно просто добавить к ней разность между новым и прежним значениями изменившегося 16-битового слова. Чтобы понять, как это работает, напомним, что каждое целое число имеет аддитивную инверсию, а операция сложения ассоциативна. Если исходное значение слова обозначить m, новое значение — m', а исходную контрольную сумму — C, тогда новая сумма C' будет равна:
C' = C + (-m) + m' = C + (m' - m)
3. Численные примеры
Ниже рассматриваются явные примеры расчета сумм дополнений до 1 на машине с дополнением до 2. Примеры показывают, как одну и ту же сумму можно рассчитать путем сложения байтов, 16-битовых слов с нормальным и измененным порядком байтов, а также 32-битовых слов с 3 вариантами порядка байтов. Все числа задаются в шестнадцатеричном формате.
Byte-by-byte "Normal" Swapped
Order Order
Byte 0/1: 00 01 0001 0100
Byte 2/3: f2 03 f203 03f2
Byte 4/5: f4 f5 f4f5 f5f4
Byte 6/7: f6 f7 f6f7 f7f6
--- --- ----- -----
Sum1: 2dc 1f0 2ddf0 1f2dc
dc f0 ddf0 f2dc
Carrys: 1 2 2 1
-- -- ---- ----
Sum2: dd f2 ddf2 f2dd
Final Swap: dd f2 ddf2 ddf2
Byte 0/1/2/3: 0001f203 010003f2 03f20100
Byte 4/5/6/7: f4f5f6f7 f5f4f7f6 f7f6f5f4
-------- -------- --------
Sum1: 0f4f7e8fa 0f6f4fbe8 0fbe8f6f4
Carries: 0 0 0
Top half: f4f7 f6f4 fbe8
Bottom half: e8fa fbe8 f6f4
----- ----- -----
Sum2: 1ddf1 1f2dc 1f2dc
ddf1 f2dc f2dc
Carrys: 1 1 1
---- ---- ----
Sum3: ddf2 f2dd f2dd
Final Swap: ddf2 ddf2 ddf2
В заключение приводится пример суммирования в виде двух групп, из которых вторая начинается на нечетной границе.
Byte-by-byte Normal
Order
Byte 0/1: 00 01 0001
Byte 2/ : f2 (00) f200
--- --- -----
Sum1: f2 01 f201
Byte 4/5: 03 f4 03f4
Byte 6/7: f5 f6 f5f6
Byte 8/: f7 (00) f700
--- --- -----
Sum2: 1f0ea
Sum2: f0ea
Carry: 1
-----
Sum3: f0eb
Sum1: f201
Sum3 byte swapped: ebf0
-----
Sum4: 1ddf1
Sum4: ddf1
Carry: 1
-----
Sum5: ddf2
4. Примеры реализации
Ниже приводятся примеры реализации алгоритма подсчета контрольных сумм Internet, которые доказали свою эффективность для разных типов CPU. В каждом случае приводится ядро алгоритма без включения дополнительного кода (например, свящывания подпрограмм).
4.1. Код на языке C
Приведенный ниже пример на языке C показывает расчет контрольной суммы с использованием внутреннего цикла сложения 16-битовых значений в 32-битовый «аккумулятор».
in 6
{
/* Расчет контрольной суммы Internet для count байтов,
* начиная с addr.
*/
register long sum = 0;
while( count > 1 ) {
/* Внутренний цикл */
sum += * (unsigned short) addr++;
count -= 2;
}
/* Прибавляем байт переноса, если он есть */
if( count > 0 )
sum += * (unsigned char *) addr;
/* поместим 32-битовую сумму в 16 битов */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
checksum = ~sum;
}
4.2. Motorola 68020
Ниже приведен пример ассемблерной реализации алгоритма для процессора Motorola 68020. Этот вариант использует суммирование 32-битовых значений в один прием и использует внутренний цикл сложения с 16 операциями. Для простоты была опущена логика дополнения последнего слова для случаев, когда число суммируемых байтов не кратно 4. Результат сохраняется в регистре d0.
При тактовой частоте процессора 20 МГц время расчета контрольной суммы составляет 134 мксек/кбайт. Разработал этот алгоритм Van Jacobson.
movl d1,d2
lsrl #6,d1 | count/64 = # число проходов цикла
andl #0x3c,d2 | Нахождение частей блока
negl d2
andb #0xf,cc | Сброс X (расширенный флаг переноса)
jmp pc@(2$-.-2:b,d2) | Переход в цикл
1$: | Начало внутреннего цикла...
movl a0@+,d2 | Выборка 32-битового слова
addxl d2,d0 | Сложение слова и предыдущего переноса
movl a0@+,d2 | Выборка 32-битового слова
addxl d2,d0 | Сложение слова и предыдущего переноса
| ... еще 14 повторов
2$:
dbra d1,1$ | (Отметим, что dbra не воздействует на X)
movl d0,d1 | Вталкивание 32 битов суммы в 16 битов
swap d1 | (Отметим, что swap не воздействует на X)
addxw d1,d0
jcc 3$
addw #1,d0
3$:
andl #0xffff,d0
4.3. Cray
Ниже приводится ассемблерная реализация алгоритма для процессора Cray, которую предложил Charley Kline. Расчет контрольной суммы производится как векторная операция, обеспечивающая одновременное сложение до 512 байтов с базовым блоком суммирования 32 бита. Для простоты из примера исключены фрагменты, обеспечивающие возможность работы с короткими блоками.
Регистр A1 содержит адрес 512-байтового блока памяти для контрольной суммы. Две первых копии данных загружаются в два векторных регистра. Один вектор сдвигается вправо на 32 бита, а для второго используется операция AND с 32-битовой маской. После этого векторы складываются. Поскольку все эти операции связаны в цепочку, они дают один результат на каждый цикл процессора. Далее производится сжатие (collaps) результирующего вектора в цикле, который прибавляет каждый элемент к скалярному регистру. В заключение выполняется перенос и результат помещается в 16 битов.
EBM
A0 A1
VL 64 используются полные векторы
S1 <32 формируется 32-битовая маска из правой части.
A2 32
V1 ,A0,1 загрузка пакета в V1
V2 S1&V1 формирование "правых" 32 битов в V2.
V3 V1>A2 формирование "левых" 32 битов в V3.
V1 V2+V3 Сложение.
A2 63 Подготовка к сжатию в скаляр.
S1 0
S4 <16 Form 16-bit mask from the right.
A4 16
CK$LOOP S2 V1,A2
A2 A2-1
A0 A2
S1 S1+S2
JAN CK$LOOP
S2 S1&S4 формирование " правых" 16 битов в S2
S1 S1>A4 формирование " левых" 16 битов в S1
S1 S1+S2
S2 S1&S4 формирование " правых" 16 битов в S2
S1 S1>A4 формирование " левых" 16 битов в S1
S1 S1+S2
S1 #S1 Получение дополнения до 1
CMR В этой точке S1 будет содержать контрольную сумму.
4.4. IBM 370
Следующий пример на ассемблере для процессора IBM 370 суммирует по 4 байта одновременно. Для простоты опущен код дополнения, используемых для выравнивания данных по 4-байтовой границе и обращения порядка байтов, когда это требуется. Результат сохраняется в регистре RCARRY.
Этот код на процессоре IBM 3090 давал время расчета 27 мксек/кбайт при расчете контрольной суммы байтов, содержащих только единицы. Время расчета снижается до 24.3 мксек/кбайт, если применить средства выравнивания слов (специальная обработка в начале и в конце, а при необходимости замена местами байтов при расчете с нечетной позиции).
* Регистры RADDR и RCOUNT содержат адрес и размер суммируемого блока.
*
* (RCARRY, RSUM) должны быть парой регистров (четный/нечетный).
* (RCOUNT, RMOD) должны быть парой регистров (четный/нечетный).
*
CHECKSUM SR RSUM,RSUM Сброс рабочих регистров.
SR RCARRY,RCARRY
LA RONE,1 Установка значения 1.
*
SRDA RCOUNT,6 Count/64 в RCOUNT.
AR RCOUNT,RONE +1 = # число циклов.
SRL RMOD,26 Размер частичного блока в RMOD.
AR RADDR,R3 Выравнивание для компенсации перехода
S RADDR,=F(64) в цикл.
SRL RMOD,1 (RMOD/4)*2 - индекс "полуслов".
LH RMOD,DOPEVEC9(RMOD) используется специальный вектор для
B LOOP(RMOD) смещения и перехода в цикл...
*
* Внутренний цикл:
*
LOOP AL RSUM,0(,RADDR) Сложить логические слова
BC 12,*+6 Переход, если нет переноса
AR RCARRY,RONE Добавит ь 1 переноса
AL RSUM,4(,RADDR) Сложить логические слова
BC 12,*+6 Branch i f no carry
AR RCARRY,RONE Добавить 1 переноса
*
* ... еще 14 повторов ...
*
A RADDR,=F'64' Увеличить адресный указатель
BCT RCOUNT,LOOP Перейти к Count
*
* Прибавить переносы к сумме и "затолкнуть" в 16 битов
*
ALR RCARRY,RSUM Сложить слова SUM и CARRY
BC 12,*+6 и учесть возможный перенос
AR RCARRY,RONE
SRDL RCARRY,16 Поместить 32-битовую сумму
SRL RSUM,16 в 16 битов
ALR RCARRY,RSUM
C RCARRY,=X'0000FFFF' Прибавить оставшийся перенос
BNH DONE
S RCARRY,=X'0000FFFF'
DONE X RCARRY,=X'0000FFFF' Дополнить до 1
Литература
- Cerf, V.G. and Kahn, Robert E., «A Protocol for Packet Network Communications», IEEE Transactions on Communications, vol. COM-22, No. 5, May 1974.
- Kahn, Robert E., «The Organization of Computer Resources into a Packet Radio Network», IEEE Transactions on Communications, vol. COM-25, no. 1, pp. 169-178, January 1977.
- Jacobs, Irwin, et al., «CPODA — A Demand Assignment Protocol for SatNet», Fifth Data Communications Symposium, September 27-9, 1977, Snowbird, Utah
- Bolt Beranek and Newman, Inc. «Specifications for the Interconnection of a Host and an IMP», Report 1822, January 1976 edition.
- Dean, Richard A., «Elements of Abstract Algebra», John Wyley and Sons, Inc., 1966
- Peterson, W. Wesley, «Error Correcting Codes», M.I.T. Press Cambridge MA, 4th edition, 1968.
- Avizienis, Algirdas, «A Study of the Effectiveness of Fault-Detecting Codes for Binary Arithmetic», Jet Propulsion Laboratory Technical Report No. 32-711, September 1, 1965.
- Kirstein, Peter, private communication
- Cerf, V. G. and Postel, Jonathan B., «Specification of Internetwork Transmission Control Program Version 3», University of Southern California Information Sciences Institute, January 1978.
- Digital Equipment Corporation, «PDP-10 Reference Handbook», 1970, pp. 114-5.
- Swanson, Robert, «Understanding Cyclic Redundancy Codes», Computer Design, November, 1975, pp. 93-99.
- Clements, Robert C., private communication.
- Conklin, Peter F., and Rodgers, David P., «Advanced Minicomputer Designed by Team Evaluation of Hardware/Software Tradeoffs», Computer Design, April 1978, pp. 136-7.
Перевод на русский язык
Николай Малых, moc.milib@hkylamn
