FastNetMon

Thursday 30 April 2015

How to sniff interface on remote machine with Wireshark from Mac OS?

Execute following commands on Mac OSX console.

Create fifo:
mkfifo /tmp/remote
Run wireshark:
wireshark -k -i /tmp/remote
And run tcpdump to this fifo over ssh:
ssh root@10.0.xxx.xxx  "tcpdump -s 0 -U -n -w - -i eth1 -S" > /tmp/remote
Works nice!

Source: http://serverfault.com/questions/362529/how-can-i-sniff-the-traffic-of-remote-machine-with-wireshark

Wednesday 29 April 2015

How to code for DPDK with C++

Hello!

If you want to code for DPDK with C++ you need some beer and half of day for digging into DPDK maillist.

Or you could use my manual and do it in seconds!

Lets' go! First of all, please download and build DPDK 2.0.0 into folder /usr/src/dpdk2.0.0

After this, please download files https://www.dropbox.com/s/hy3eisssxn2cp1f/rte.compile-pre.mk?dl=0 and https://www.dropbox.com/s/u2bkcfl35yejwx4/rte.vars.mk?dl=0 and replace files /usr/src/dpdk-2.0.0/mk/toolchain/gcc/rte.vars.mk and /usr/src/dpdk-2.0.0/mk/internal/rte.compile-pre.mk accordingly.

After this you should fix you project Makefile and rename main.c to main.cpp.

I could provide example file for you%
ifeq ($(RTE_SDK),)
$(error "Please define RTE_SDK environment variable")
endif

# http://patchwork.dpdk.org/ml/archives/dev/2014-January/001127.html
CC=g++

# Default target, can be overriden by command line or environment
RTE_TARGET ?= x86_64-native-linuxapp-gcc

include $(RTE_SDK)/mk/rte.vars.mk

# binary name
APP = example

# all source are stored in SRCS-y
SRCS-y := main.cpp


CXXFLAGS += -std=gnu++11
CFLAGS += -O3
CFLAGS += -Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable
LDFLAGS += -lstdc++

include $(RTE_SDK)/mk/rte.extapp.mk
My huge thanks to author of this patches http://patchwork.dpdk.org/ml/archives/dev/2014-January/001127.html :)

Sunday 26 April 2015

Поддержка BGP силами ExaBGP добавлена в тулкит для выявления DDoS атак FastNetMon

Прошу к официальной документации на GitHub :) Теперь можно обойтись без кривых скриптов и анонсировать атакуемый хост прямо силами BGP.

How to control ExaBGP from external tool?

Please setup ExaBGP and Quagga before this manual: http://www.stableit.ru/2015/04/quagga-bgp-and-exabgp-work-together-for.html

Let's create fake process which work as proxy for relying data from Linux PIPE to ExaBGP:

vim /etc/exabgp/exabgp_pipe_provider.sh
With this contents:
#!/bin/sh

FIFO="/var/run/exabgp.cmd"
#trap "rm -f $FIFO" SIGINT

rm -f $FIFO
mkfifo $FIFO
tail -f $FIFO
Set exec flag:

chmod +x /etc/exabgp/exabgp_pipe_provider.sh
And add following (process service-dynamic ....) to ExaBGP config: /etc/exabgp_blackhole.conf
group Core_v4 {
    hold-time 180;
    local-as 65001;
    peer-as 1234;
    router-id 10.0.3.114;
    graceful-restart 1200;

    static {
        route 10.10.10.1/32 next-hop 10.0.3.114 community 65001:666;
    }  

    neighbor 10.0.3.115 {
        local-address 10.0.3.114;
        description "Quagga";
    }  

    # Add this line for process management
    process service-dynamic {
        run /etc/exabgp/exabgp_pipe_provider.sh;
    }  
}
And run ExaBGP!

After this we could see multiple processes in process list:
ps aux|grep exa
root     36854  0.0  0.0  52764 14604 ?        S    11:47   0:00 /usr/bin/python /usr/local/bin/exabgp /etc/exabgp_blackhole.conf
root     36855  0.0  0.0   4328   868 ?        S    11:47   0:00 /bin/sh /etc/exabgp/exabgp_pipe_provider.sh
root     36858  0.0  0.0   5800  1324 ?        S    11:47   0:00 tail -f /var/run/exabgp.cmd
We are ready!

Let's add announce:

echo "announce route 10.10.10.123/32 next-hop 10.0.3.114 community 65001:666" > /var/run/exabgp.cmd
If you want to disable it please use this syntax:

echo "withdraw route 10.10.10.123/32" > /var/run/exabgp.cmd
After announce route we could see on Quagga side new prefix:
*> 10.10.10.123/32  10.0.3.114                             0 65001 i
Source: https://github.com/Exa-Networks/exabgp/wiki/Controlling-ExaBGP-:-using-a-named-PIPE

Saturday 25 April 2015

Quagga BGP and exabgp: work together for BGP blackhole implementation

In our test case we will deploy two machines: 10.0.3.114 for exabgp (it announce /32 prefix for blackholing on core router side) and 10.0.3.115 (it emulates core router). We will do this work on Debian 8 Jessie.

Install exabgp:
pip install exabgp

Create ExaBGP configuration:
vim /etc/exabgp_blackhole.conf
Here you can find example for exabgp configuration:
group Core_v4 {
    hold-time 180;
    local-as 65001;
    peer-as 1234;
    router-id 10.0.3.114;
    graceful-restart 1200;

    static {
        route 10.10.10.1/32 next-hop 10.0.3.114 community 65001:666;
    }  

    neighbor 10.0.3.115 {
        local-address 10.0.3.114;
        description "Quagga";
    }  
}
We specify current machine IP as next hop because without it Quagga ignores it: 10.0.3.114 rcvd UPDATE about 10.10.10.1/32 -- DENIED due to: martian next-hop;

Start exabgp:
env exabgp.daemon.user=root exabgp.daemon.daemonize=true exabgp.daemon.pid=/var/run/exabgp.pid exabgp.log.destination=/var/log/exabgp.log exabgp /etc/exabgp_blackhole.conf
I recommend you to open log file and look at it:
tail -f /var/log/exabgp.log exabgp 
Now we will install Quagga.

Install package:
apt-get install -y quagga
Enable BGP daemon in Quagga:
vim /etc/quagga/daemons
And change following lines:
zebra=yes
bgpd=yes
Then you should create config files and fix permissions for they:
touch /etc/quagga/zebra.conf
touch /etc/quagga/bgpd.conf
touch /etc/quagga/quagga.conf
chown quagga:quagga /etc/quagga/bgpd.conf
chown quagga:quagga /etc/quagga/zebra.conf
chown quagga:quagga /etc/quagga/quagga.conf
Create BGP configuration:
vi /etc/quagga/bgpd.conf
Example for configuration (please be aware! It's not suitable for production):
hostname SoftBGP
password zebra987
enable password zebra987
log file /var/log/quagga/bgpd.log

debug bgp events
debug bgp filters
debug bgp fsm
debug bgp keepalives
debug bgp updates

router bgp 1234
bgp router-id 10.0.3.115
bgp log-neighbor-changes

neighbor 10.0.3.114 remote-as 65001
Apply configuration:
/etc/init.d/quagga restart
 Wow! We see this announce in Quagga:
/usr/bin/vtysh -d bgpd -c "show ip bgp summary"
BGP router identifier 10.0.3.115, local AS number 1234
RIB entries 1, using 112 bytes of memory
Peers 1, using 4568 bytes of memory

Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.0.3.114      4 65001      12      18        0    0    0 00:01:12        1

Total number of neighbors 1

Check announced subnets from exabgp:
/usr/bin/vtysh -d bgpd -c "show ip bgp"
BGP table version is 0, local router ID is 10.0.3.115
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
              i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete

   Network          Next Hop            Metric LocPrf Weight Path
*> 10.10.10.1/32    10.0.3.114                             0 65001 i

Total number of prefixes 1

This guide builded from more detailed and complex: https://www.m00nie.com/2014/01/bgp-rtbh-setup-using-exabgp/

Friday 24 April 2015

Активация SSH для root на DragonflyBSD

Открываем логин по паролю руту:
vi /etc/ssh//sshd_config
Правим:
PermitRootLogin yes
PasswordAuthentication yes
Включаем автозапуск:
vi /etc/rc.conf
Вуаля:
sshd_enable="YES"
/etc/rc.d/sshd restart

Thursday 23 April 2015

Сжатие результатов захвата трафика tcpdump в потоковом режиме

Есть два подхода к данной задаче - использовать потоковое сжатие в один файл либо использовать встроенную функцию ротации и ротировать файлы по достижении определенного объема.

Начнем с потокового сжатия:
screen
tcpdump -i venet0 -n -w - | bzip2 -c > /root/tcpdump_23apr.pcap.bz2
ctrl+a d

Как остановить сбор:
killall tcpdump

НЕЛЬЗЯ останавливать сбор данных по CTRL+C, это побьет архив!

Читаем собранный файл:
bzcat /root/tcpdump_23apr.pcap.bz2 | tcpdump -n -r -

На мой взгляд более предпочтительна ротация силами tcpdump (ротируем как только дойдет до 100 мб файл):
screen
mkdir /root/whole_server_dump
tcpdump -i venet0 -n -w /root/whole_server_dump/pcap_dump -C 100 -z bzip2
На CentOS же может понадобиться указать флаг -z root, чтобы не было понижения прав, которое приведет к ошибке записи в файл:
 tcpdump -i eth0 -n -w /root/whole_server_dump/pcap_dump -C 100 -z bzip2 -Z root

В итоге через некоторое время в текущей папке будут созданы вот такие файлы:
-rw-r--r--  1 root root  28M Apr 23 11:31 pcap_dump1.bz2
-rw-r--r--  1 root root  24M Apr 23 11:32 pcap_dump2.bz2
-rw-r--r--  1 root root  23M Apr 23 11:32 pcap_dump3.bz2
-rw-r--r--  1 root root  71M Apr 23 11:33 pcap_dump4
-rw-r--r--  1 root root  39M Apr 23 11:31 pcap_dump.bz2
Также вместо bzip2 можно попробовать использовать lzma, который потенциально может сжимать лучше, но в конкретно моем случае процессор не успевал сжимать файлы с приемлемой скоростью.


Итак, стандартный bzip2 выдал мне сжатие в 4 раза ровно, попробуем включить его самый жесткий режим.
vim /usr/bin/bzip2_best
#!/bin/bash
/bin/bzip2 -9 "$@"
chmod +x /usr/bin/bzip2_best
После этого указываем этот скрипт как аргумент для -z. Но в моем случае это не дало никакого особого толку - сила сжатия не увеличилась.

Wednesday 22 April 2015

DPDK: LPM memory allocation failed

Имеется ошибка от при запуске l3fwd:
PMD: eth_ixgbe_dev_init(): port 3 vendorID=0x8086 deviceID=0x10fb
Initializing port 0 ... Creating queues: nb_rxq=3 nb_txq=2...  Address:90:E2:BA:4A:D8:DC, Allocated mbuf pool on socket 0
LPM: Adding route 0x01010100 / 24 (0)
LPM: Adding route 0x02010100 / 24 (1)
LPM: Adding route 0x03010100 / 24 (2)
LPM: Adding route 0x04010100 / 24 (3)
LPM: LPM memory allocation failed
EAL: Error - exiting with code: 1
  Cause: Unable to create the l3fwd LPM table on socket 0

Для фикса заменяем:
echo 64 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
На:
echo 512 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
И запускаем приложение заново.

Такое происходит потому что LPM хочет много памяти (1200 MB), а мы выделяем 128MB! :)

Tuesday 21 April 2015

How to enable GeoIP support in tshark / Wireshark console

First of all you need install GeoIP databases.

On Debian system you could do it with apt-get:
apt-get install -y geoip-database
Then you should specify folder with GeoIP databases to Wireshark:
mkdir -p ~/.wireshark
echo '"/usr/share/GeoIP"' > ~/.wireshark/geoip_db_paths
Finally, you could call tshark with enable GeoIP lookup mode:
tshark -n -i venet0 -V  -o "ip.use_geoip: TRUE" -c 1
As result you will get following screen:
   Source: xx.xx.xx.xx (xx.xx.xx.xx)    Destination: xx.xx.xx.xx (xx.xx.xx.xx)    [Source GeoIP: Germany]        [Source GeoIP Country: Germany]    [Destination GeoIP: Germany]        [Destination GeoIP Country: Germany] 
If you want use this ability in console scripts I recommend following approach:
tshark -n -i venet0 -V  -o "ip.use_geoip: TRUE" -T fields -e ip.dst -e ip.geoip.dst_country 
It will provide something like this:
117.169.1.130 China117.169.1.130 China117.169.1.130 China117.169.1.130 China117.169.1.130 China117.169.1.130 China117.169.1.130 China 
Definitely  you could use geoip in filters too:

tshark -n -i venet0  -o "ip.use_geoip: TRUE" -R "ip.geoip.country==China"

Monday 20 April 2015

How to measure DPDK application performance?

Really brilliant idea! Found it here: http://www.net.in.tum.de/fileadmin/bibtex/publications/papers/MoonGen_draft2.pdf

Quote:

Measuring the CPU load caused by a DPDK-based application is difficult because DPDK recommends a busy-wait loop, i.e. the CPU load is always 100% for a typical application. MoonGen and other DPDKbased generators like Pktgen-DPDK are no exception to this. The bottleneck for packet transmission is usually not the CPU but the line rate of the network, so just measuring the achieved rate provides no insight. We therefore decrease the clock frequency of our CPU such that the processing power becomes the bottleneck. The performance can then be quantified as CPU cycles per packet. The same approach was used by Rizzo to evaluate the performance of netmap.


Использование DPDK на Debian 8 Jessie вместе с драйвером ixgbe (Intel 82599)

Использование DPDK на Debian 8 Jessie вместе с драйвером ixgbe (Intel 82599).

Собираем:
cd /usr/src
wget http://dpdk.org/browse/dpdk/snapshot/dpdk-16.04.tar.gz
tar -xf dpdk-16.04.tar.gz
cd dpdk-16.04/
make config T=x86_64-native-linuxapp-gcc
make
Загружаем uio:
modprobe uio_pci_generic

Проверяем, какие сетевые мы видим:
tools/dpdk_nic_bind.py --status
tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
<none>
Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection' if=eth0 drv=igb unused=uio_pci_generic *Active*
0000:02:00.1 'I350 Gigabit Network Connection' if=eth1 drv=igb unused=uio_pci_generic
0000:02:00.2 'I350 Gigabit Network Connection' if=eth2 drv=igb unused=uio_pci_generic
0000:02:00.3 'I350 Gigabit Network Connection' if=eth3 drv=igb unused=uio_pci_generic
0000:0a:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth4 drv=ixgbe unused=uio_pci_generic
0000:0a:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth5 drv=ixgbe unused=uio_pci_generic
0000:0d:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth6 drv=ixgbe unused=uio_pci_generic
0000:0d:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth7 drv=ixgbe unused=uio_pci_generic 

Отключаем сетевые (в моем случае eth4/eth6), с которыми будем работать от драйвера из Linux ядра для работы с DPDK:

./tools/dpdk_nic_bind.py --bind=uio_pci_generic  0a:00.0
./tools/dpdk_nic_bind.py --bind=uio_pci_generic 0d:00.0

Убеждаемся, что все подцепилось:
tools/dpdk_nic_bind.py --status
Network devices using DPDK-compatible driver
============================================
0000:0a:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=
0000:0d:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=uio_pci_generic unused=
Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection' if=eth0 drv=igb unused=uio_pci_generic *Active*
0000:02:00.1 'I350 Gigabit Network Connection' if=eth1 drv=igb unused=uio_pci_generic
0000:02:00.2 'I350 Gigabit Network Connection' if=eth2 drv=igb unused=uio_pci_generic
0000:02:00.3 'I350 Gigabit Network Connection' if=eth3 drv=igb unused=uio_pci_generic
0000:0a:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth5 drv=ixgbe unused=uio_pci_generic
0000:0d:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' if=eth7 drv=ixgbe unused=uio_pci_generic
Other network devices
=====================
<none>

Теперь нужно настроить HugeTLB, смотрим, в какие точки оно у нас смонтировано:
cat /proc/mounts |grep tlb

И размонтируем!

После этого монтируем вновь:
mkdir -p /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
echo 64 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
Собираем пример форвардера:

cd examples
apt-get install -y libvirt-dev
export RTE_TARGET=x86_64-native-linuxapp-gcc
export RTE_SDK=/usr/src/dpdk-16.04
make
Если получаем ошибку "/usr/src/dpdk-16.04/mk/internal/rte.extvars.mk:57: *** Cannot find .config in /usr/src/dpdk-16.04/x86_64-native-linuxapp-gcc.  Останов.", то нужно внести фикс:

В файле:
vim /usr/src/dpdk-16.04/mk/internal/rte.extvars.mk

Фиксим:
-RTE_SDK_BIN := $(RTE_SDK)/$(RTE_TARGET)
+RTE_SDK_BIN := $(RTE_SDK)/build

Итак, у нас CPU E5-2407 0 @ 2.20GHz у него 3 канала памяти (-n 3) и 4 ядра (-l 0-3).

Запускаем (можно указать --pci-whitelist 0a:00.0 --pci-whitelist 0d:00.0 чтобы работать только с этими портами):
./l2fwd/l2fwd/x86_64-native-linuxapp-gcc/app/l2fwd -l 0-3 -n 3  -- -p 3

-p 3 - это битовая маска портов, с которыми мы работаем (3 = 11 в бинарной кодировке, оба порта).

Обращаю внимание, что на целевой стороне нужно включить promisc режим, ибо пакеты летят с левым MAC:
11:47:35.261390 90:e2:ba:4a:d8:e8 > 02:00:00:00:00:01, ethertype IPv4 (0x0800), length 60: 128.0.71.57.9926 > 10.20.20.100.80: UDP, length 18
11:47:35.261391 90:e2:ba:4a:d8:e8 > 02:00:00:00:00:01, ethertype IPv4 (0x0800), length 60: 128.0.71.56.14204 > 10.20.20.100.80: UDP, length 18
11:47:35.261392 90:e2:ba:4a:d8:e8 > 02:00:00:00:00:01, ethertype IPv4 (0x0800), length 60: 128.0.71.57.6523 > 10.20.20.100.80: UDP, length 18
11:47:35.261394 90:e2:ba:4a:d8:e8 > 02:00:00:00:00:01, ethertype IPv4 (0x0800), length 60: 128.0.71.56.51110 > 10.20.20.100.80: UDP, length 18
11:47:35.261394 90:e2:ba:4a:d8:e8 > 02:00:00:00:00:01, ethertype IPv4 (0x0800), length 60: 128.0.71.57.12424 > 10.20.20.100.80: UDP, length 18

Включаем режим прослушки вот так:
ifconfig eth1 promisc 

Итак, нагрузка:
33624 root      20   0  378800   3716   3356 R 200.0  0.0  30:04.50 l2fwd                                            
%Cpu(s): 50.0 us,  0.0 sy,  0.0 ni, 50.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st


Показания с PCM просто потрясающие - все операции идут через кэш процессора:
Time elapsed: 998 ms
Called sleep function for 1000 ms
---------------------------------------|
--             Socket 0              --|
---------------------------------------|
---------------------------------------|
---------------------------------------|
--   Memory Performance Monitoring   --|
---------------------------------------|
--  Mem Ch 0: Reads (MB/s):    0.26  --|
--            Writes(MB/s):   18.52  --|
--  Mem Ch 1: Reads (MB/s):    0.10  --|
--            Writes(MB/s):   17.11  --|
-- NODE0 Mem Read (MB/s):      0.36  --|
-- NODE0 Mem Write (MB/s) :   35.64  --|
-- NODE0 P. Write (T/s) :      3107  --|
-- NODE0 Memory (MB/s):    36.00     --|
---------------------------------------||---------------------------------------
--                   System Read Throughput(MB/s):      0.36                  --
--                  System Write Throughput(MB/s):     35.64                  --
--                 System Memory Throughput(MB/s):     36.00                  --
---------------------------------------||---------------------------------------

В случае netmap цифры ужасающие:
---------------------------------------|
--             Socket 0              --|
---------------------------------------|
---------------------------------------|
---------------------------------------|
--   Memory Performance Monitoring   --|
---------------------------------------|
--  Mem Ch 0: Reads (MB/s): 1162.53  --|
--            Writes(MB/s):  726.09  --|
--  Mem Ch 1: Reads (MB/s):    0.01  --|
--            Writes(MB/s):    0.00  --|
-- NODE0 Mem Read (MB/s):   1162.53  --|
-- NODE0 Mem Write (MB/s) :  726.09  --|
-- NODE0 P. Write (T/s) :      3575  --|
-- NODE0 Memory (MB/s):  1888.63     --|
---------------------------------------||---------------------------------------
--                   System Read Throughput(MB/s):   1162.53                  --
--                  System Write Throughput(MB/s):    726.09                  --
--                 System Memory Throughput(MB/s):   1888.63                  --
---------------------------------------||---------------------------------------

Запуск тест testpmd:
./x86_64-native-linuxapp-gcc/build/app/test-pmd/testpmd -l 0-3 -n 3  -- --interactive --total-num-mbufs=2048
Вот огромный гайд по тулзе testpmd: http://www.intel.com/content/dam/www/public/us/en/documents/guides/intel-dpdk-testpmd-application-user-guide.pdf

Генерация до 14.6 MPPS на одном логическом ядре силами MoonGen и DPDK

Итак, для начала Вам нужно собрать и установить DPDK: 2.0.0 версии или старше.

Вытягиваем код и стаскиваем зависимости (LuaJIT):
cd /usr/src
git clone https://github.com/emmericp/MoonGen.git
cd MoonGen/
# Update dependencies
git submodule update --init
Указываем путь к свеже установленному DPDK:
export RTE_TARGET=x86_64-native-linuxapp-gcc
export RTE_SDK=/usr/src/dpdk-16.04
Собираем:
./build.sh
Смотрим номера портов (этот блок выдается при запуске MoonGen без параметров):
Found 7 usable ports:
   Ports 0: D8:9D:67:64:4A:71 (unknown NIC (PCI ID 8086:1521))
   Ports 1: D8:9D:67:64:4A:72 (unknown NIC (PCI ID 8086:1521))
   Ports 2: D8:9D:67:64:4A:73 (unknown NIC (PCI ID 8086:1521))
   Ports 3: 90:E2:BA:4A:D8:DC (82599EB 10-Gigabit SFI/SFP+ Network Connection)
   Ports 4: 90:E2:BA:4A:D8:DD (82599EB 10-Gigabit SFI/SFP+ Network Connection)
   Ports 5: 90:E2:BA:4A:D8:E8 (82599EB 10-Gigabit SFI/SFP+ Network Connection)
   Ports 6: 90:E2:BA:4A:D8:E9 (82599EB 10-Gigabit SFI/SFP+ Network Connection)

Запускаем генерацию SYN флуда (5 - порт из списка выше, 10.0.0.1 - стартовый порт для генерации src, 10000 - скорость):
build/MoonGen examples/l3-tcp-syn-flood.lua 5 10.0.0.1 16000000 10000
В итоге после инициализации получаем отличный флуд:
[Device: id=0] Sent 845365678 packets, current rate 14.83 Mpps, 7594.27 MBit/s, 9967.48 MBit/s wire rate.
[Device: id=0] Sent 860193837 packets, current rate 14.83 Mpps, 7592.01 MBit/s, 9964.52 MBit/s wire rate.
[Device: id=0] Sent 875025963 packets, current rate 14.83 Mpps, 7594.04 MBit/s, 9967.17 MBit/s wire rate.
[Device: id=0] Sent 889854138 packets, current rate 14.83 Mpps, 7591.99 MBit/s, 9964.49 MBit/s wire rate.
[Device: id=0] Sent 904685096 packets, current rate 14.83 Mpps, 7593.43 MBit/s, 9966.37 MBit/s wire rate.
[Device: id=0] Sent 919514890 packets, current rate 14.83 Mpps, 7592.84 MBit/s, 9965.60 MBit/s wire rate.

[Device: id=0] Sent 934345896 packets, current rate 14.83 Mpps, 7593.42 MBit/s, 9966.37 MBit/s wire rate.
Со стороны получателя это выглядит вот так:
10.224.21.215.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc562 (correct), seq 1:21, win 10, length 2015:01:27.116876 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.223.153.106.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41d0 (correct), seq 1:21, win 10, length 2015:01:27.116877 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.224.21.216.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc561 (correct), seq 1:21, win 10, length 2015:01:27.116877 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.223.153.117.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41c5 (correct), seq 1:21, win 10, length 2015:01:27.116878 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.224.21.230.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc553 (correct), seq 1:21, win 10, length 2015:01:27.116878 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.223.153.122.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41c0 (correct), seq 1:21, win 10, length 2015:01:27.116879 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.224.21.233.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc550 (correct), seq 1:21, win 10, length 2015:01:27.116879 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.223.153.129.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41b9 (correct), seq 1:21, win 10, length 2015:01:27.116880 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.224.21.246.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc543 (correct), seq 1:21, win 10, length 2015:01:27.116880 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)   
10.223.153.142.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41ac (correct), seq 1:21, win 10, length 2015:01:27.116881 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.224.21.249.1025 > 192.168.1.1.1024: Flags [S], cksum 0xc540 (correct), seq 1:21, win 10, length 2015:01:27.116882 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto TCP (6), length 60)    
10.223.153.145.1025 > 192.168.1.1.1024: Flags [S], cksum 0x41a9 (correct), seq 1:21, win 10, length 20
Тесты проводились на железе  Intel(R) Core(TM) i7 CPU 950  @ 3.07GHz. На более слабом чипе Intel(R) Xeon(R) CPU E5-2407 0 @ 2.20GHz удалось достичь лишь 12.75 MPPS просто потому что чип медленный.

Content of /etc/rc.local for auto start:
echo 64 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
/usr/src/MoonGen/bind-interfaces.sh

Friday 17 April 2015

Сборка модуля netmap на Debian 7/8 с сетевой Intel 82599 с использование драйверов SourceForge

Если Вас устраивают обычные драйверы из дистрибутива, используйте вот эту инструкцию, она намного проще: http://www.stableit.ru/2015/03/netmap-ixgbe.html

Проект netmap не блещет понятной информацией, но я постараюсь упростить Вам немного жизнь.

Вам можно взять пропатченную мною версию драйвера, прошу, в спец репо (там лежит самая новая на 2е марта 2015го года версия драйвера ixgbe с Sourceforge): https://github.com/pavel-odintsov/ixgbe-linux-netmap  Эта версия отлично работает как с ядром 3.2 (Wheezy), так и с ядром 3.16 (Jessie).

Для работ нам нужно будет  установить довольно фундаментальных тулзы:
apt-get install -y make git gcc

Для начала создадим фейковую иерархию повторяющую структуру попок ядра Linux и положим в нее уже пропатченный драйвер ixgbe c Sourceforge:
cd /usr/src
git clone https://github.com/pavel-odintsov/ixgbe-linux-netmap.git
После этого приступаем к сборке модуля netmap вместе с драйвером ixgbe (почему мы собираемся из ветки next потому что стабильная имеет крайне критичные баги):
# Debian 7
apt-get install -y linux-headers-3.2.0-4-amd64
# Debian 8
apt-get install -y linux-headers-3.16.0-4-amd64
cd /usr/src
git clone https://github.com/luigirizzo/netmap.git
cd netmap/LINUX/
Накладывем патч sed'ом:
sed -i 's/#define ixgbe_driver_name netmap_ixgbe_driver_name/\/\/\0/' ixgbe_netmap_linux.h
sed -i 's/^char ixgbe_driver_name\[\]/\/\/\0/' ixgbe_netmap_linux.h
Создаем override конфиг:
vim ixgbe-override
Следующим содержимым:
ixgbe-dst := ixgbe
ixgbe-patch := #(leave empty)
ixgbe-src := /usr/src/ixgbe-linux-netmap/ixgbe-3.23.2.1/src/
Также можно заменить ixgbe-3.23.2.1 на ixgbe-4.1.5, чтобы использовать обновленную версию драйвера.

И наконец-то собираемся:
./configure  --override=ixgbe-override --drivers=ixgbe
make
Выгружаем текущий драйвер ixgbe (обычно он идет из поставки ядра) - будьте внимательны, не выгрузите драйвер той сетевой по которой находитесь на машине:
rmmod ixgbe
Загружаем (последовательность важна):
insmod /usr/src/netmap/LINUX/netmap.ko
insmod /usr/src/netmap/LINUX/ixgbe/ixgbe.ko
Убеждаемся, что netmap поднялся:
ls -al /dev/netmap
crw------- 1 root root 10, 59 Oct 29 03:51 /dev/netmap
Кроме этого, вот так выглядит dmesg, если все подцепилось успешно:
[153334.585563] 291.669424 [3083] netmap_init               run mknod /dev/netmap c 10 59 # error 0
[153334.585631] netmap: loaded module
[153334.855803] Intel(R) 10 Gigabit PCI Express Network Driver - version 3.23.2.1
[153334.855853] Copyright (c) 1999-2014 Intel Corporation.
[153334.856074] ixgbe 0000:0a:00.0: setting latency timer to 64
[153334.856209] ixgbe: 0000:0a:00.0: ixgbe_check_options: FCoE Offload feature enabled
[153335.015669] ixgbe 0000:0a:00.0: irq 74 for MSI/MSI-X
[153335.015681] ixgbe 0000:0a:00.0: irq 75 for MSI/MSI-X
[153335.015690] ixgbe 0000:0a:00.0: irq 76 for MSI/MSI-X
[153335.015699] ixgbe 0000:0a:00.0: irq 77 for MSI/MSI-X
[153335.015708] ixgbe 0000:0a:00.0: irq 78 for MSI/MSI-X
[153335.017961] ixgbe 0000:0a:00.0: PCI Express bandwidth of 32GT/s available
[153335.017987] ixgbe 0000:0a:00.0: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[153335.018104] ixgbe 0000:0a:00.0: eth4: MAC: 2, PHY: 9, SFP+: 3, PBA No: E68793-006
[153335.018141] ixgbe 0000:0a:00.0: 90:e2:ba:4a:d8:dc
[153335.018164] ixgbe 0000:0a:00.0: eth4: Enabled Features: RxQ: 4 TxQ: 4 FdirHash DCA RSC
[153335.019351] ixgbe 0000:0a:00.0: eth4: Intel(R) 10 Gigabit Network Connection
[153335.019380] 292.103764 [2720] netmap_attach             success for eth4 tx 4/512 rx 4/512 queues/slots
[153335.019536] ixgbe 0000:0a:00.1: setting latency timer to 64
[153335.019669] ixgbe: 0000:0a:00.1: ixgbe_check_options: FCoE Offload feature enabled
[153336.166573] ixgbe 0000:0a:00.1: irq 89 for MSI/MSI-X
[153336.166584] ixgbe 0000:0a:00.1: irq 90 for MSI/MSI-X
[153336.166593] ixgbe 0000:0a:00.1: irq 91 for MSI/MSI-X
[153336.166602] ixgbe 0000:0a:00.1: irq 92 for MSI/MSI-X
[153336.166611] ixgbe 0000:0a:00.1: irq 93 for MSI/MSI-X
[153336.168899] ixgbe 0000:0a:00.1: PCI Express bandwidth of 32GT/s available
[153336.168927] ixgbe 0000:0a:00.1: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[153336.169044] ixgbe 0000:0a:00.1: eth5: MAC: 2, PHY: 1, PBA No: E68793-006
[153336.169069] ixgbe 0000:0a:00.1: 90:e2:ba:4a:d8:dd
[153336.169092] ixgbe 0000:0a:00.1: eth5: Enabled Features: RxQ: 4 TxQ: 4 FdirHash DCA RSC
[153336.170307] ixgbe 0000:0a:00.1: eth5: Intel(R) 10 Gigabit Network Connection
[153336.170338] 293.256101 [2720] netmap_attach             success for eth5 tx 4/512 rx 4/512 queues/slots
[153336.170491] ixgbe 0000:0d:00.0: setting latency timer to 64
[153336.170624] ixgbe: 0000:0d:00.0: ixgbe_check_options: FCoE Offload feature enabled
[153336.330127] ixgbe 0000:0d:00.0: irq 94 for MSI/MSI-X
[153336.330138] ixgbe 0000:0d:00.0: irq 95 for MSI/MSI-X
[153336.330147] ixgbe 0000:0d:00.0: irq 96 for MSI/MSI-X
[153336.330156] ixgbe 0000:0d:00.0: irq 97 for MSI/MSI-X
[153336.330165] ixgbe 0000:0d:00.0: irq 98 for MSI/MSI-X
[153336.332445] ixgbe 0000:0d:00.0: PCI Express bandwidth of 32GT/s available
[153336.332474] ixgbe 0000:0d:00.0: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[153336.332591] ixgbe 0000:0d:00.0: eth6: MAC: 2, PHY: 9, SFP+: 3, PBA No: E68793-006
[153336.332628] ixgbe 0000:0d:00.0: 90:e2:ba:4a:d8:e8
[153336.332651] ixgbe 0000:0d:00.0: eth6: Enabled Features: RxQ: 4 TxQ: 4 FdirHash DCA RSC
[153336.333845] ixgbe 0000:0d:00.0: eth6: Intel(R) 10 Gigabit Network Connection
[153336.333875] 293.419834 [2720] netmap_attach             success for eth6 tx 4/512 rx 4/512 queues/slots
[153336.334038] ixgbe 0000:0d:00.1: setting latency timer to 64
[153336.334174] ixgbe: 0000:0d:00.1: ixgbe_check_options: FCoE Offload feature enabled
[153337.477010] ixgbe 0000:0d:00.1: irq 99 for MSI/MSI-X
[153337.477021] ixgbe 0000:0d:00.1: irq 100 for MSI/MSI-X
[153337.477030] ixgbe 0000:0d:00.1: irq 101 for MSI/MSI-X
[153337.477039] ixgbe 0000:0d:00.1: irq 102 for MSI/MSI-X
[153337.477048] ixgbe 0000:0d:00.1: irq 103 for MSI/MSI-X
[153337.479378] ixgbe 0000:0d:00.1: PCI Express bandwidth of 32GT/s available
[153337.479406] ixgbe 0000:0d:00.1: (Speed:5.0GT/s, Width: x8, Encoding Loss:20%)
[153337.479523] ixgbe 0000:0d:00.1: eth7: MAC: 2, PHY: 1, PBA No: E68793-006
[153337.479548] ixgbe 0000:0d:00.1: 90:e2:ba:4a:d8:e9
[153337.479570] ixgbe 0000:0d:00.1: eth7: Enabled Features: RxQ: 4 TxQ: 4 FdirHash DCA RSC
[153337.480771] ixgbe 0000:0d:00.1: eth7: Intel(R) 10 Gigabit Network Connection
[153337.480800] 294.568133 [2720] netmap_attach             success for eth7 tx 4/512 rx 4/512 queues/slots


После этого в случае мирроринга трафика включаем передатчики и активируем режим прослушки:
ifconfig eth3 up
ifconfig eth4 up
ifconfig eth3 promisc
ifconfig eth4 promisc

Собираем примеры:
cd /usr/src/netmap/examples
make
Пробуем послушать трафик:
./pkt-gen -i eth3 -f rx
После этого радуемся пришедшему трафику:
./pkt-gen -i eth3 -f rx
680.697796 main [1624] interface is eth3
680.698022 extract_ip_range [275] range is 10.0.0.1:0 to 10.0.0.1:0
680.698032 extract_ip_range [275] range is 10.1.0.1:0 to 10.1.0.1:0
680.979194 main [1807] mapped 334980KB at 0x7f25d7fd4000
Receiving from netmap:eth3: 8 queues, 1 threads and 1 cpus.
680.979231 main [1887] Wait 2 secs for phy reset
682.979291 main [1889] Ready...
682.979330 nm_open [457] overriding ifname eth3 ringid 0x0 flags 0x1
683.980349 main_thread [1421] 137263 pps (137391 pkts in 1000935 usec)
684.981295 main_thread [1421] 124018 pps (124135 pkts in 1000945 usec)
685.259717 main_thread [1421] 120051 pps (33425 pkts in 278423 usec)

Wednesday 15 April 2015

Реализация TFO TCP Fast Open на примере ядра Linux 3.19

В данной статьей я кратко постараюсь объяснить, как устроен внутри Linux ядра механизм TCP Fast Open позволяющий обойтись без 3 этапного установления соединения.

Суть его сводится к тому, что если и клиент и сервер имеют поддержку TFO, о которой сообщают за счет специального флага в TCP пакете (а также сопровождающего его TFO Cookie - секретного ключа), который получают при установке обычного 3-х этапного соединения, то второе и последующие соединения с тем же сервером они могут осуществлять сразу высылая данные в SYN пакете, а не осуществляя повторную установку соединения. Авторизация что этот пакет является легитимным осуществляется за счет проверки TFO Cookie (который ранее был получен от сервера).

Во-первых! Чтобы активировать поддержку и клиентского и серверного TFO на обоих машинах для теста нужно сделать следующее:
sysctl -w net.ipv4.tcp_fastopen=3

Если не задано обратное, то генерация ключей для TFO cookie осуществляется автоматически.

Если же требуется задать ключ вручную, можно использовать спец переменную ядра:
cat /proc/sys/net/ipv4/tcp_fastopen_key
00000000-00000000-00000000-00000000

Обработчик записи в эту переменную (функция proc_tcp_fastopen_key, файл net/ipv4/sysctl_net_ipv4.c) вызывает функцию tcp_fastopen_reset_cipher с параметрами - переданный ключ и его длина. По дефалту генерируется рандомный ключ посредством функции net_get_random_once. После этого создается контекст для шифрования с данным ключем посредством aes алгоритма. Контекст сохраняется в переменной tcp_fastopen_ctx.

Генерация куки для IPv4.

Тут все просто, собирается массив из 4х 32 битных чисел. Два - src и dst IP адреса для данного соединения, два числа еще - нули. После этого все это дело шифруется aes.

Генерация куки для IPv6.

А вот тут немного магии (зовется она CBC MAC: http://en.wikipedia.org/wiki/CBC-MAC). Сначала шифруется IP адрес источника (уже без паддинга нулями - 4 32 битных целых числе). После этого мы берем результат шифрования (4 32 битных числа) и xor-им с соответствующими 32 битными частями целевого IP адреса. После этого результата еще раз шифруем токеном и получаем итоговую cookie.

Кроме этого, судя по тексту из патча:

A simple cookie scheme together with capping the number of outstanding TFO requests (still in TCP_SYN_RECV state) to a limit per listener forms the main line of defense against spoofed SYN
attacks.

Число, которое передается как параметр для listen сокета посредством функции setsockopt(sockfd, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)) используется, чтобы защититься от флуда TFO SYN'ами и перейти на обычный механизм установки соединения.

К сожалению, в процессе тестов мною было убито ядро 3.16, проблема оказалась апстримной и я очень надеюсь, что скоро будет решена :)

В Debian Jessie 8 пред релизной версии сломана поддержка TCP Fast Open сокетов

Вот такая хреновая тема :( Подробнее вот тут: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=782515

Баг апстримный: http://thread.gmane.org/gmane.linux.network/359588

Машину не валит, но сокеты лочит, так что уже назначен уровень Local DoS и можно ждать скорого фикса :)

Ура ура! Баг исправлен! Ждем ребилда ядра :) Следить удобно тут: https://packages.debian.org/sid/linux-image-3.16.0-4-amd64

Ура ура ура! Баг исправлен и доступен в стабильном репо свежего Debian Jessie! Все обновляемся! :)