2014-10-18 2 views
0

я испытывал влияние установки различных IP_MTU_DISCOVER значений с помощью setsockopt() на UdP фрагментации пакетов и выяснил (из man страницы ip(7)), что мне нужно, чтобы установить это значение IP_PMTUDISC_WANT или IP_PMTUDISC_DONT, чтобы выключить «не фрагментировать» флаг , Тем не менее, я получаю socket.error: [Errno 90] Message too long, когда пытаюсь отправить пакет.Почему не отключен флаг «dont fragment»?

import IN, socket 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 

hostname = 'localhost' 
s.connect((hostname, 1060)) 

s.setsockopt(socket.IPPROTO_IP, IN.IP_MTU_DISCOVER, IN.IP_PMTUDISC_DONT) 
mtu = s.getsockopt(socket.IPPROTO_IP, IN.IP_MTU) 

print 'MTU:', mtu 
s.send('.' * (mtu + 1)) 
print 'Big packet sent' 

Спасибо

ответ

2

Давайте сначала сделать повторение, как PMTU работает для UDP.

  1. Конечная точка IP начинается с заданного MTU, как правило, MTU непосредственно связанного соединения.
  2. При отправке пакетов конечная точка всегда устанавливает бит DF.
  3. Если транзитный маршрутизатор решает, что он не может отправить пакет без фрагментации пакета, он вернет пакет ICMP Destination Unreachable с кодом ошибки 4 и MTU следующего перехода.
  4. Конечная точка IP получает ICMP недоступную и адаптирует свой PMTU.
  5. Конечная точка IP решает, что делать с исходным пакетом (повторная передача, уровень сигнала приложения, ...).

Очень важно отметить, что PMTU не происходит автоматически. Нет встроенного пакета зондов, который обнаружит MTU перед вами (приложение), начнет отправлять фактические данные.

Так Linux управляет этим (для дейтаграмм), используя следующие флаги:

  • IP_PMTUDISC_WANT Выполняет PMTU, как описано выше. Если приложение отправляет пакет, который слишком велик для известного MTU, слой сокета будет его фрагментировать. Исходящие пакеты (включая фрагменты) будут иметь бит DF.
  • IP_PMTUDISC_DONT Не делайте открытие PMTU.
  • IP_PMTUDISC_DO Обнаружение PMTU. Если приложение отправляет пакет, который является слишком большим для известного MTU, отправьте сообщение об ошибке в приложение.
  • IP_PMTUDISC_PROBE Устанавливает бит DF для обнаружения PMTU, но игнорирует изученный в настоящее время MTU. Поэтому, если приложение отправляет слишком большой пакет, он попытается отправить его в любом случае. Это полезно, чтобы время от времени посылать зонд, чтобы узнать, не увеличился ли PMTU.

Теперь одна часть уведомления, что IP_PMTUDISC_DONT не указывает, что делать, если пакет на самом деле больше, чем ваш текущий MTU, то есть один из вашей прямой ссылке. Поэтому, скорее всего, он оставляет этот выбор до интерфейса, который фактически должен отправить пакет. Большинство интерфейсов должны фактически фрагментировать пакет, поскольку бит DF не отправляется. Однако вы используете локальный интерфейс link, который обычно представляет собой программный интерфейс с меньшими возможностями. Возможно, что в вашем дистрибутиве это не поддерживает фрагментацию и поэтому отправляет ошибку. Это имеет смысл, принять этот вывод из моей машины:

In [6]: s.getsockopt(socket.IPPROTO_IP, 14) #14 = IP_MTU, just wasn't in my python lib. 
Out[6]: 16436 

Это показывает, что MTU для интерфейса локальной связи достаточно огромен в сети плане, так почему он должен беспокоиться, поддерживающие фрагментациями, чтобы начать с. Это, как говорится, в моей системе, это действительно сработало.

+0

Я получаю ту же ошибку, когда я заменяю 'IP_PMTUDISC_DONT' на' IP_PMTUDISC_WANT', почему? Он должен фрагментировать пакет правильно? – Apoorv

+0

Вы прочитали мой весь ответ? В конце я указываю, что может пойти не так с фрагментацией независимо от этой настройки. – KillianDS

+0

Почему downvote? – KillianDS

Смежные вопросы