Выбрать главу

14.3.5. Как работает SCH_DSMARK.

Эта дисциплина выполняет следующие шаги:

• Если вставлена инструкция set_tc_index, то считывается поле DS и сохраняется в skb->tc_index.

• Вызывается классификатор. Он возвращает идентификатор класса, который будет сохранен в skb->tc_index. Если такой класс не найден, то используется класс по-умолчанию из параметра default_index. Если ни set_tc_index, ни default_index не объявлены, то результат может оказаться непредсказуемым.

• После этого управление передается внутренней qdisc, где вы можете повторно использовать результаты фильтрации. Идентификатор класса, возвращаемый внутренней qdisc, запоминается в skb->tc_index. Это значение будет использоваться в качестве индекса таблицы маска-значение. Конечный результат, который будет связан с пакетом, получается из выражения:

New_Ds_field = (Old_DS_field & mask) | value

• Таким образом, конечный результат получается в результате объединения по "И" ds_field и маски, и затем объединения по "ИЛИ" с параметром value. Следующая диаграмма иллюстрирует этот процесс: 

                         skb->ihp->tos

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >

     |                                                       |     ^

     | -- Если объявлена инструкция set_tc_index,            |     |  <-----Значение поля

     |    то значение DS переписывается в skb->tc_index      |     |O       DS может измениться

     |                                                      A|     |R

   +-|-+      +------+    +---+-+    внутренняя +-+     +---N|-----|----+

   | | |      | tc   |--->|   | |-->  . . .  -->| |     |   D|     |    |

   | | |----->|index |--->|   | |     Qdisc     | |---->|    v     |    |

   | | |      |filter|--->| | | +---------------+ |   ---->(mask,value) |

-->| O |      +------+    +-|-+--------------^----+  /  |  (.  ,  .)    |

   | | |          ^         |                |       |  |  (.  ,  .)    |

   | | +----------|---------|----------------|-------|--+  (.  ,  .)    |

   | | sch_dsmark |         |                |       |                  |

   +-|------------|---------|----------------|-------|------------------+

     |            |         | <- tc_index -> |       |

     |            |(read)   |    может       |       |  <--------------Индекс в таблице

     |            |         |    измениться  |       |                    (mask,value)

     v            |         v                v       |                              

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->

                         skb->tc_index           

 Как установить метку? Просто измените mask и value класса. См. следующий код:

tc class change dev eth0 classid 1:1 dsmark mask 0x3 value 0xb8

Это изменение пары (mask,value) в хеш-таблице, пометит пакеты, принадлежащие классу 1:1.

Теперь перейдем к описанию фильтра TC_INDEX. Кроме всего прочего, фильтр TC_INDEX может использоваться и в других конфигурациях, а не только в тех, которые включают DS услуги.

14.3.6. Фильтр TC_INDEX.

Базовый синтаксис команды, объявляющей фильтр TC_INDEX:

… tcindex [ hash SIZE ] [ mask MASK ] [ shift SHIFT ]

          [ pass_on | fall_through ]

          [ classid CLASSID ] [ police POLICE_SPEC ]

Ниже приводится пример, который описывает работу TC_INDEX (обратите внимание на места, выделенные жирным шрифтом:

tc qdisc add dev eth0 handle 1:0 root dsmark indices 64 set_tc_index

tc filter add dev eth0 parent 1:0 protocol ip prio 1 tcindex mask 0xfc shift 2

tc qdisc add dev eth0 parent 1:0 handle 2:0 cbq bandwidth 10Mbit cell 8 avpkt 1000 mpu 64

# EF traffic class

tc class add dev eth0 parent 2:0 classid 2:1 cbq bandwidth 10Mbit rate 1500Kbit avpkt 1000 prio 1 bounded isolated allot 1514 weight 1 maxburst 10

# Packet fifo qdisc for EF traffic

tc qdisc add dev eth0 parent 2:1 pfifo limit 5

tc filter add dev eth0 parent 2:0 protocol ip prio 1 handle 0x2e tcindex classid 2:1 pass_on

(Это неполный код, я просто привел часть примера EFCBQ, включенного в состав дистрибутива iproute2).

Будем исходить из предположения, что мы получаем пакет, помеченный как EF. Если вы прочитаете RFC2598, то увидите, что рекомендуемое значение DSCP для EF трафика — 101110. Это означает, что в поле DS будет записано 10111000 (не забывайте, что младшие биты в поле TOS не используются в DS), или 0xb8, в шестнадцатиричном представлении. 

              TC INDEX

              FILTER

   +---+      +-------+    +---+-+    +------+                +-+    +-------+

   |   |      |       |    |   | |    |FILTER|  +-+    +-+    | |    |       |

   |   |----->| MASK  | -> |   | | -> |HANDLE|->| |    | | -> | | -> |       |

   |   |  .   | =0xfc |    |   | |    |0x2E  |  | +----+ |    | |    |       |

   |   |  .   |       |    |   | |    +------+  +--------+    | |    |       |

   |   |  .   |       |    |   | |                            | |    |       |

-->|   |  .   | SHIFT |    |   | |                            | |    |       |-->

   |   |  .   | =2    |    |   | +----------------------------+ |    |       |