3. Канальный уровень В этой главе рассматриваются алгоритмы надежной и эффективной передачи данных между двумя соседними машинами. Под словом «соседние» мы понимаем то, что эти машины физически соединены проводом. Под проводом мы будем понимать любую физическую среду передачи данных, для которой справедливо, что биты поступают получателю точно в той последовательности, в какой их послал отправитель. Эта, простая, на первый взгляд, задача при детальном рассмотрении оказывается весьма сложной, если учесть, что при передаче по каналу могут возникать ошибки, возникают задержки, которые могут вызывать дублирование данных, и т.д. 3.1. Проблемы, решаемые на уровне канала данных На уровне канала данных решается ряд проблем, присущих только этому уровню: реализация сервиса для сетевого уровня, объединение битов, поступающих с физического уровня в кадры, обработка ошибок передачи, управление потоком кадров и другие. 3.1.1. Сервис, предоставляемый сетевому уровню Основная задача канального уровня - обеспечить сервис сетевому уровню по передаче и приему данных. Назначение этого сервиса - передать данные от процесса на сетевом уровне одной машины процессу на сетевой уровень другой машины. Как это происходит, показано на рисунке 3-1 (а). Фактически процесс передачи сложнее, что проиллюстрировано на рисунке 3-1 (b). Однако для простоты изложения мы будем придерживаться первой схемы. Рисунок 3-1. Передача данных - виртуальная (a), фактическая (b) Канальный уровень может обеспечивать различный сервис. Хотя этот сервис может варьироваться от системы к системе, есть три общих видов сервиса: 1. Сервис без уведомления и без соединения 2. Сервис с уведомлением и без соединения 3. Сервис с уведомлением и с соединением Сервис без уведомления и без соединения не предполагает, что до начала передачи должно быть установлено соединение, которое после передачи должно быть разорвано, что факт приема переданного кадра должен подтверждаться специальным сообщением. Если в результате помех на физическом уровне кадр будет потерян, то никаких попыток его восстановить на канальном уровне произведено не будет. Этот класс сервиса используется там, где физический уровень обеспечивает настолько высокую надежность при передаче, что потери кадров происходят редко и восстановление при потере кадров можно переложить на верхние уровни. Этот вид сервиса также применяют при передаче данных в реальном времени там, где лучше потерять часть данных, чем увеличить задержку при их доставке. Например, передача речи, видео изображения. Большинство ЛВС использует этот вид сервиса на канальном уровне. Следующий вид сервиса – сервис с уведомлением без соединения. В этом виде сервиса получение каждого посланного кадра должно быть подтверждено. Если подтверждения не пришло в течение определенного промежутка времени, то считают, что кадр не принят и должен быть послан опять. Этот вид сервиса используется в ненадежной физической среде передачи, например, беспроводной. Можно было бы, конечно, подтверждать не кадры, а все сообщение целиком на сетевом уровне. Однако это было бы невыгодно для больших сообщений. Например, если при передаче этих данных разрушалось бы 10-20% кадров, то повторная передача таких сообщений заняла бы больше времени, чем передача их отдельных фрагментов. Поэтому подтверждение на канальном уровне следует рассматривать как минимизацию затрат на передачу данных, а не необходимость. Наиболее сложный класс сервиса на канальном уровне - сервис с соединением и уведомлением. Этот класс сервиса предполагает, что до начала передачи между машинами устанавливают соединение и данные передают по этому соединению. Каждый передаваемый кадр нумеруется, и канальный уровень гарантирует, что он будет обязательно получен, причем только один раз, а также что все кадры будут получены в надлежащей последовательности. При сервисе без соединения этого гарантировать нельзя, потому что потеря подтверждения получения кадра приведет к его пересылке, что, в свою очередь, приведет к появлению нескольких идентичных кадров. Использование сервиса с соединением особенно полезно в том случае, когда канал образует СПД. Как мы уже видели, в СПД может быть достаточно сложная организация канала, при которой может происходить коммутация потоков данных самыми разными способами. Здесь полезно вспомнить структуру кадра в Х.25, рассмотренную в разделе 2.3. С точки зрения структуры, в Х.25 есть три вида кадров: с 3-битовым полем номера кадра, 7- и 12-битовым. Таким образом, в Х.25 предусмотрен сервис с соединением, причем, в зависимости от длины передаваемых данных, можно оптимизировать затраты на поддержку соединения. При сервисе с соединением и уведомлением передача данных разбивается на три этапа. На первом этапе устанавливают соединение: на обеих машинах инициируют переменные и счетчики, отслеживающие, кадры с какими номерами были приняты, а с какими нет. На втором этапе передают нужные кадры. На третьем - соединение разрывают: переменные, счетчики, буферы и другие ресурсы, использованные для поддержки соединения, освобождают. На рисунке 3-2 показан типичный фрагмент WAN, где два маршрутизатора соединены через телефонную линию. Когда кадр поступает на маршрутизатор, аппаратура проверяет контрольную сумму и передает кадр канальному уровню. Канальный уровень проверяет, является ли поступивший кадр ожидаемым, и если да, то передает пакет, расположенный в кадре, сетевому уровню на другой машине. Рисунок 3-2. Размещение протокола канального уровня 3.1.2. Разбиение на кадры Сервис, создаваемый канальным уровнем для сетевого уровня, опирается на сервис, создаваемый физическим уровнем. На физическом уровне принимают и передают потоки битов. Отправленное количество битов не обязательно должно быть равно принятому количеству битов, значение посланного бита также не обязательно должно быть равно принятому значению бита. Поэтому на канальном уровне нужны специальные действия по обнаружению и исправлению таких ошибок. Типовой подход к решению подобных проблем - разбиение потока битов на кадры, подсчет контрольной суммы для каждого кадра и передача этой суммы вместе с кадром данных. При приеме контрольная сумма вычисляется для каждого кадра заново и сравнивается с той, что хранится в кадре. Если они различаются, то это признак ошибки передачи. На канальном уровне должны быть приняты меры к исправлению ошибки, например, сбросить плохой кадр и послать сообщение об ошибке тому, кто прислал этот кадр. Разбиение потока битов на кадры - задача не простая. Один из способов - делать паузу между битами разных кадров. Однако в сети, где нет единого таймера, нет гарантии, что эта пауза всегда будет одинаковой, или, наоборот, не появится новая пауза там, где ее не должно было быть. Так как методы, использующие временные задержки, не надежны, применяются другие методы. Здесь мы рассмотрим четыре основных метода: 1. счетчик символов 2. вставка специальных стартовых и конечных символов 3. вставка стартовых и концевых битов 4. нарушение кодировки на физическом уровне Первый метод показан на рисунке 3-3. В начале каждого кадра указывают, сколько символов в кадре. При приеме кадра вновь подсчитывают число принятых символов. Если число полученных символов отлично от ожидаемого числа, то этот факт воспринимают как ошибку. Однако этот метод имеет существенный недостаток: счетчик символов может быть искажен при передаче. Тогда принимающая сторона не сможет обнаружить границы кадра. Даже обнаружив несовпадение контрольных сумм, принимающая сторона не сможет сообщить передающей, какой кадр надо переслать и сколько символов пропало. Этот метод сейчас используется редко. Рисунок 3-3. Поток символов: (а) без ошибок; (b) с одной ошибкой Второй метод построен на вставке специальных символов. Обычно для этого используют последовательность символов DLE STX для начала кадра и DLE ETX для конца кадра. DLE (Data Link Escape), STX (Start TeXt), ETX (End TeXt) – это специальные символы, имеющие специальную кодировку. При этом методе, если даже была потеряна граница текущего кадра, нужно просто найти ближайшую последовательность DLE STX или DLE ETX. Однако здесь есть одна опасность: при передаче чисел или программы в объектном коде такие последовательности могут уже содержаться в передаваемых данных. Для решения этой проблемы используют прием экранирования: каждая последовательность DLE или STX просто дублируется в передаваемых данных. Поэтому, если при приеме есть два последовательных DLE, то один удаляется. Этот метод проиллюстрирован на рисунке 3-4. Рисунок 3-4. Метод экранирования Основным недостатком только что рассмотренного метода является то, что он жестко связан с размером байта и конкретным методом кодировки символов - ASCII. По мере развития сетей эта связь становилась все более и более обременительной. Кроме этого, на стороне отправителя надо было просматривать кадр, чтобы обнаружить недопустимые последовательности. Был предложен иной прием, позволяющий использовать любое число битов на символ и любую кодировку. Его идея состоит в том, что каждый кадр начинается и заканчивается специальным флаг-байтом: 01111110. Чтобы избежать аналогичной последовательности, внутри кадра поступают следующим образом. Посылающая сторона, встретив последовательно 5 единиц, обязательно вставит 0. Принимающая сторона, приняв 5 последовательных единиц, обязательно удалит следующий за ними 0. Таким образом, если в передаваемых данных встретится конфигурация флаг-байта, то она будет преобразована в конфигурацию 011111010. Этот метод иллюстрирует рисунок 3-5. Этот метод прозрачен для сетевого уровня так же, как и метод вставки байтов. Рисунок 3-5. Замена шестой единицы нулем Таким образом, кадр легко может быть распознан по флаг-байту. Если граница очередного кадра по какой-то причине была потеряна, то все что надо делать – «ловить» ближайший флаг-байт. Последний метод - нарушение кодировки используется там, где применяется специальная кодировка битов на физическом уровне. Например, пусть для передачи одного бита используется два импульса. «1» кодируется как переход «высокое-низкое», «0» - как переход «низкое-высокое». Сочетания «низкое-низкое» или «высокое-высокое» не используются для передачи данных. Их и используют для границ кадра. Так делают в стандарте IEEE 802 для ЛВС, который мы рассмотрим позже. На практике используют, как правило, комбинацию этих методов. Например, счетчик символов с одним из выше перечисленных. Тогда, если число символов в кадре совпадает с кодировкой границы кадра, кадр считается переданным правильно. 3.1.3. Обнаружение ошибок Решив проблему разбиения на кадры, мы приходим к следующей проблеме: как обеспечить, чтобы кадры попадали на сетевой уровень в надлежащей последовательности? Если для отправляющей стороны все равно, в какой последовательности поступают кадры, то этой проблемы нет. Например, если нам нужен сервис без уведомления и без соединения. Однако как быть, если нам нужен сервис с уведомлением и с соединением? Для решения этой проблемы устанавливают обратную связь между отправителем и получателем в виде кадра подтверждения. Если кадр-подтверждение несет положительную информацию, то считается, что переданные кадры прошли нормально, если же в нем сообщение об ошибке, то переданные кадры надо передать заново. Однако возможны ситуации, когда из-за ошибок в канале кадр исчезнет целиком. В этом случае получатель не будет никак реагировать, а отправитель будет сколь угодно долго ждать подтверждения. Для решения этой проблемы на канальном уровне вводят таймеры. Когда передается очередной кадр, то одновременно устанавливается таймер на определенное время. Этого времени должно хватать на то, чтобы получатель получил кадр и отправил уведомление, а отправитель получил его. Если отправитель не получит уведомление раньше, чем истечет время, установленное на таймере, то он будет считать, что кадр потерян и повторит его еще раз. Однако если кадр-подтверждение был утерян, то вполне возможно, что один и тот же кадр получатель получит дважды. Как быть? Для решения этой проблемы каждому кадру присваивают порядковый номер. С помощью этого номера получатель может обнаружить дубли. Итак, таймеры и нумерация кадров - основные средства на канальном уровне, обеспечивающие доставку каждого кадра до сетевого уровня в единственном экземпляре и в нужном порядке. 3.1.4. Управление потоком Другая важная проблема, которую надо решать на канальном уровне - управление потоком. Вполне может случиться, что отправитель будет посылать кадры столь часто, что получатель не будет успевать их обрабатывать. Это может произойти, если, например, машина-отправитель более мощная или загружена слабее, чем машина-получатель. Для борьбы с такими ситуациями вводят специальный механизм управления потоком. Этот механизм предполагает обратную связь между отправителем и получателем, которая позволяет им урегулировать темп передачи. Существует много схем управления потоком, но все они в основе своей используют следующий сценарий. Прежде чем отправитель начнет передачу, он спрашивает у получателя, сколько кадров тот может принять. Получатель сообщает ему определенное число. Отправитель, после того как передаст это число кадров, должен приостановить передачу и спросить у получателя еще раз, сколько кадров тот может принять, и т.д. Позднее на примерах мы познакомимся с конкретными механизмами управления потоком. 3.2. Обнаружение и исправление ошибок При рассмотрении физической среды мы отмечали, что у беспроводных систем связи и аналоговых каналов, например, абонентской линии в телефонных сетях, достаточно высокий уровень ошибок в канале. Поэтому ошибки при передаче на физическом уровне - это реальность, которую надо обязательно учитывать. В разных средах характер ошибок разный. Ошибки могут быть одиночные, а могут возникать группами, сразу по несколько штук. У групповых ошибок есть свои достоинства и недостатки. Достоинство заключается в следующем. Пусть данные передаются блоками по 1000 бит, а частота ошибки - 10-3 на бит, т.е. одна на каждые 1000 бит. Если ошибки изолированные и независимые, то практически каждый блок в среднем будет содержать ошибку. Если же они возникают группами по 100 сразу, то ошибки будут содержать в среднем 1-2 блока из каждых 100. Недостатком групповых ошибок является то, что их труднее обнаруживать и исправлять, чем одиночные. 3.2.1. Коды с исправлением ошибок Для надежной передачи кодов было предложено два основных метода. Первый - внести избыточность в форме дополнительных битов в передаваемый блок данных так, чтобы, анализируя полученный блок, можно было бы указать, где возникли искажения. Это так называемые коды с исправлением ошибок. Второй метод - внести избыточность, но лишь настолько, чтобы, анализируя полученные данные, можно было сказать: есть в переданном блоке ошибки или нет. Это так называемые коды с обнаружением ошибок. Пусть данные занимают m разрядов, и мы добавляем r избыточных, контрольных разрядов. Нам необходимо передать слово длины n = m+r, которое называют n-битовым кодословом. Пусть у нас есть два кодослова - 10001001 и 10110001. С помощью операции EXCLUSIVE OR легко определить число различных разрядов в двух кодословах. В данном случае таких разрядов 3. Количество разных битов в двух кодословах называется расстоянием Хемминга между этими словами. Поэтому, если два кодослова находятся на расстоянии d по Хеммингу, это значит, что надо преобразовать ровно d разрядов, чтобы преобразовать одно кодослово в другое. В силу того, что избыточные контрольные разряды могут принимать только вполне определенные значения, то не все 2n кодовых слов возможны. Зная алгоритм установки контрольных разрядов, мы можем вычислить минимальное расстояние по Хеммингу между двумя правильными кодословами. Способен код исправлять ошибки или только обнаруживать их - зависит от расстояния между кодословами по Хеммингу. Если мы хотим обнаруживать d ошибок, то необходимо, чтобы два кодослова отстояли друг от друга на расстоянии d+1. Тогда, если принятый код отстоит на расстоянии k Список предлагаемых параметров и их значений Configure-ack < Все параметры приняты Configure-nak < Некоторые параметры не приняты Configure-reject < Некоторые параметры недоступны Terminate-request > Требуется закрыть соединение Terminate-ack < ОК, соединение закрыто Code-reject < Получен неизвестный запрос Protocol-reject < Запрошен неизвестный протокол Echo-request > Пришлите кадр обратно Echo-reply < Вот ваш кадр Discard-request > Сбросьте этот кадр (для проверки) 3.5.4. Уровень канала данных в ATM Теперь вернемся к уровням АТМ-протокола. Физический уровень в АТМ покрывает физический уровень и уровень канала данных в OSI. Поскольку физический уровень АТМ на подуровне физической зависимости не предъявляет каких-то специальных требований к физической среде, то мы сосредоточим наше внимание на ТС-подуровне - подуровне преобразования при передаче. Когда прикладная программа посылает сообщение, оно движется вниз по АТМ-стеку, получая заголовки, концевики, разбивается на ячейки и т.д. Проследим, что с ним происходит, когда ячейки достигают ТС-подуровня и далее. 3.5.4.1. Передача ячеек Первый шаг - вычисление контрольной суммы заголовка. Заголовок состоит из 5 байт - 4 байта идентифицируют виртуальное соединение и несут контрольную информацию, за ними следует 1 байт с контрольной суммой. Контрольная сумма защищает только первые четыре байта и не затрагивает данные в ячейке. Контрольная сумма вычисляется как остаток от деления содержимого 4 байтов на полином x8+x2+x+1. К этому остатку добавляется константа 01010101 для повышения надежности, в случае если заголовок содержит много нулей. Решение защищать контрольной суммой только управляющую информацию было принято с целью сократить затраты на обработку на нижних уровнях. Защита собственно данных возложена на верхние уровни, если это необходимо. Как мы уже отмечали, многие приложения реального времени - передача видео-, аудиоданных - более критичны к времени передачи, чем к степени искажения отдельных ячеек. Поскольку контрольная сумма покрывает только заголовок, то этот байт так и называется - HEC (Header Error Control - контроль ошибки в заголовке). Другим важным фактором, повлиявшим на выбор этой схемы контрольной суммы, было то, что основной средой для АТМ является оптоволокно. Исследования, выполненные компанией АТ&Т, показали, что оптоволокно - высоконадежная среда и единичные ошибки происходят в ней с вероятностью менее 1%. Схема НЕС прекрасно справляется как с однобитными ошибками, так и множественными. Для надежной передачи ячеек была предложена схема, когда две последовательные ячейки объединяются через EXCLUSIVE OR, после чего получается новая ячейка, которая добавляется в последовательность после первых двух. В результате если хоть одна ячейка была принята с ошибкой или потеряна, то она легко может быть восстановлена. После того как НЕС вычислен и добавлен в заголовок, ячейка готова к передаче. Среда передачи может быть двух категорий - синхронной и асинхронной. В асинхронной среде ячейка посылается сразу, как только она готова к передаче. В синхронной среде ячейка передается в соответствии с временными соглашениями. Если нет ячейки для передачи, то ТС-подуровень должен сгенерировать специальную ячейку ожидания. Другой вид служебных ячеек - OAM (Operation And Maintenance). Эти ячейки используются АТМ-переключателями для проверки работоспособности системы. Ячейки ожидания обрабатываются соответствующим ТС-подуровнем, а ОАМ-ячейки передаются на АТМ-уровень. Другой важной функцией ТС подуровня является генерирование ячеек в формате физической среды передачи. Это значит, что ТС-подуровень генерирует обычную АТС-ячейку и упаковывает ее в кадр надлежащей среды передачи. 3.5.4.2. Прием ячеек Итак, на выходе ТС-подуровень формирует НЕС-заголовок, преобразует ячейку в кадр, формирует АТМ-ячейки и передает поток битов на физический уровень. На противоположном конце ТС-подуровень производит те же самые действия, но в обратном порядке: разбивает поток бит на кадры, выделяет ячейки, проверяет НЕС-заголовки и передает ячейки на АТМ-уровень. Самое трудное - выделить кадр из потока битов. На уровне битов ячейка - это 53х8 = 424 бита. Нет маркеров ни начала, ни конца кадра. Как определить границы кадра? На ТС-подуровне есть сдвиговый регистр на 40 бит. Если в этих 40 бит правые 8 представляют собой НЕС, то последующие 32 левых бита - заголовок ячейки. Если условие не выполнено, то все сдвигается на один бит и проверка повторяется. Этот процесс продолжается до тех пор, пока не будет обнаружен НЕС. Схема распознавания в том виде, как она описана не надежна. Вероятность того, что случайный байт будет выглядеть как НЕС, равна 1/256. Чтобы исправить эту схему, используют автомат, схема состояний которого изображена на рисунке 3-24. Есть три состояния: HUNT, PRESYNCH, SYNCH. В состоянии HUNT ищется НЕС. Как только найден похожий байт, автомат переходит в состояние PRESYNCH и отчитывает следующие 53 байта. Если предположение о том, что найденный НЕС - начало ячейки, то сдвиг на 53 байта приведет к следующему НЕС. Происходит проверка последовательно ? ячеек, после этого происходит переход в состояние SYNCH. Рисунок 3-24. Процедура поиска ячеек Если в состоянии SYNCH ? последовательных ячеек оказались плохими, происходит переход в состояние HUNT.