Это, вероятно, один из самых длинных сообщений, которые я написал в Stack Overflow. Я изучал OpenFlow, SDN и Ryu и хотел бы задокументировать мои знания для новичков. Пожалуйста, исправьте/отредактируйте мое сообщение, если это необходимо.
В этом кратком руководстве предполагается, что вы уже знаете компьютерные сети и основные сетевые протоколы. Это руководство поможет вам начать работу с OpenFlow при настройке системы.
1. Что такое OpenFlow и SDN?
Просьба ознакомиться с OpenFlow - Open Networking Foundation.
Дополнительная информация: The Future of Networking, and the Past of Protocols by Scott Shenker and Software-defined Networking, IEEE INFOCOM 2009.
Перед тем, как начать:
слой Инфраструктура включает в себя маршрутизаторы и коммутаторы внутри ядра сети.
Контрольный уровень включает в себя ПК, который управляет контроллером OpenFlow вместе с самим контроллером.
Уровень приложения включает приложения, которые работают поверх этого контроллера. В Ryu эти приложения написаны на Python.
OpenFlow - это протокол, с помощью которого взаимодействуют интерфейс Infrastructure и Control. OpenFlow не предоставляет API сам по себе. Это протокол с открытым исходным кодом, который используется поставщиками, которые разрабатывают ключи, совместимые с OpenFlow, и разработчиками, которые пишут контроллеры, например Ryu. API предоставляется контроллером.
2. Настройка контроллера Ryu OpenFlow на Debian 8
Предпосылки
Вам необходим доступ в Интернет. Если вы работаете в Debian внутри виртуальной машины, выполните следующую команду, чтобы автоматически настроить интерфейс Ethernet через NAT:
su
dhclient eth0
Enable Sudo
Debian не приходит с Судом по умолчанию. Некоторые приложения Ryu, которые вы будете использовать позже, потребуют sudo. Вы можете установить Sudo и добавить себя в список sudo'ers следующим образом:
su
apt-get install sudo # you might need to do apt-get update first!
nano /etc/sudoers
Найдите строку, в которой% Sudo ALL = (ALL: ALL) ALL и добавить запись непосредственно под ним:
yourusername ALL=(ALL:ALL) ALL
Нажмите CTRL + X, а затем нажмите Y, чтобы сохранить изменения в файле sudoers.Теперь вы можете выйти из системы, как корень, чтобы вернуться к вашей собственной оболочки
exit
Enable Оптимальное разрешение экрана (VM Only)
Если вы работаете в Debian в Virtual Box, установка по умолчанию не позволяет полный экран поддержка разрешения Virtual Box. Вам понадобится более крупный экран позже в разделе 3. Это хорошая идея, чтобы включить его сейчас.
В окне виртуальной машины выберите Устройства> Вставить Гость дополнения CD Image ...
Затем перейдите в каталог, содержащий файлы
cd /media/cdrom
Debian не позволит вам запустить сценарий из-за на вопросы разрешения. Скопируйте файлы в свой домашний каталог, изменение прав доступа, а затем запустить его:
mkdir ~/VBOXGUEST
cp * ~/VBOXGUEST
cd ~/VBOXGUEST
chmod 755 *
sudo ./VBoxLinuxAdditions.run
Reboot
sudo shutdown -r now
Установка Git
sudo apt-get install git
Установите Mininet
Мин. inet позволяет виртуально эмулировать различные сетевые интерфейсы на вашем ноутбуке/ПК. Установите его с помощью Git:
cd ~ # if you are in some other directory
git clone git://github.com/mininet/mininet
cd mininet
git tag # this will list available versions
git checkout -b 2.2.1 2.2.1 # replace 2.2.1 with the version you wish to install
cd ..
mininet/util/install.sh -a # default installation, includes all components, recommended
Я рекомендую установить рассеиватель Wireshark OpenFlow. Вы можете позже установить Wireshark для анализа пакетов. OpenFlow Wireshark Dissector помогает Wireshark извлекать как можно больше информации из пакетов OpenFlow.
mininet/util/install.sh -h
Выполните следующую команду, чтобы проверить правильность установки mininet:
sudo mn --test pingall
Установка Ryu OpenFlow контроллер
OpenFlow контроллер взаимодействует между уровнем управления и уровнем инфраструктуры с использованием протокола OpenFlow , Кроме того, это контроллер, который предоставляет API для разработки приложений SDN, работающих на уровне приложений (поверх уровня управления). Существует множество контроллеров OpenFlow. Контроллер Ryu OpenFlow - это тот, который использует скрипты Python в качестве своих приложений. Опять же, установите его с помощью Git:
cd ~
git clone git://github.com/osrg/ryu.git
Установите Wireshark
sudo apt-get install wireshark
Установите вспомогательные модули Python
Debian 8.3 приходит как с Python 2.7 и 3.4, установленной по умолчанию. Однако вам необходимо установить некоторые модули Python, которые используют приложения Ryu (скрипты Python).Вы можете установить модули Python с использованием пипа:
cd ~/ryu
sudo apt-get install python-dev python-pip python-setuptools
sudo pip install .
выше будет автоматически запустить setup.py находятся в этой директории и принести недостающие модули Python из индекса пакетов Python. Сценарий автоматически установит все соответствующие модули. Однако, выполнить следующие действия, чтобы убедиться, что вы не пропуская ни одного модуля позже:
sudo pip install webob
sudo pip install eventlet
sudo pip install paramiko
sudo pip install routes
Запуск
Start mininet эмулировать 3 хостов и переключатель с помощью следующей команды:
sudo mn --topo single,3 --mac --switch ovsk --controller remote
Вы увидите приглашение на мини-станцию. Это приглашение можно использовать для ping-хостов, отправки пакетов между ними и т. Д.
Откройте еще одно окно терминала, чтобы запустить Ryu. В этом примере мы запустим приложение (simple_switch_13.py), которое будет эмулировать простой переключатель уровня 2, который пересылает все принятые пакеты всем портам, кроме тех, которые были приняты.
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
Убедитесь, что вы находитесь в своем домашнем каталоге при запуске.
Вы все настроены. Чтобы выполнить ping-хосты и проанализировать передачу пакетов, перейдите к следующему разделу.
3. Экспериментирование с Wireshark и ТСРйитр
В этом разделе мы будем стрелять пакеты от одного узла к другому с помощью mininet и анализа полученных передач с использованием ТСРйитр и Wireshark.
Способ передачи пакетов - это именно то, что мы можем контролировать в Software Defined Networking. Мы делаем это, создавая различные приложения, которые работают поверх контроллера. Эти приложения образуют прикладной уровень плоскости управления SDN.
Настройка топологии и запустить контролирующее приложение
Примечание: В предыдущем разделе вы создали топологию с mininet и начал приложение Ryu для управления коробкой передач. В случае, если вы перезагружается, или вышел из любой из них, повторяю команды для создания топологии и запустить приложение Рю здесь:
cd ~
sudo mn --topo single,3 --mac --switch ovsk --controller remote
и в отдельном окне терминала:
cd ~/ryu
PYTHONPATH=. ./bin/ryu-manager ryu/app/simple_switch_13.py
Play с пакеты
в mininet строке, выполните следующие действия, чтобы открыть окно консоли для каждого из трех хостов в топологии вы создали:
mininet> xterm h1 h2 h3
Уложите эти консоли, чтобы вы могли видеть их все одновременно!Тогда в xterms для h2 и h3, запустите ТСРйитр, утилита для печати пакетов замеченного хоста:
tcpdump -XX -n -i h2-eth0
tcpdump -XX -n -i h3-eth0
Примечания: Если вы использовали Wireshark ранее, это захват пакетов на интерфейсе eth0 этих два хостов соответственно.
При создании топологии mininet назначены следующие IP-адреса трех хостов:
h1: 10.0.0.1
h2: 10.0.0.2
h3: 10.0.0.3
с узла 1 в оболочке, пинг хоста 2 и устройство 3 и наблюдать эффект на двух других консолях после каждой команды:
ping 10.0.0.2
ping 10.0.0.3
Проверьте доступность недостижимый (не существующий хост), и увидеть эффект на консолях:
ping 10.0.0.7
Вы должны были наблюдать протоколы ICMP (ping) и ARP (которые имеют этот IP-адрес) в этом разделе! Вы также можете сделать это, используя Wireshark вместо tcpdump. Это графическая альтернатива tcpdump.
Примечание: способ пересылки пакетов ALL зависит от приложения, выполняющегося поверх Ryu. Вы можете написать приложение, чтобы удалить все пакеты. В этом случае ваши пинги не повлияют на другие две консоли.
4. Понимание базового уровня 2 коммутатора приложения
В этом разделе мы анализируем работу упрощенной версии приложения коммутатора 2-го уровня, которые контролировали передачи пакетов в разделе 3.
Работа моста обучения (или коммутатора уровня 2)
Я упоминал ранее, что, если вы читаете это руководство, я предполагаю, что вы уже знаете основные сетевые протоколы (включая работу переключателя уровня 2, или учебный мост, или коммутатор Ethernet!) Я опишу его в нескольких строках ниже независимо.
Мост «обучения» хранит базу данных хостов, к которой он подключен, к его портам. Хосты идентифицируются MAC-адресом своей сетевой карты, которая выглядит следующим образом: ab:cd:ef:12:34:56
(это в шестнадцатеричной форме). Порты идентифицируются просто по их числу. Например, коммутатор с 4 портами имеет порты 1, 2, 3 и 4.
Если коммутатор получает пакет на своем порту 2, он будет искать MAC-адрес получателя (которому он предназначен) этого пакет. Затем он заглядывает в свою базу данных, чтобы узнать, знает ли он, к какому порту подключен этот узел. Если он обнаружит это, он пересылает этот пакет ТОЛЬКО к этому конкретному порту. Но если он еще не имеет записи в своей базе данных, он наводняет этот пакет для ВСЕХ портов, и хосты могут проверить сами, если пакет был предназначен для них.
В то же время коммутатор просматривает источник MAC-адрес этого пакета, и он сразу же знает, что хост X находится в порту 2. Он хранит эту запись в этой базе данных. Итак, теперь вы знаете, что, если хост-получатель отвечает на исходный хост, коммутатору не нужно заливать ответный пакет!
Введение в код Ryu API Python
Вместо того, чтобы идти непосредственно к simple_switch_13.py, давайте выберем очень простую программу, которая не имеет «обучение» потенциал. Пока нет базы данных пересылки. Ниже программа является простой слой 2 переключатель, который передает принятый пакет ко всем портам (заливает пакет):
from ryu.base import app_manager
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER
from ryu.controller.handler import set_ev_cls
class L2Switch(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
@set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
def packet_in_handler(self, ev):
msg = ev.msg
dp = msg.datapath
ofp = dp.ofproto
ofp_parser = dp.ofproto_parser
actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
out = ofp_parser.OFPPacketOut(
datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
actions=actions)
dp.send_msg(out)
Импорт
Я не буду углубляться в операторы импорта еще. Мы будем обсуждать импорт отдельно, анализируя код, который их использует.
Основное применение скелет
Следующий код является совершенно полное применение Рю. На самом деле вы тоже можете его выполнить! Он ничего не будет делать, хотя:
from ryu.base import app_manager
class L2Switch(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(L2Switch, self).__init__(*args, **kwargs)
В качестве аргумента в классе, мы переходим ryu.base.app_manager.RyuApp
импорта (импортированный в первой строке). Из справочника Ryu API app_manager
класс является центральным управлением приложениями Ryu. Он загружает приложения Ryu, предоставляет им контексты и маршрутизирует сообщения между приложениями Ryu.
EventOFPPacketIn Событие
Новый метод packet_in_handler
добавляется L2Switch
класса. Это называется, когда Ryu получает сообщение OpenFlow packet_in
. Когда Ryu получает сообщение packet_in
, возникает событие ofp_event.EventOFPPacketIn
. Декоратор set_ev_cls
рассказывает Рю, когда нужно вызвать связанную функцию, packet_in_handler
.
Первый аргумент декоратора set_ev_cls
указывает событие, которое вызывает функцию. Как вы ожидаете, каждый раз, когда возникает событие ofp_event.EventOFPPacketIn
, эта функция вызывается.
Второй аргумент указывает состояние переключателя, если вы хотите разрешить Ryu обрабатывать событие. Возможно, вы хотите игнорировать сообщения OpenFlow packet_in
до того, как рукопожатие между Ryu и коммутатором закончится. Использование MAIN_DISPATCHER
в качестве второго аргумента означает, что эта функция вызывается только после завершения согласования. MAIN_DISPATCHER
обозначает нормальное состояние переключателя. На этапе инициализации переключатель находится в состоянии HANDSHAKE_DISPATCHER
!
Теперь давайте посмотрим на тело функции. Мы разделим его на две части.
msg = ev.msg
dp = msg.datapath
ofp = dp.ofproto
ofp_parser = dp.ofproto_parser
ev.msg
- это структура данных, которая содержит полученный пакет.
msg.dp
- это объект внутри этой структуры данных, который представляет собой datapath (switch).
dp.ofproto
и dp.ofproto_parser
- это объекты, представляющие протокол OpenFlow, которые согласовали Ryu и переключатель.
actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]
out = ofp_parser.OFPPacketOut(
datapath=dp, buffer_id=msg.buffer_id, in_port=msg.in_port,
actions=actions)
dp.send_msg(out)
OFPActionOutput
класса используется с packet_out
сообщения указать порт коммутатора, который вы хотите отправить пакет из. Поскольку в этом упрощенном приложении нет базы данных пересылки, мы накладываем пакет на все порты, поэтому используется константа OFPP_FLOOD
.
OFPPacketOut
класс используется для создания сообщения packet_out
.
С помощью метода класса send_msg
вы можете отправить объект сообщения OpenFlow в порты, определенные в переменной действий. Повторяю, в этом случае действия создаются так, что пункт назначения включает ВСЕ порты.
События
Вы неоднократно видели термин событие в приведенном выше коде. В событии ориентированного программирования, поток программы управляются событиями, которые поднятые сообщениями, полученных система (например, EventOFPPacketIn
поднимается, когда packet_in
сообщения получен от Рит из (включено OpenFlow) переключатель). Ранее мы обсуждали, что OpenFlow - это протокол, использующий контроллер (Ryu, PC) и инфраструктуру (или коммутатор). Такие сообщения, какpacket_in
- это именно то, что общение между ними выглядит так, как использование протокола OpenFlow!
Следующие шаги
Вы могли бы хотеть идти вперед и строить свои собственные приложения Рю. Изучение API-интерфейса Ryu (или языка Python, если вы еще не знакомы с ним), может быть хорошим началом. Удачи!