Обработка потока данных на примере deep packet inspection:...

36
Максим Хижинский, C++ CoreHard Autumn 2017

Upload: corehardby

Post on 22-Jan-2018

89 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Максим Хижинский, C++ CoreHard Autumn 2017

Page 2: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

ПрологПролог

3 вечных вопроса

Что делать?Что делать?

Кто виноват?Кто виноват?

Максим Хижинский, C++ CoreHard Autumn 2017

Page 3: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

ПрологПролог

3 вечных вопроса

Что делать?Что делать?

Кто виноват?Кто виноват? Почему так Почему так получилось?получилось?

Как сделать?Как сделать?

Максим Хижинский, C++ CoreHard Autumn 2017

Page 4: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

4x10G NIC (Network Interface Card)4x10G NIC (Network Interface Card)

Максим Хижинский, C++ CoreHard Autumn 2017

Page 5: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

4x10G NIC

Инструменты:● Netmap — opensource● pf_ring — proprietary● DPDK (Data Plane Dev Kit) — opensource

Key features: ● Работа в userspace, минуя kernel● DMA, no copy

Максим Хижинский, C++ CoreHard Autumn 2017

Page 6: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

4x10G NIC4x10G NIC

Пакет = 512 байт = 2**9 байт = 2**17 битПоток = 40 x 2**30 бит

Итого: 40 x 2**30 / 2**17 = 40 x 2**13 пакетов/сек

Процессор = 4 ГГц ~ 4 x 2**30На пакет: 4 x 2**30 / 40 x 2**13 = 0.1 x 2**17 ~ 2**14 = 16K тактов на пакет

Максим Хижинский, C++ CoreHard Autumn 2017

Page 7: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Port 0

RSS RSS RSS RSS

Port 3

RSS RSS RSS RSS

Port 1

RSS RSS RSS RSS

Port 2

RSS RSS RSS RSS

NIC Application

Thread 0

Thread 1

Thread 2

Thread 3

Thread 4

Thread 5

Thread 6

Thread 7

Thread N

Hash

Page 8: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Порочные практикиПорочные практики

Безумное количество потоков — потоков много больше, чем ядер

Создание потоков «на лету», под выполнение конкретного действия

Максим Хижинский, C++ CoreHard Autumn 2017

Page 9: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Распараллеливание

Thread Thread Thread Thread Thread Thread

Число потоков <= число ядер

Page 10: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Распараллеливание

Thread Thread Thread Thread Thread

Core 0 — свободен (для OS)Hard pinning threads to cores

Page 11: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Worker thread

ХарактеристикиХарактеристики:● No memory allocation● Hard pinned to processor core

● No memcpy (по возможности)

ThreadIn port

Out portМаксим Хижинский, C++ CoreHard Autumn 2017

Page 12: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Worker thread

Характеристики:● No memory allocation (= no std containers)● Hard pinned to processor core● No memcpy (по возможности)

ПроблемыПроблемы: ● Длительные/отложенные действия (авторизация абонента)

● Периодические задачи (тайм-ауты)● Мониторинг внутреннего состояния● Взаимодействие со сторонними системами (DHCP, Radius, ...)

Thread

Максим Хижинский, C++ CoreHard Autumn 2017

Page 13: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Ядро DPIЯдро DPI

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

NIC Application

Thread 0Thread 1Thread 2Thread 3Thread 4Thread 5Thread 6Thread 7

Thread N

Hash

Apartment modelApartment modelСлужебные потоки:Служебные потоки:

Мониторинг, отложенные действия, взаимодействие Мониторинг, отложенные действия, взаимодействие со сторонними системами, ...со сторонними системами, ...

Максим Хижинский, C++ CoreHard Autumn 2017

Page 14: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment modelApartment model - концепция

● Поток (thread) — низкоуровневая абстракция, не связанная с предметной областью

● Понятия «управление потоками» не должно быть в принципе

● ITC (inter-thread communication) — глубоко спрятано. Вызываем member function, где и как она выполняется — определяет владелец

Максим Хижинский, C++ CoreHard Autumn 2017

Page 15: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment modelApartment model - концепция

Msg queue

Apartment == thread

Apartment — замкнутая системаВзаимодействие — только через

MPSC-очередь сообщений

Максим Хижинский, C++ CoreHard Autumn 2017

Page 16: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment modelApartment model - концепция

Apartment 1 Apartment 2

MsgQ MsgQ

Апартменты заселяются компонентами

Заселение - на этапе старта, положение компонента задается в conf-файле

Максим Хижинский, C++ CoreHard Autumn 2017

Page 17: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment modelApartment model - концепция

Apartment 1 Apartment 2

MsgQ MsgQ

Каждый компонент — single threadedОбщение между компонентами — async callКомпоненты не знают о расположении друг друга

Максим Хижинский, C++ CoreHard Autumn 2017

Page 18: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment modelApartment modelclass Component {public: Component( Apartment& ap ): apartment_( ap ) {}

void foo( int arg1, void* arg2 ) { if ( current_apartment() != apartment_ ) apartment_.invoke( this, foo, arg1, arg2 ); else { // находимся в своем апартменте // выполняем свою работу } }

// Вызов — всегда асинхронный void bar() { apartment_.invoke( this, do_bar ); }private: void do_bar() { … }

private: Apartment& apartment_; // в какой апартмент заселен};

Максим Хижинский, C++ CoreHard Autumn 2017

Page 19: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - сервисыApartment model - сервисыКомпоненты хотят:✔Распределять память✔Выполнять периодические или отложенные действия✔Следить за внешними событиями (сетевое

взаимодействие)

Apartment 1

MsgQ

Apartment 2

MsgQ

Apartment allocator (single-threaded!)

Page 20: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - allocatorApartment model - allocatorApartment 1

MsgQ

Apartment 2

MsgQ

1

1

2

3

4

A: ptr = ap1.alloc( 64 )

2 A: B.invoke( foo, ptr );

AB

3 B: foo( ptr ) { ...

4 B: ap1.free( ptr ); }

Page 21: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - allocatorApartment model - allocatorApartment 1

MsgQ

Apartment 2

MsgQ

1

1

A: ptr = ap1.alloc( 64 )

2 A: B.invoke( foo, ptr );

A

3 B: foo( ptr ) { ...

4 B: ap2.free( ptr ); }

B

2

3

4

Page 22: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - allocatorApartment model - allocatorApartment 1

MsgQ

Apartment 2

MsgQ

1

A

4 B: ap2.free( ptr );

B

2

3

4

5

5 ap1.invoke( free, ptr );

6

6 A: ap1.free( ptr );

Page 23: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment allocatorApartment allocator

ТребованияТребования:

● Избежать фрагментации / вспенивания● Для каждого распределенного блока памяти при вызове free() нужно быстро понять, к какому аллокатору (апартменту) он относится

● Выделенный блок памяти не должен иметь префиксов / управляющих структур

РешениеРешение: страничный single-threaded субаллокатор

Максим Хижинский, C++ CoreHard Autumn 2017

Page 24: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment allocatorApartment allocator

Page header

Block 1

Block 1

Block 1

Block N

64 byte blocks

Page header

Block 1

Block 2

Block 3

Block N

128 byte blocks

Page header

Block 1

Block 2

Block 3

Block N

256 byte blocks

Page header

Block 1

Block 2

Block 3

Block N

Page header

Block 1

Block 2

Block 3

Block N

64K byte blocks

1 2 3 k

● Размер страницы — фиксированный (2M)● Для каждой страницы - блоки фиксированного размера● Выделение M байт:

● size_class = ближайшая сверху к M степень двойки● Выделяем свободный блок из страницы для size_class

Максим Хижинский, C++ CoreHard Autumn 2017

Page 25: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment allocatorApartment allocatorstruct page_header { size_class_desc* psc; // дескриптор size_class apartment* owner; // апартмент-владелец страницы void* first_free_block; // 1-й свободный блок страницы page_header* next; // связь в списки для size_class};

struct size_class_desc { apartment* owner; page_header* current_page; // с этой страницы выделяем page_header* part_page_list; // список неполных страниц page_header* full_page_list; // список полных страниц};

Размер страницы — 2M (2**21 — Linux huge page), выравненный по 2M

x x x x 0 0 002063

page header

Максим Хижинский, C++ CoreHard Autumn 2017

Page 26: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - сервисыApartment model - сервисыКомпоненты хотят:✔Распределять память - done✔Выполнять периодические или отложенные действия✔Следить за внешними событиями (сетевое

взаимодействие)

Apartment 1

MsgQ

Apartment 2

MsgQ

Максим Хижинский, C++ CoreHard Autumn 2017

Page 27: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - schedulerApartment model - scheduler

Apartment 1

MsgQ

Apartment 2

MsgQ

Root apartment

MsgQ

Scheduler + Connection monitor

add fdschedule

Выполнить foo() в apartment 1

через T ms(в т.ч. периоди-

чески)

add/remove fd toconnection monitor,invoke bar() on event

in apartment 2

Page 28: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Apartment model - schedulerApartment model - schedulerRoot apartment

MsgQ

Scheduler + Connection monitor

epoll_wait()

int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout );

Максим Хижинский, C++ CoreHard Autumn 2017

Page 29: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Ядро DPIЯдро DPI

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

NIC Application

Thread 0Thread 1Thread 2Thread 3Thread 4Thread 5Thread 6Thread 7

Thread N

Hash

Shared dataShared data

Hash — не всегда распределит в нужный поток — появляютсяshared data между worker threads

Persistent data (например, сессии) — создаются в apartment, используются в worker threads

Page 30: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Shared dataShared data

По месту созданияПо месту создания:

● Worker threads — нет аллокатора, на предраспределенных массивах (pointer = индекс в массиве)

● Apartment — есть аллокатор, истинно динамические контейнеры

Постоянная задачаПостоянная задача: по возможности вывести создание/удаление shared data в apartment

Максим Хижинский, C++ CoreHard Autumn 2017

Page 31: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Shared dataShared data

Intrusive (in-place) containersIntrusive (in-place) containers

● std — хранит копии, intrusive — no copy● Разделено создание данных и операции с контейнером

● Одни и те же данные можно одновременно хранить в разных контейнерах

пример: boost::intrusiveboost::intrusive

Максим Хижинский, C++ CoreHard Autumn 2017

Page 32: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Intrusive containersIntrusive containerstemplate <typename Tag = void>struct slist_node { slist_node<Tag>* next_;};

template <typename Tag = void>struct rbtree_node { rbtree_node<Tag>* parent_, * left_, * right_; int color;};

struct tag_list1 {};struct tag_list2 {};

struct my_data: slist_node<tag_list1>, slist_node<tag_list2>, rbtree_node<>{ std::string key; // прочие данные};

Максим Хижинский, C++ CoreHard Autumn 2017

Page 33: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

P – thread count

Thread 0

Thread HP Manager

0

1

K - 1

HP[K]0

1

2

R - 1

Retired[R]

Hazard Pointer Singleton

Thread 1

Thread P - 1

K = 4 R = 2 KP

<K,P, R> : R > K * P

Hazard PointersHazard Pointers

Максим Хижинский, C++ CoreHard Autumn 2017

Page 34: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Удаление элемента

void hp_retire( T * what ) {

push what to current_thread.Retired array

if ( current_thread.Retired is full )

hp.Scan( current_thread );

}

void hp::Scan() {

void * guarded[K*P] = union HP[K] for all P thread;

foreach ( p in current_thread.Retired[R] )

if ( p not in guarded[] )

delete p;

}

<K,P, R> : R > K * P

012…

R - 1

Retired[R]

01…

K - 1

HP[K]

Гарантия scan():

Hazard PointersHazard Pointers

Максим Хижинский, C++ CoreHard Autumn 2017

Page 35: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Ядро DPIЯдро DPI

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

RSS RSS RSS RSS

NIC Application

Thread 0Thread 1Thread 2Thread 3Thread 4Thread 5Thread 6Thread 7

Thread N

Hash

Hazard PointersHazard Pointers

HP применима, если:● Либо Scan() вызывается в apartment, не в worker thread● Либо Scan() в worker threads подменяет Retired array на

пустой из пула и передает заполненный Retired array в apartment

Page 36: Обработка потока данных на примере deep packet inspection: внутренняя архитектура и решения

Спасибо за вниманиеСпасибо за внимание

Максим Хижинский, C++ CoreHard Autumn 2017