Как найти значение mtu сети через код (в python)?

Мне нужно написать код, в котором мне нужно отправлять данные по протоколу udp в python. Мне нужно установить размер пакета равным значению MTU сети. Есть ли способ, которым я могу определить значение MTU сети, написав код на python?


person Rahul Katare    schedule 23.12.2012    source источник


Ответы (3)


Этот ответ был взят с сайта http://books.google.co.il/books?id=9HGUc8AO2xQC&pg=PA31&lpg=PA31&dq#v=onepage&q&f=false (стр. 31)

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
hostName = #ip here
Port = 9999
s.connect((hostName, Port))
s.setsockopt(socket.IPPROTO_IP, IN.IP_MTU_DISCOVER, IN.IP_PMTUDISC_DO)
try:
    s.send('#' * 1473)
except socket.error:
    print 'The message did not make it'
    option = getattr(IN, 'IP_MTU', 14)
    print 'MTU:', s.getsockopt(socket.IPPROTO_IP, option)
else:
    print 'The big message was sent! Your network supports really big packets!'
person hillel_guy    schedule 23.12.2012
comment
Да, это сработало, но правильно ли использовать подключение по протоколу udp? - person Rahul Katare; 24.12.2012
comment
@RahulKatare: Да, это так: чтобы получить начальную оценку MTU пути, подключите сокет дейтаграммы к адресу назначения, используя connect (2), и получите MTU, вызвав getockopt (2) с параметром IP_MTU. - person Matt Joiner; 19.06.2013
comment
Что такое IN? import IN не работает - гуглить IN непросто. - person Isaac Turner; 09.11.2017
comment
Ah - IN определяет сетевые константы конкретной платформы. Он был удален из Python 3.6 python.readthedocs. .io/en/latest/whatsnew/ - person Isaac Turner; 09.11.2017

Существует github-gist, обеспечивающий эту функциональность:

import re
import socket
import struct
import logging
import subprocess
from fcntl import ioctl

SIOCGIFMTU = 0x8921
SIOCSIFMTU = 0x8922

log = logging.getLogger(__name__)

def get_mtu_for_address(ip):
    routeinfo = subprocess.check_output(['ip', 'route', 'get', ip])
    dev = re.search('.*dev (\w+) .*', routeinfo).groups()[0]
    mtuinfo = subprocess.check_output(['ip', 'link', 'show', dev])
    mtu = re.search('.*mtu ([0-9]+) .*', mtuinfo).groups()[0]
    return int(mtu)

class Iface:
    def __init__(self, ifname):
        self.ifname = ifname

    def get_mtu(self):
        '''Use socket ioctl call to get MTU size'''
        s = socket.socket(type=socket.SOCK_DGRAM)
        ifr = self.ifname + '\x00'*(32-len(self.ifname))
        try:
            ifs = ioctl(s, SIOCGIFMTU, ifr)
            mtu = struct.unpack('<H',ifs[16:18])[0]
        except Exception, s:
            log.critical('socket ioctl call failed: {0}'.format(s))
            raise

        log.debug('get_mtu: mtu of {0} = {1}'.format(self.ifname, mtu))
        self.mtu = mtu
        return mtu

    def set_mtu(self, mtu):
        '''Use socket ioctl call to set MTU size'''
        s = socket.socket(type=socket.SOCK_DGRAM)
        ifr = struct.pack('<16sH', self.ifname, mtu) + '\x00'*14
        try:
            ifs = ioctl(s, SIOCSIFMTU, ifr)
            self.mtu = struct.unpack('<H',ifs[16:18])[0]
        except Exception, s:
            log.critical('socket ioctl call failed: {0}'.format(s))
            raise

        log.debug('set_mtu: mtu of {0} = {1}'.format(self.ifname, self.mtu))

        return self.mtu


if __name__ == "__main__":
    import sys
    logging.basicConfig()

    mtu = None
    if len(sys.argv) > 2:
        dev,mtu = sys.argv[1:]
    elif len(sys.argv) > 1:
        dev = sys.argv[1]
    else:
        dev = 'eth0'

    iface = Iface(dev)
    if mtu is not None:
        iface.set_mtu(int(mtu))

    print dev,'mtu =',iface.get_mtu()

Источник: https://gist.github.com/nzjrs/8934855

person Humoyun Ahmad    schedule 27.12.2016
comment
У меня не работает в Python 3.7. Вызов ioctl в get_mtu вызывает: OSError: [Errno 6] Device not configured - person Damon Maria; 15.04.2021

Принятый ответ не работал у меня в Python 3.7. Я получаю: OSError: [Errno 6] Device not configured

Но теперь в psutil это встроено.

import psutil
print(psutil.net_if_stats())

Результат:

{
  'lo0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=16384), 
  'en0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=1500), 
  ...
}
person Damon Maria    schedule 14.04.2021