bpf(2) - wariua/manpages-ko GitHub Wiki

NAME

bpf - ํ™•์žฅ BPF ๋งต๊ณผ ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ๋ช…๋ น ์ˆ˜ํ–‰ํ•˜๊ธฐ

SYNOPSIS

#include <linux/bpf.h>

int bpf(int cmd, union bpf_attr *attr, unsigned int size);

DESCRIPTION

bpf() ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ ํ™•์žฅ ๋ฒ„ํด๋ฆฌ ํŒจํ‚ท ํ•„ํ„ฐ(extended Berkeley Packet Filter)์™€ ๊ด€๋ จ๋œ ๋‹ค์–‘ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. ํ™•์žฅ BPF(eBPF)๋Š” ๋„คํŠธ์›Œํฌ ํŒจํ‚ท ํ•„ํ„ฐ๋ง์— ์“ฐ๋Š” ์›๋ž˜์˜ ("์ „ํ†ต์ ") BPF(cBPF)์™€ ๋น„์Šทํ•˜๋‹ค. cBPF ํ”„๋กœ๊ทธ๋žจ๊ณผ eBPF ํ”„๋กœ๊ทธ๋žจ ๋ชจ๋‘ ์ ์žฌ ์ „์— ์ปค๋„์ด ์ •์  ๋ถ„์„์„ ํ•˜์—ฌ ์‹คํ–‰ ์‹œ์Šคํ…œ์— ํ•ด๋ฅผ ๋ผ์น˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

eBPF๋Š” cBPF๋ฅผ ์—ฌ๋Ÿฌ ๋ฐฉ์‹์œผ๋กœ ํ™•์žฅํ•œ ๊ฒƒ์ด๋‹ค. (eBPF์—์„œ ์ œ๊ณตํ•˜๋Š” BPF_CALL ๋ช…๋ น ์ฝ”๋“œ ํ™•์žฅ์„ ํ†ตํ•ด) ์ •ํ•ด์ง„ ์ปค๋„ ๋‚ด ํ•จ์ˆ˜๋“ค์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ eBPF ๋งต ๊ฐ™์€ ๊ณต์œ  ์ž๋ฃŒ ๊ตฌ์กฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ™•์žฅ BPF ์„ค๊ณ„/๊ตฌ์กฐ

eBPF ๋งต์€ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฐ์ดํ„ฐ ์ €์žฅ์„ ์œ„ํ•œ ๋ฒ”์šฉ ์ž๋ฃŒ ๊ตฌ์กฐ์ด๋‹ค. ๋ฐ์ดํ„ฐ ํƒ€์ž…๋“ค์„ ์ผ๋ฐ˜์ ์œผ๋กœ ์ด์ง„ ๋ฐ”์ดํŠธ ์—ด๋กœ ๋‹ค๋ฃจ๋ฉฐ, ๊ทธ๋ž˜์„œ ์‚ฌ์šฉ์ž๊ฐ€ ๋งต ์ƒ์„ฑ ์‹œ์ ์— ํ‚ค์˜ ํฌ๊ธฐ์™€ ๊ฐ’์˜ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•  ๋ฟ์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด ๋งต์ด ์žˆ์„ ๋•Œ ๊ทธ ํ‚ค/๊ฐ’์€ ์–ด๋–ค ๊ตฌ์กฐ๋“  ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค์—์„œ (๋ถˆํˆฌ๋ช… ๋ฐ์ดํ„ฐ์ธ ํ‚ค/๊ฐ’ ์Œ์„ ๊ฐ€์ง„) ์—ฌ๋Ÿฌ ๋งต์„ ๋งŒ๋“ค๊ณ  ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๋Ÿฌ eBPF ํ”„๋กœ๊ทธ๋žจ๋“ค์ด ๊ฐ™์€ ๋งต์— ๋ณ‘๋ ฌ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งต ์•ˆ์— ๋ฌด์—‡์„ ์ €์žฅํ• ์ง€๋Š” ์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค์™€ eBPF ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฐ์ •์— ๋‹ฌ๋ ค ์žˆ๋‹ค.

ํŠน์ˆ˜ํ•œ ์ข…๋ฅ˜์˜ ๋งต์ด ํ•˜๋‚˜ ์žˆ๋Š”๋ฐ, ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ด ๋งต์€ ๋‹ค๋ฅธ eBPF ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋“ค์„ ์ €์žฅํ•œ๋‹ค. ๊ทธ ๋งต์—์„œ ํƒ์ƒ‰ ์ˆ˜ํ–‰ ์‹œ ํ”„๋กœ๊ทธ๋žจ ํ๋ฆ„์ด ๋‹ค๋ฅธ eBPF ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ์ž‘์ ์œผ๋กœ ๊ทธ๋Œ€๋กœ ์˜ฎ๊ฒจ์ง€๋ฉฐ ํ˜ธ์ถœ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ๋˜๋Œ์•„ ์˜ค์ง€ ์•Š๋Š”๋‹ค. ๋“ค์–ด๊ฐ€๋Š” ๊นŠ์ด์— 32๋ฒˆ์ด๋ผ๋Š” ๊ณ ์ • ์ œํ•œ์ด ์žˆ์–ด์„œ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์—†๊ฒŒ ํ•œ๋‹ค. ๋Ÿฐํƒ€์ž„์— ๋งต์— ์ €์žฅ๋œ ํ”„๋กœ๊ทธ๋žจ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋“ค์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ตฌ์ฒด์  ์š”๊ตฌ์— ๋”ฐ๋ผ ํ”„๋กœ๊ทธ๋žจ ๊ธฐ๋Šฅ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด ๋งต์—์„œ ์ฐธ์กฐํ•˜๋Š” ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ์€ bpf()๋ฅผ ํ†ตํ•ด ์ปค๋„๋กœ ๋ฏธ๋ฆฌ ์ ์žฌํ•ด ๋‘์–ด์•ผ ํ•œ๋‹ค. ๋งต ํƒ์ƒ‰์ด ์‹คํŒจํ•˜๋ฉด ํ˜„์žฌ ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰์„ ๊ณ„์†ํ•œ๋‹ค. ๋” ์ž์„ธํ•œ ๊ฑด ์•„๋ž˜์˜ BPF_MAP_TYPE_PROG_ARRAY ์„ค๋ช…์„ ๋ณด๋ผ.

์ผ๋ฐ˜์ ์œผ๋กœ eBPF ํ”„๋กœ๊ทธ๋žจ์€ ์‚ฌ์šฉ์ž ํ”„๋กœ๊ทธ๋žจ์— ์˜ํ•ด ์ ์žฌ๋˜๋ฉฐ ๊ทธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋๋‚  ๋•Œ ์ž๋™์œผ๋กœ ๋‚ด๋ ค๊ฐ„๋‹ค. tc-bpf(8) ๊ฐ™์€ ์ผ๋ถ€ ๊ฒฝ์šฐ์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ ์žฌํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋๋‚œ ํ›„์—๋„ ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„ ๋‚ด์— ๊ณ„์† ์‚ด์•„ ์žˆ๋‹ค. ๊ทธ ๊ฒฝ์šฐ์—๋Š” ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋‹ซ์€ ํ›„์— tc ์„œ๋ธŒ์‹œ์Šคํ…œ์ด eBPF ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ์žก๊ณ  ์žˆ๋Š”๋‹ค. ์ฆ‰, ํŠน์ • ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„ ๋‚ด์— ๊ณ„์† ์‚ด์•„ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋Š” bpf()๋ฅผ ํ†ตํ•ด ์ ์žฌ๋œ ํ›„์— ํ•ด๋‹น ์ปค๋„ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์–ด๋–ป๊ฒŒ ๋ถ™๋Š”๊ฐ€์— ๋”ฐ๋ผ ์ •ํ•ด์ง„๋‹ค.

๊ฐ eBPF ํ”„๋กœ๊ทธ๋žจ์€ ์™„๋ฃŒ ๋•Œ๊นŒ์ง€ ์•ˆ์ „ํ•˜๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์ŠคํŠธ๋Ÿญ์…˜๋“ค์˜ ์ง‘ํ•ฉ์ด๋‹ค. eBPF ํ”„๋กœ๊ทธ๋žจ์— ๋์ด ์žˆ๊ณ  ์‹คํ–‰ํ•˜๊ธฐ์— ์•ˆ์ „ํ•œ์ง€๋ฅผ ์ปค๋„ ๋‚ด ๊ฒ€์ฆ๊ธฐ๊ฐ€ ์ •์ ์œผ๋กœ ํŒ๋‹จํ•œ๋‹ค. ๊ฒ€์ฆํ•˜๋Š” ๋™์•ˆ ์ปค๋„์€ ๊ทธ eBPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋งต๋“ค ๊ฐ๊ฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ ์นด์šดํ„ฐ๋ฅผ ์˜ฌ๋ ค์„œ ํ”„๋กœ๊ทธ๋žจ์„ ๋‚ด๋ฆด ๋•Œ๊นŒ์ง€ ๊ด€๋ จ ๋งต๋“ค์ด ์ œ๊ฑฐ๋˜์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.

eBPF ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ์— ์—ฐ๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ์ด๋ฒคํŠธ๋Š” ๋„คํŠธ์›Œํฌ ํŒจํ‚ท ๋„์ฐฉ์ผ ์ˆ˜๋„ ์žˆ๊ณ , ์ถ”์  ์ด๋ฒคํŠธ, ๋„คํŠธ์›Œํฌ ํ ๊ทœ์ œ์˜ ๋ถ„๋ฅ˜ ์ด๋ฒคํŠธ (tc(8) ๋ถ„๋ฅ˜์ž์— ์—ฐ๊ณ„๋œ eBPF ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ), ๊ทธ๋ฆฌ๊ณ  ํ–ฅํ›„ ์ถ”๊ฐ€๋  ๋‹ค๋ฅธ ์ข…๋ฅ˜์ผ ์ˆ˜ ์žˆ๋‹ค. ์ƒˆ ์ด๋ฒคํŠธ๊ฐ€ eBPF ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์„ ์ผ์œผํ‚ค๊ณ , ๊ทธ๋Ÿฌ๋ฉด ํ”„๋กœ๊ทธ๋žจ์—์„œ eBPF ๋งต์— ๊ทธ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ฐ์ดํ„ฐ ์ €์žฅ ์™ธ์— eBPF ํ”„๋กœ๊ทธ๋žจ์ด ํ•œ์ •๋œ ์ปค๋„ ๋‚ด ํ—ฌํผ ํ•จ์ˆ˜๋“ค์„ ํ˜ธ์ถœํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

๋™์ผํ•œ eBPF ํ”„๋กœ๊ทธ๋žจ์„ ์—ฌ๋Ÿฌ ์ด๋ฒคํŠธ์— ์—ฐ๊ณ„ํ•  ์ˆ˜ ์žˆ๊ณ  ์ƒ์ดํ•œ eBPF ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ผ ๋งต์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถ”์        ์ถ”์        ์ถ”์         eth0์˜      eth1์˜      eth2์˜
์ด๋ฒคํŠธ A   ์ด๋ฒคํŠธ B   ์ด๋ฒคํŠธ C    ํŒจํ‚ท        ํŒจํ‚ท        ํŒจํ‚ท
  |          |          |           |           |           ^
  |          |          |           |           v           |
  --> ์ถ”์  <--        ์ถ”์         ์†Œ์ผ“       tc ์ž…๊ตฌ     tc ์ถœ๊ตฌ
      prog_1          prog_2      prog_3      ๋ถ„๋ฅ˜์ž       ํ–‰์œ„
      |  |              |           |         prog_4      prog_5
   |---  -----|  |------|          map_3        |           |
 map_1       map_2                              --| map_4 |--

์ธ์ž

cmd ์ธ์ž๊ฐ€ bpf() ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด ์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ๊ฒฐ์ •ํ•œ๋‹ค. ๊ฐ ์ž‘์—…์€ bpf_attr ํƒ€์ž… ๊ณต์šฉ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์ธ attr์„ ํ†ตํ•ด ์ถ”๊ฐ€ ์ธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค (์•„๋ž˜ ์ฐธ๊ณ ). size ์ธ์ž๋Š” attr์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ณต์šฉ์ฒด์˜ ํฌ๊ธฐ์ด๋‹ค.

cmd๋กœ ์ฃผ๋Š” ๊ฐ’์€ ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

BPF_MAP_CREATE
๋งต์„ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ ๋งต์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—๋Š” 'exec์—์„œ ๋‹ซ๊ธฐ' ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ํ”Œ๋ž˜๊ทธ(fcntl(2) ์ฐธ๊ณ )๊ฐ€ ์ž๋™์œผ๋กœ ์ผœ์ง„๋‹ค.
BPF_MAP_LOOKUP_ELEM
์ง€์ •ํ•œ ๋งต์—์„œ ํ‚ค๋กœ ํ•ญ๋ชฉ์„ ์ฐพ์•„์„œ ๊ทธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
BPF_MAP_UPDATE_ELEM
์ง€์ •ํ•œ ๋งต์—์„œ ํ•ญ๋ชฉ(ํ‚ค/๊ฐ’ ์Œ)์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ฐฑ์‹ ํ•œ๋‹ค.
BPF_MAP_DELETE_ELEM
์ง€์ •ํ•œ ๋งต์—์„œ ํ‚ค๋กœ ํ•ญ๋ชฉ์„ ์ฐพ์•„์„œ ์‚ญ์ œํ•œ๋‹ค.
BPF_MAP_GET_NEXT_KEY
์ง€์ •ํ•œ ๋งต์—์„œ ํ‚ค๋กœ ํ•ญ๋ชฉ์„ ์ฐพ์•„์„œ ๋‹ค์Œ ํ•ญ๋ชฉ์˜ ํ‚ค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
BPF_PROG_LOAD
eBPF ํ”„๋กœ๊ทธ๋žจ์„ ๊ฒ€์ฆ ๋ฐ ์ ์žฌํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ๊ณผ ์—ฐ๊ณ„๋œ ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์—๋Š” 'exec์—์„œ ๋‹ซ๊ธฐ' ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ ํ”Œ๋ž˜๊ทธ(fcntl(2) ์ฐธ๊ณ )๊ฐ€ ์ž๋™์œผ๋กœ ์ผœ์ง„๋‹ค.

bpf_attr ๊ณต์šฉ์ฒด๋Š” ์—ฌ๋Ÿฌ bpf() ๋ช…๋ น์—์„œ ์“ฐ๋Š” ๋‹ค์–‘ํ•œ ์ต๋ช… ๊ตฌ์กฐ์ฒด๋“ค๋กœ ์ด๋ค„์ ธ ์žˆ๋‹ค.

union bpf_attr {
    struct {    /* BPF_MAP_CREATE์— ์‚ฌ์šฉ */
        __u32         map_type;
        __u32         key_size;    /* ํ‚ค ํฌ๊ธฐ, ๋ฐ”์ดํŠธ ๋‹จ์œ„ */
        __u32         value_size;  /* ๊ฐ’ ํฌ๊ธฐ, ๋ฐ”์ดํŠธ ๋‹จ์œ„ */
        __u32         max_entries; /* ๋งต ๋‚ด์˜ ํ•ญ๋ชฉ ์ตœ๋Œ€ ๊ฐœ์ˆ˜ */
    };

    struct {    /* BPF_MAP_*_ELEM ๋ฐ BPF_MAP_GET_NEXT_KEY
                   ๋ช…๋ น์— ์‚ฌ์šฉ */
        __u32         map_fd;
        __aligned_u64 key;
        union {
            __aligned_u64 value;
            __aligned_u64 next_key;
        };
        __u64         flags;
    };

    struct {    /* BPF_PROG_LOAD์— ์‚ฌ์šฉ */
        __u32         prog_type;
        __u32         insn_cnt;
        __aligned_u64 insns;      /* 'const struct bpf_insn *' */
        __aligned_u64 license;    /* 'const char *' */
        __u32         log_level;  /* ๊ฒ€์ฆ๊ธฐ์˜ ์ƒ์„ธ๋„ ์ˆ˜์ค€ */
        __u32         log_size;   /* ์‚ฌ์šฉ์ž ๋ฒ„ํผ ํฌ๊ธฐ */
        __aligned_u64 log_buf;    /* ์‚ฌ์šฉ์ž๊ฐ€ ์ œ๊ณตํ•˜๋Š” 'char *'
                                     ๋ฒ„ํผ */
        __u32         kern_version;
                                  /* prog_type=kprobe์ผ ๋•Œ ๊ฒ€์‚ฌ
                                     (๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ) */
    };
} __attribute__((aligned(8)));

eBPF ๋งต

๋งต์€ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ”์šฉ ์ž๋ฃŒ ๊ตฌ์กฐ์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด eBPF ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ๋“ค ์‚ฌ์ด์—์„œ, ๊ทธ๋ฆฌ๊ณ  ์ปค๋„๊ณผ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ์‘์šฉ ์‚ฌ์ด์—์„œ ๋ฐ์ดํ„ฐ ๊ณต์œ ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

๊ฐ ๋งต์—๋Š” ๋‹ค์Œ ์†์„ฑ์ด ์žˆ๋‹ค.

  • ์ข…๋ฅ˜

  • ํ•ญ๋ชฉ ์ตœ๋Œ€ ๊ฐœ์ˆ˜

  • ํ‚ค์˜ ๋ฐ”์ดํŠธ ๋‹จ์œ„ ํฌ๊ธฐ

  • ๊ฐ’์˜ ๋ฐ”์ดํŠธ ๋‹จ์œ„ ํฌ๊ธฐ

๋‹ค์–‘ํ•œ bpf() ๋ช…๋ น์œผ๋กœ ๋งต์— ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•„๋ž˜ ๋ž˜ํผ ํ•จ์ˆ˜๋“ค์ด ๋ณด์—ฌ ์ค€๋‹ค. ์ด ํ•จ์ˆ˜๋“ค์€ cmd ์ธ์ž๋ฅผ ์ด์šฉํ•ด ๊ฐ๊ธฐ ๋‹ค๋ฅธ ์ž‘์—…์„ ํ˜ธ์ถœํ•œ๋‹ค.

BPF_MAP_CREATE

BPF_MAP_CREATE ๋ช…๋ น์€ ์ƒˆ๋กœ์šด ๋งต์„ ๋งŒ๋“ค๊ณ  ๊ทธ ๋งต์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

int
bpf_create_map(enum bpf_map_type map_type,
               unsigned int key_size,
               unsigned int value_size,
               unsigned int max_entries)
{
    union bpf_attr attr = {
        .map_type    = map_type,
        .key_size    = key_size,
        .value_size  = value_size,
        .max_entries = max_entries
    };

    return bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
}

์ƒˆ ๋งต์€ map_type์œผ๋กœ ์ง€์ •ํ•œ ์ข…๋ฅ˜์ด๊ณ  key_size, value_size, max_entries๋กœ ์ง€์ •ํ•œ ์†์„ฑ์„ ๊ฐ€์ง„๋‹ค. ์„ฑ๊ณต ์‹œ ์ด ๋™์ž‘์€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์˜ค๋ฅ˜ ์‹œ -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ EINVAL์ด๋‚˜ EPERM, ENOMEM์œผ๋กœ ์„ค์ •ํ•œ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ ์ ์žฌ ๊ณผ์ •์—์„œ ํ”„๋กœ๊ทธ๋žจ์ด ์˜ฌ๋ฐ”๋กœ ์ดˆ๊ธฐํ™” ํ•œ key๋กœ bpf_map_*_elem() ํ—ฌํผ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ ๋งต ํ•ญ๋ชฉ value๋ฅผ ์ง€์ •ํ•œ value_size ๋„ˆ๋จธ๋กœ ์ ‘๊ทผํ•˜์ง€ ์•Š์Œ์„ ๊ฒ€์ฆ๊ธฐ์—์„œ ํ™•์ธํ•˜๋Š” ๋ฐ key_size์™€ value_size ์†์„ฑ์„ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด key_size๋ฅผ 8๋กœ ํ•ด์„œ ๋งต์„ ์ƒ์„ฑํ–ˆ๋Š”๋ฐ eBPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‹ค์Œ ํ˜ธ์ถœ์„ ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ๊ฑฐ๋ถ€๋  ๊ฒƒ์ด๋‹ค.

bpf_map_lookup_elem(map_fd, fp - 4)

์ปค๋„ ๋‚ด ํ—ฌํผ ํ•จ์ˆ˜์ธ

bpf_map_lookup_elem(map_fd, void *key)

์—์„œ๋Š” key๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ์œ„์น˜์—์„œ 8๋ฐ”์ดํŠธ๋ฅผ ์ฝ๊ธฐ๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š”๋ฐ fp - 4(fp๋Š” ์Šคํƒ ์ƒ๋‹จ)๋ผ๋Š” ์‹œ์ž‘ ์ฃผ์†Œ๋Š” ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ์Šคํƒ ์ ‘๊ทผ์„ ์œ ๋ฐœํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ value_size๋ฅผ 1๋กœ ํ•ด์„œ ๋งต์„ ์ƒ์„ฑํ–ˆ๋Š”๋ฐ eBPF ํ”„๋กœ๊ทธ๋žจ์— ๋‹ค์Œ ๋‚ด์šฉ์ด ์žˆ์œผ๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ๊ฑฐ๋ถ€๋  ๊ฒƒ์ด๋‹ค.

value = bpf_map_lookup_elem(...);
*(u32 *) value = 1;

์ง€์ •ํ•œ 1๋ฐ”์ดํŠธ value_size ์ œํ•œ ๋„ˆ๋จธ๋กœ value ํฌ์ธํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ˜„์žฌ map_type์œผ๋กœ ๋‹ค์Œ ๊ฐ’๋“ค์„ ์ง€์›ํ•œ๋‹ค.

enum bpf_map_type {
    BPF_MAP_TYPE_UNSPEC,  /* 0์€ ์œ ํšจํ•˜์ง€ ์•Š์€ ๋งต ์ข…๋ฅ˜๋กœ ์˜ˆ์•ฝ */
    BPF_MAP_TYPE_HASH,
    BPF_MAP_TYPE_ARRAY,
    BPF_MAP_TYPE_PROG_ARRAY,
    BPF_MAP_TYPE_PERF_EVENT_ARRAY,
    BPF_MAP_TYPE_PERCPU_HASH,
    BPF_MAP_TYPE_PERCPU_ARRAY,
    BPF_MAP_TYPE_STACK_TRACE,
    BPF_MAP_TYPE_CGROUP_ARRAY,
    BPF_MAP_TYPE_LRU_HASH,
    BPF_MAP_TYPE_LRU_PERCPU_HASH,
    BPF_MAP_TYPE_LPM_TRIE,
    BPF_MAP_TYPE_ARRAY_OF_MAPS,
    BPF_MAP_TYPE_HASH_OF_MAPS,
    BPF_MAP_TYPE_DEVMAP,
    BPF_MAP_TYPE_SOCKMAP,
    BPF_MAP_TYPE_CPUMAP,
};

map_type์ด ์ปค๋„์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋งต ๊ตฌํ˜„๋“ค ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•œ๋‹ค. eBPF ํ”„๋กœ๊ทธ๋žจ์€ ๋ชจ๋“  ๋งต ์ข…๋ฅ˜์— ๋™์ผํ•œ bpf_map_lookup_elem() ๋ฐ bpf_map_update_elem() ํ—ฌํผ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ์ ‘๊ทผํ•œ๋‹ค. ์•„๋ž˜์— ์—ฌ๋Ÿฌ ๋งต ์ข…๋ฅ˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์ด ์žˆ๋‹ค.

BPF_MAP_LOOKUP_ELEM

BPF_MAP_LOOKUP_ELEM ๋ช…๋ น์€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งต์—์„œ ์ฃผ์–ด์ง„ key๋กœ ํ•ญ๋ชฉ์„ ์ฐพ๋Š”๋‹ค.

int
bpf_lookup_elem(int fd, const void *key, void *value)
{
    union bpf_attr attr = {
        .map_fd = fd,
        .key    = ptr_to_u64(key),
        .value  = ptr_to_u64(value),
    };

    return bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
}

ํ•ญ๋ชฉ์„ ์ฐพ์œผ๋ฉด ๋™์ž‘์ด 0์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ํ•ญ๋ชฉ์˜ ๊ฐ’์„ value์— ์ €์žฅํ•œ๋‹ค. value๋Š” value_size ๋ฐ”์ดํŠธ ํฌ๊ธฐ์˜ ๋ฒ„ํผ๋ฅผ ๊ฐ€๋ฆฌ์ผœ์•ผ ํ•œ๋‹ค.

ํ•ญ๋ชฉ์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด ๋™์ž‘์ด -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ ENOENT๋กœ ์„ค์ •ํ•œ๋‹ค.

BPF_MAP_UPDATE_ELEM

BPF_MAP_UPDATE_ELEM ๋ช…๋ น์€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งต์—์„œ ์ฃผ์–ด์ง„ key/value๋กœ ํ•ญ๋ชฉ์„ ์ƒ์„ฑ ๋˜๋Š” ๊ฐฑ์‹ ํ•œ๋‹ค.

int
bpf_update_elem(int fd, const void *key, const void *value,
                uint64_t flags)
{
    union bpf_attr attr = {
        .map_fd = fd,
        .key    = ptr_to_u64(key),
        .value  = ptr_to_u64(value),
        .flags  = flags,
    };

    return bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
}

flags ์ธ์ž๋Š” ๋‹ค์Œ ์ค‘ ํ•˜๋‚˜๋กœ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

BPF_ANY
์ƒˆ ํ•ญ๋ชฉ์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ํ•ญ๋ชฉ์„ ๊ฐฑ์‹ ํ•œ๋‹ค.
BPF_NOEXIST
์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ ์ƒˆ ํ•ญ๋ชฉ์„ ์ƒ์„ฑํ•˜๊ธฐ๋งŒ ํ•œ๋‹ค.
BPF_EXIST
๊ธฐ์กด ํ•ญ๋ชฉ์„ ๊ฐฑ์‹ ํ•œ๋‹ค.

์„ฑ๊ณต ์‹œ ๋™์ž‘์ด 0์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์˜ค๋ฅ˜ ์‹œ -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ EINVAL์ด๋‚˜ EPERM, ENOMEM, E2BIG์œผ๋กœ ์„ค์ •ํ•œ๋‹ค. E2BIG์€ ๋งต ๋‚ด์˜ ํ•ญ๋ชฉ ์ˆ˜๊ฐ€ ๋งต ์ƒ์„ฑ ์‹œ ์ง€์ •ํ•œ max_entries ์ œํ•œ์— ๋„๋‹ฌํ–ˆ๋‹ค๋Š” ๋œป์ด๋‹ค. flags๊ฐ€ BPF_NOEXIST์ธ๋ฐ key๋ฅผ ๊ฐ€์ง„ ํ•ญ๋ชฉ์ด ์ด๋ฏธ ๋งต์— ์กด์žฌํ•˜๋ฉด EEXIST๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. flags๊ฐ€ BPF_EXIST์ธ๋ฐ key๋ฅผ ๊ฐ€์ง„ ํ•ญ๋ชฉ์ด ๋งต์— ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ENOENT๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

BPF_MAP_DELETE_ELEM

BPF_MAP_DELETE_ELEM ๋ช…๋ น์€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งต์—์„œ ํ‚ค๊ฐ€ key์ธ ํ•ญ๋ชฉ์„ ์‚ญ์ œํ•œ๋‹ค.

int
bpf_delete_elem(int fd, const void *key)
{
    union bpf_attr attr = {
        .map_fd = fd,
        .key    = ptr_to_u64(key),
    };

    return bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
}

์„ฑ๊ณต ์‹œ 0์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํ•ญ๋ชฉ์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ ENOENT๋กœ ์„ค์ •ํ•œ๋‹ค.

BPF_MAP_GET_NEXT_KEY

BPF_MAP_GET_NEXT_KEY ๋ช…๋ น์€ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งต์—์„œ key๋กœ ํ•ญ๋ชฉ์„ ์ฐพ์•„์„œ next_key๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฒ„ํผ๋ฅผ ๊ทธ ๋‹ค์Œ ํ•ญ๋ชฉ์˜ ํ‚ค๋กœ ์„ค์ •ํ•œ๋‹ค.

int
bpf_get_next_key(int fd, const void *key, void *next_key)
{
    union bpf_attr attr = {
        .map_fd   = fd,
        .key      = ptr_to_u64(key),
        .next_key = ptr_to_u64(next_key),
    };

    return bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
}

key๋ฅผ ์ฐพ์œผ๋ฉด ๋™์ž‘์ด 0์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ next_key๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฒ„ํผ๋ฅผ ๋‹ค์Œ ํ•ญ๋ชฉ์˜ ํ‚ค๋กœ ์„ค์ •ํ•œ๋‹ค. key๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด ๋™์ž‘์ด 0์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ next_key๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฒ„ํผ๋ฅผ ์ฒซ ๋ฒˆ์งธ ํ•ญ๋ชฉ์˜ ํ‚ค๋กœ ์„ค์ •ํ•œ๋‹ค. key๊ฐ€ ๋งˆ์ง€๋ง‰ ํ•ญ๋ชฉ์ด๋ฉด -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ ENOENT๋กœ ์„ค์ •ํ•œ๋‹ค. ๊ฐ€๋Šฅํ•œ ๋‹ค๋ฅธ errno ๊ฐ’์€ ENOMEM, EFAULT, EPERM, EINVAL์ด๋‹ค. ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ด ๋งต์˜ ํ•ญ๋ชฉ ์ „์ฒด๋ฅผ ์ˆœํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

close(map_fd)

ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋งต์„ ์‚ญ์ œํ•œ๋‹ค. ๋งต์„ ์ƒ์„ฑํ•œ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ์ข…๋ฃŒํ•  ๋•Œ ๋ชจ๋“  ๋งต๋“ค์ด ์ž๋™์œผ๋กœ ์‚ญ์ œ๋œ๋‹ค. (ํ•˜์ง€๋งŒ NOTES๋ฅผ ๋ณด๋ผ.)

eBPF ๋งต ์ข…๋ฅ˜

๋‹ค์Œ ์ข…๋ฅ˜์˜ ๋งต์„ ์ง€์›ํ•œ๋‹ค.

BPF_MAP_TYPE_HASH

ํ•ด์‹œ ํ…Œ์ด๋ธ” ๋งต์˜ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ๋งต์„ ์ƒ์„ฑํ•˜๊ณ  ์—†์•ค๋‹ค. ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ๊ณผ eBPF ํ”„๋กœ๊ทธ๋žจ ๋ชจ๋‘ ๊ฒ€์ƒ‰, ๊ฐฑ์‹ , ์‚ญ์ œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ปค๋„์ด ํ‚ค/๊ฐ’ ์Œ์˜ ํ• ๋‹น๊ณผ ํ•ด์ œ๋ฅผ ๋งก๋Š”๋‹ค.

  • max_entries ํ•œ๊ณ„์— ๋„๋‹ฌํ•˜๋ฉด map_update_elem() ํ—ฌํผ๊ฐ€ ์‚ฝ์ž…์— ์‹คํŒจํ•˜๊ฒŒ ๋œ๋‹ค. (๊ทธ๋ž˜์„œ eBPF ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ ๊ฐˆ์‹œํ‚ค์ง€ ๋ชปํ•œ๋‹ค.)

  • map_update_elem()์ด ๊ธฐ์กด ํ•ญ๋ชฉ์„ ์›์ž์ ์œผ๋กœ ๊ต์ฒดํ•œ๋‹ค.

ํ•ด์‹œ ํ…Œ์ด๋ธ” ๋งต์€ ๊ฒ€์ƒ‰ ์†๋„์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๋‹ค.

BPF_MAP_TYPE_ARRAY

๋ฐฐ์—ด ๋งต์˜ ํŠน์ง•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ๊ฐ€๋Šฅํ•œ ์ตœ๊ณ  ์†๋„์˜ ๊ฒ€์ƒ‰์— ์ตœ์ ํ™”๋˜์–ด ์žˆ๋‹ค. ํ–ฅํ›„์— ๊ฒ€์ฆ๊ธฐ/JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ƒ์ˆ˜ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” lookup() ์ž‘์—…์„ ์ธ์‹ํ•ด์„œ ์ด๋ฅผ ์ƒ์ˆ˜ ํฌ์ธํ„ฐ๋กœ ์ตœ์ ํ™”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์ƒ์ˆ˜ ์•„๋‹Œ ํ‚ค๋ฅผ ํฌ์ธํ„ฐ ์ง์ ‘ ๊ณ„์‚ฐ์œผ๋กœ ์ตœ์ ํ™”ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•œ๋ฐ, eBPF ํ”„๋กœ๊ทธ๋žจ์˜ ์ˆ˜๋ช… ๋™์•ˆ ํฌ์ธํ„ฐ์™€ value_size๊ฐ€ ๊ณ ์ •๋ผ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด ๊ฒ€์ฆ๊ธฐ/JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ array_map_lookup_elem()์„ '์ธ๋ผ์ธ'์œผ๋กœ ๋งŒ๋“ค๋ฉด์„œ๋„ ์—ฌ์ „ํžˆ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ด ๋งต์— ๋™์‹œ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ชจ๋“  ๋ฐฐ์—ด ํ•ญ๋ชฉ๋“ค์€ ์‚ฌ์ „ ํ• ๋‹น๋˜๋ฉฐ ์ดˆ๊ธฐํ™” ์‹œ์ ์— 0์œผ๋กœ ์ดˆ๊ธฐํ™” ๋œ๋‹ค.

  • ํ‚ค๋Š” ๋ฐฐ์—ด ์ƒ‰์ธ์ด๋ฉฐ ์ •ํ™•ํžˆ 4๋ฐ”์ดํŠธ์—ฌ์•ผ ํ•œ๋‹ค.

  • map_delete_elem()์ด EINVAL ์˜ค๋ฅ˜๋กœ ์‹คํŒจํ•œ๋‹ค. ํ•ญ๋ชฉ๋“ค์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • map_update_elem()์ด ๋น„์›์ž์  ๋ฐฉ์‹์œผ๋กœ ํ•ญ๋ชฉ์„ ๊ต์ฒดํ•œ๋‹ค. ์›์ž์  ๊ฐฑ์‹ ์„ ์›ํ•˜๋ฉด ํ•ด์‹œ ํ…Œ์ด๋ธ” ๋งต์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐฐ์—ด์—์„œ๋„ ๊ฐ€๋Šฅํ•œ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ, 32๋น„ํŠธ ๋ฐ 64๋น„ํŠธ ์›์ž ์นด์šดํ„ฐ์— ์›์ž์ ์ธ ๋‚ด์žฅ __sync_fetch_and_add()๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐ’์ด ๋‹จ์ผ ์นด์šดํ„ฐ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค๋ฉด ๊ฐ’ ์ „์ฒด์— ์ ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—ฌ๋Ÿฌ ์นด์šดํ„ฐ๋ฅผ ๋‹ด์€ ๊ตฌ์กฐ์ฒด์ธ ๊ฒฝ์šฐ์—๋Š” ๊ฐœ๋ณ„ ์นด์šดํ„ฐ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ์ด๋ฒคํŠธ ํ•ฉ์‚ฐ ๋ฐ ๊ณ„์ˆ˜์— ์ข…์ข… ์œ ์šฉํ•˜๋‹ค.

๋ฐฐ์—ด ๋งต์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • eBPF "์ „์—ญ" ๋ณ€์ˆ˜: ํ•œ ํ•ญ๋ชฉ์งœ๋ฆฌ ๋ฐฐ์—ด์— ํ‚ค๋ฅผ (์ƒ‰์ธ) 0์œผ๋กœ ํ•˜๊ณ  ๊ฐ’์„ '์ „์—ญ' ๋ณ€์ˆ˜๋“ค์˜ ์ง‘ํ•ฉ์œผ๋กœ ํ•ด์„œ eBPF ํ”„๋กœ๊ทธ๋žจ์ด ์ด๋ฅผ ์ด์šฉํ•ด ์ด๋ฒคํŠธ ๊ฐ„์— ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ณ ์ • ํ•ญ๋ชฉ๋“ค์— ์ถ”์  ์ด๋ฒคํŠธ ํ•ฉ์‚ฐํ•ด ๋„ฃ๊ธฐ.

  • ํŒจํ‚ท ์ˆ˜๋‚˜ ํŒจํ‚ท ํฌ๊ธฐ ๊ฐ™์€ ๋„คํŠธ์›Œํ‚น ์ด๋ฒคํŠธ ๊ณ„์ˆ˜.

BPF_MAP_TYPE_PROG_ARRAY (๋ฆฌ๋ˆ…์Šค 4.2๋ถ€ํ„ฐ)

ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด ๋งต์€ ํŠน๋ณ„ํ•œ ์ข…๋ฅ˜์˜ ๋ฐฐ์—ด ๋งต์ธ๋ฐ, ๊ฐ’์œผ๋กœ ๋‹ค๋ฅธ eBPF ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋งŒ ๋‹ด๋Š”๋‹ค. ๋”ฐ๋ผ์„œ key_size์™€ value_size ๋ชจ๋‘ ์ •ํ™•ํžˆ 4๋ฐ”์ดํŠธ์—ฌ์•ผ ํ•œ๋‹ค. ์ด ๋งต์€ bpf_tail_call() ํ—ฌํผ์™€ ๊ฒฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

์ด๊ฒŒ ๋œปํ•˜๋Š” ๋ฐ”๋Š” ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด ๋งต์ด ์žˆ๋Š” eBPF ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„ ์ชฝ์—์„œ ๋‹ค์Œ์„ ํ˜ธ์ถœํ•˜์—ฌ ์ž๊ธฐ ํ”„๋กœ๊ทธ๋žจ ํ๋ฆ„์„ ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด ์Šฌ๋กฏ์— ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ํ๋ฆ„์œผ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

void bpf_tail_call(void *context, void *prog_map,
                   unsigned int index);

์ด ๋ฐฐ์—ด์„ ๋‹ค๋ฅธ eBPF ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ๊ฐ€๋Š” ์ผ์ข…์˜ ์ ํ”„ ํ…Œ์ด๋ธ”๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ˜ธ์ถœ๋œ ํ”„๋กœ๊ทธ๋žจ์€ ๊ฐ™์€ ์Šคํƒ์„ ์žฌ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ์ƒˆ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ ํ”„๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋‚˜๋ฉด ์ด์ „ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ๋Š” ๋” ์ด์ƒ ๋Œ์•„์˜ค์ง€ ์•Š๋Š”๋‹ค.

(๋งต ์Šฌ๋กฏ์— ์œ ํšจํ•œ ํ”„๋กœ๊ทธ๋žจ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ์—†๊ฑฐ๋‚˜, ์ง€์ •ํ•œ ๊ฒ€์ƒ‰ ์ƒ‰์ธ/ํ‚ค๊ฐ€ ๋ฒ”์œ„ ๋ฐ–์ด๊ฑฐ๋‚˜, ํ˜ธ์ถœ ๊นŠ์ด ์ œํ•œ 32๋ฒˆ์„ ์ดˆ๊ณผํ•ด์„œ) ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด์˜ ์ฃผ์–ด์ง„ ์ƒ‰์ธ์—์„œ eBPF ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ์„ ์ˆ˜ ์—†์œผ๋ฉด ํ˜„์žฌ eBPF ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์„ ๊ณ„์†ํ•œ๋‹ค. ์ด ๋™์ž‘ ๋ฐฉ์‹์„ ์ด์šฉํ•ด ๊ธฐ๋ณธ ๊ฒฝ์šฐ๋กœ ๋–จ์–ด์ง€๋Š” ๊ฒƒ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ ๋ฐฐ์—ด ๋งต์ด ์œ ์šฉํ•œ ๊ฒฝ์šฐ๋กœ ์ถ”์ ์ด๋‚˜ ๋„คํŠธ์›Œํ‚น์ด ์žˆ๋Š”๋ฐ, ๊ฐœ๋ณ„ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด๋‚˜ ํ”„๋กœํ† ์ฝœ์„ ๋ณ„๊ฐœ์˜ ํ•˜์œ„ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‹ค๋ฃจ๊ณ  ์‹๋ณ„์ž๋ฅผ ๋งต ์ƒ‰์ธ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ ๋‹จ์ผ eBPF ํ”„๋กœ๊ทธ๋žจ์˜ ์ตœ๋Œ€ ์ธ์ŠคํŠธ๋Ÿญ์…˜ ์ˆ˜ ์ œํ•œ์„ ๋„˜์–ด์„ค ์ˆ˜ ์žˆ๊ธฐ๋„ ํ•œ๋‹ค. ๊ฐ€๋ณ€์ ์ธ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ๋ฐ๋ชฌ์ด ์˜ˆ๋ฅผ ๋“ค์–ด ์ „์—ญ ์ •์ฑ…์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ๋Ÿฐํƒ€์ž„์— ์›์ž์ ์œผ๋กœ ๊ฐœ๋ณ„ ํ•˜์œ„ ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ์ƒˆ ๋ฒ„์ „์œผ๋กœ ๊ต์ฒดํ•˜์—ฌ ์ „์ฒด ํ”„๋กœ๊ทธ๋žจ ๋™์ž‘์„ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

eBPF ํ”„๋กœ๊ทธ๋žจ

BPF_PROG_LOAD ๋ช…๋ น์„ ์‚ฌ์šฉํ•ด eBPF ํ”„๋กœ๊ทธ๋žจ์„ ์ปค๋„๋กœ ์ ์žฌํ•œ๋‹ค. ์ด ๋ช…๋ น์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ ๊ทธ eBPF ํ”„๋กœ๊ทธ๋žจ์— ์—ฐ๊ณ„๋œ ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์ด๋‹ค.

char bpf_log_buf[LOG_BUF_SIZE];

int
bpf_prog_load(enum bpf_prog_type type,
              const struct bpf_insn *insns, int insn_cnt,
              const char *license)
{
    union bpf_attr attr = {
        .prog_type = type,
        .insns     = ptr_to_u64(insns),
        .insn_cnt  = insn_cnt,
        .license   = ptr_to_u64(license),
        .log_buf   = ptr_to_u64(bpf_log_buf),
        .log_size  = LOG_BUF_SIZE,
        .log_level = 1,
    };

    return bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
}

prog_type์€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜๋“ค ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

enum bpf_prog_type {
    BPF_PROG_TYPE_UNSPEC,        /* 0์€ ์œ ํšจํ•˜์ง€ ์•Š์€
                                    ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜๋กœ ์˜ˆ์•ฝ */
    BPF_PROG_TYPE_SOCKET_FILTER,
    BPF_PROG_TYPE_KPROBE,
    BPF_PROG_TYPE_SCHED_CLS,
    BPF_PROG_TYPE_SCHED_ACT,
};

eBPF ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์•„๋ž˜๋ฅผ ๋ณด๋ผ.

bpf_attr์˜ ๋‚˜๋จธ์ง€ ๋น„ํŠธ๋“ค์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•œ๋‹ค.

  • insns๋Š” struct bpf_insn ์ธ์ŠคํŠธ๋Ÿญ์…˜์˜ ๋ฐฐ์—ด์ด๋‹ค.

  • insn_cnt๋Š” insns๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ”„๋กœ๊ทธ๋žจ ๋‚ด ์ธ์ŠคํŠธ๋Ÿญ์…˜ ๊ฐœ์ˆ˜์ด๋‹ค.

  • license๋Š” ๋ผ์ด์„ ์Šค ๋ฌธ์ž์—ด์ด๋ฉฐ, gpl_only๋กœ ํ‘œ์‹œ๋œ ํ—ฌํผ ํ•จ์ˆ˜๋“ค์„ ํ˜ธ์ถœํ•˜๋ ค๋ฉด GPL ํ˜ธํ™˜์ด์–ด์•ผ ํ•œ๋‹ค. (๋ผ์ด์„ ์Šค ๊ทœ์น™์ด ์ปค๋„ ๋ชจ๋“ˆ๊ณผ ๊ฐ™์œผ๋ฏ€๋กœ "Dual BSD/GPL" ๊ฐ™์€ ์ด์ค‘ ๋ผ์ด์„ ์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.)

  • log_buf๋Š” ํ˜ธ์ถœ์ž๊ฐ€ ํ• ๋‹นํ•œ ๋ฒ„ํผ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์ด๋ฉฐ ์ปค๋„ ๋‚ด ๊ฒ€์ฆ๊ธฐ๊ฐ€ ์—ฌ๊ธฐ์— ๊ฒ€์ฆ ๋กœ๊ทธ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ๋กœ๊ทธ๋Š” ์—ฌ๋Ÿฌ ํ–‰์˜ ๋ฌธ์ž์—ด์ด๋ฉฐ ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ์ž๊ฐ€ ์ด๋ฅผ ํ™•์ธํ•˜์—ฌ ๊ฒ€์ฆ๊ธฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ทธ eBPF ํ”„๋กœ๊ทธ๋žจ์ด ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ฒ€์ฆ๊ธฐ๊ฐ€ ๋ฐœ์ „ํ•จ์— ๋”ฐ๋ผ ์ถœ๋ ฅ ํ˜•์‹์ด ์–ธ์ œ๋“  ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค.

  • log_size๋Š” log_buf๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฒ„ํผ์˜ ํฌ๊ธฐ์ด๋‹ค. ๋ฒ„ํผ ํฌ๊ธฐ๊ฐ€ ๊ฒ€์ฆ๊ธฐ ๋ฉ”์‹œ์ง€๋ฅผ ๋ชจ๋‘ ๋‹ด๊ธฐ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฉด -1์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  errno๋ฅผ ENOSPC๋กœ ์„ค์ •ํ•œ๋‹ค.

  • log_level์€ ๊ฒ€์ฆ๊ธฐ์˜ ์ถœ๋ ฅ ์ƒ์„ธ ์ •๋„์ด๋‹ค. 0 ๊ฐ’์€ ๊ฒ€์ฆ๊ธฐ๊ฐ€ ๋กœ๊ทธ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๋œป์ด๋‹ค. ์ด ๊ฒฝ์šฐ log_buf๊ฐ€ NULL ํฌ์ธํ„ฐ์—ฌ์•ผ ํ•˜๊ณ  log_size๊ฐ€ 0์ด์–ด์•ผ ํ•œ๋‹ค.

BPF_PROG_LOAD๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ์— close(2)๋ฅผ ์ ์šฉํ•˜๋ฉด ๊ทธ eBPF ํ”„๋กœ๊ทธ๋žจ์„ ์ œ๊ฑฐํ•˜๊ฒŒ ๋œ๋‹ค. (ํ•˜์ง€๋งŒ NOTES๋ฅผ ๋ณด๋ผ.)

eBPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋งต์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ eBPF ํ”„๋กœ๊ทธ๋žจ๋“ค ์‚ฌ์ด์—์„œ, ๊ทธ๋ฆฌ๊ณ  eBPF ํ”„๋กœ๊ทธ๋žจ๊ณผ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ ์‚ฌ์ด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•˜๋Š” ๋ฐ ๋งต์„ ์“ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด eBPF ํ”„๋กœ๊ทธ๋žจ์ด (kprobe, ํŒจํ‚ท ๊ฐ™์€) ๋‹ค์–‘ํ•œ ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ ์„œ ๋งต์— ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๊ณ , ๊ทธ๋Ÿฌ๋ฉด ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ๊ทธ ๋งต์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋Œ€๋กœ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ํ”„๋กœ๊ทธ๋žจ์ด ๋งต์„ ์„ค์ • ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งต์„ ์–ด๋–ค ๊ฐ’๋“ค๋กœ ์ฑ„์šฐ๋ฉด eBPF ํ”„๋กœ๊ทธ๋žจ์ด ๊ทธ๊ฑธ ํ™•์ธํ•ด์„œ ๊ทธ ๊ฐ’์— ๋”ฐ๋ผ ๋„์ค‘์— ๋™์ž‘ ๋ฐฉ์‹์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

eBPF ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜

eBPF ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜(prog_type)๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋„ ํ—ฌํผ ํ•จ์ˆ˜๋“ค์˜ ์ง‘ํ•ฉ์„ ๊ฒฐ์ •ํ•œ๋‹ค. ๋˜ํ•œ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜๊ฐ€ ํ”„๋กœ๊ทธ๋žจ ์ž…๋ ฅ(๋ฌธ๋งฅ)์„, ์ฆ‰ (eBPF ํ”„๋กœ๊ทธ๋žจ์—๊ฒŒ ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ์ „๋‹ฌ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ฉ์–ด๋ฆฌ์ธ) struct bpf_context์˜ ํ˜•์‹์„ ๊ฒฐ์ •ํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์˜ ํ—ฌํผ ํ•จ์ˆ˜ ์ง‘ํ•ฉ์€ ์†Œ์ผ“ ํ•„ํ„ฐ ํ”„๋กœ๊ทธ๋žจ๊ณผ ๊ฐ™์ง€ ์•Š๋‹ค. (๋ฌผ๋ก  ์ผ๋ถ€ ํ—ฌํผ๋“ค์€ ๊ณตํ†ต์ผ ์ˆ˜ ์žˆ๋‹ค.) ๋˜ ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์˜ ์ž…๋ ฅ(๋ฌธ๋งฅ)์€ ๋ ˆ์ง€์Šคํ„ฐ ๊ฐ’๋“ค์˜ ์ง‘ํ•ฉ์ธ ๋ฐ˜๋ฉด ์†Œ์ผ“ ํ•„ํ„ฐ์—์„œ๋Š” ๋„คํŠธ์›Œํฌ ํŒจํ‚ท์ด๋‹ค.

์–ด๋–ค ์ข…๋ฅ˜์˜ eBPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•จ์ˆ˜๋“ค์˜ ์ง‘ํ•ฉ์€ ํ–ฅํ›„ ์ปค์งˆ ์ˆ˜๋„ ์žˆ๋‹ค.

๋‹ค์Œ ์ข…๋ฅ˜์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์ง€์›ํ•œ๋‹ค.

BPF_PROG_TYPE_SOCKET_FILTER (๋ฆฌ๋ˆ…์Šค 3.19๋ถ€ํ„ฐ)

ํ˜„์žฌ BPF_PROG_TYPE_SOCKET_FILTER์—์„œ ์“ธ ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

bpf_map_lookup_elem(map_fd, void *key)
                    /* map_fd์—์„œ ํ‚ค ๊ฒ€์ƒ‰ */
bpf_map_update_elem(map_fd, void *key, void *value)
                    /* ํ‚ค/๊ฐ’ ๊ฐฑ์‹  */
bpf_map_delete_elem(map_fd, void *key)
                    /* map_fd์—์„œ ํ‚ค ์‚ญ์ œ */

bpf_context ์ธ์ž๋Š” struct __sk_buff์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์ด๋‹ค.

BPF_PROG_TYPE_KPROBE (๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ)
[์ž‘์„ฑ ์˜ˆ์ •]
BPF_PROG_TYPE_SCHED_CLS (๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ)
[์ž‘์„ฑ ์˜ˆ์ •]
BPF_PROG_TYPE_SCHED_ACT (๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ)
[์ž‘์„ฑ ์˜ˆ์ •]

์ด๋ฒคํŠธ

ํ”„๋กœ๊ทธ๋žจ์„ ์ ์žฌํ•˜๊ณ  ๋‚˜๋ฉด ์ด๋ฅผ ์ด๋ฒคํŠธ์— ์—ฐ๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‹ค์–‘ํ•œ ์ปค๋„ ์„œ๋ธŒ์‹œ์Šคํ…œ๋งˆ๋‹ค ์ด๋ฅผ ์œ„ํ•œ ๊ฐ์ž์˜ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

๋ฆฌ๋ˆ…์Šค 3.19๋ถ€ํ„ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•˜๋ฉด ์•ž์„œ socket(2) ํ˜ธ์ถœ๋กœ ์ƒ์„ฑํ•œ ์†Œ์ผ“ sockfd์— ํ”„๋กœ๊ทธ๋žจ prog_fd๋ฅผ ๋ถ™์ด๊ฒŒ ๋œ๋‹ค.

setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_BPF,
           &prog_fd, sizeof(prog_fd));

๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•˜์—ฌ ์•ž์„œ perf_event_open(2) ํ˜ธ์ถœ๋กœ ์ƒ์„ฑํ•œ perf ์ด๋ฒคํŠธ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ event_fd์— ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ prog_fd๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” eBPF ํ”„๋กœ๊ทธ๋žจ์„ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.

ioctl(event_fd, PERF_EVENT_IOC_SET_BPF, prog_fd);

EXAMPLES

/* bpf+์†Œ์ผ“ ์˜ˆ์‹œ:
 * 1. 256๊ฐœ ํ•ญ๋ชฉ์˜ ๋ฐฐ์—ด ๋งต ์ƒ์„ฑ
 * 2. ์ˆ˜์‹  ํŒจํ‚ท ์ˆ˜๋ฅผ ์„ธ๋Š” ํ”„๋กœ๊ทธ๋žจ ์ ์žฌ
 *    r0 = skb->data[ETH_HLEN + offsetof(struct iphdr, protocol)]
 *    map[r0]++
 * 3. setsockopt()๋ฅผ ํ†ตํ•ด raw ์†Œ์ผ“์— prog_fd ์—ฐ๊ณ„
 * 4. ๋งค์ดˆ๋งˆ๋‹ค ์ˆ˜์‹ ํ•œ TCP/UDP ํŒจํ‚ท ๊ฐœ์ˆ˜ ์ถœ๋ ฅ
 */
int
main(int argc, char **argv)
{
    int sock, map_fd, prog_fd, key;
    long long value = 0, tcp_cnt, udp_cnt;

    map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key),
                            sizeof(value), 256);
    if (map_fd < 0) {
        printf("failed to create map '%s'\n", strerror(errno));
        /* ์•„๋งˆ ๋ฃจํŠธ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์•„์„œ */
        return 1;
    }

    struct bpf_insn prog[] = {
        BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),        /* r6 = r1 */
        BPF_LD_ABS(BPF_B, ETH_HLEN + offsetof(struct iphdr, protocol)),
                                /* r0 = ip->proto */
        BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
                                /* *(u32 *)(fp - 4) = r0 */
        BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),       /* r2 = fp */
        BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),      /* r2 = r2 - 4 */
        BPF_LD_MAP_FD(BPF_REG_1, map_fd),           /* r1 = map_fd */
        BPF_CALL_FUNC(BPF_FUNC_map_lookup_elem),
                                /* r0 = map_lookup(r1, r2) */
        BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
                                /* if (r0 == 0) goto pc+2 */
        BPF_MOV64_IMM(BPF_REG_1, 1),                /* r1 = 1 */
        BPF_XADD(BPF_DW, BPF_REG_0, BPF_REG_1, 0, 0),
                                /* lock *(u64 *) r0 += r1 */
        BPF_MOV64_IMM(BPF_REG_0, 0),                /* r0 = 0 */
        BPF_EXIT_INSN(),                            /* return r0 */
    };

    prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, prog,
                            sizeof(prog) / sizeof(prog[0]), "GPL");

    sock = open_raw_sock("lo");

    assert(setsockopt(sock, SOL_SOCKET, SO_ATTACH_BPF, &prog_fd,
                      sizeof(prog_fd)) == 0);

    for (;;) {
        key = IPPROTO_TCP;
        assert(bpf_lookup_elem(map_fd, &key, &tcp_cnt) == 0);
        key = IPPROTO_UDP;
        assert(bpf_lookup_elem(map_fd, &key, &udp_cnt) == 0);
        printf("TCP %lld UDP %lld packets\n", tcp_cnt, udp_cnt);
        sleep(1);
    }

    return 0;
}

์ปค๋„ ์†Œ์Šค ํŠธ๋ฆฌ์˜ samples/bpf ๋””๋ ‰ํ„ฐ๋ฆฌ์— ์™„์ „ํ•œ ๋™์ž‘ ์ฝ”๋“œ๋“ค์ด ์ข€ ์žˆ๋‹ค.

RETURN VALUE

์„ฑ๊ณต ํ˜ธ์ถœ ์‹œ ๋ฐ˜ํ™˜ ๊ฐ’์€ ์ž‘์—…์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค.

BPF_MAP_CREATE
eBPF ๋งต์— ์—ฐ๊ณ„๋œ ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ.
BPF_PROG_LOAD
eBPF ํ”„๋กœ๊ทธ๋žจ์— ์—ฐ๊ณ„๋œ ์ƒˆ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ.
๋‹ค๋ฅธ ๋ช…๋ น๋“ค
0.

์˜ค๋ฅ˜ ์‹œ -1์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ errno๋ฅผ ์ ์ ˆํžˆ ์„ค์ •ํ•œ๋‹ค.

ERRORS

E2BIG
eBPF ํ”„๋กœ๊ทธ๋žจ์ด ๋„ˆ๋ฌด ํฌ๊ฑฐ๋‚˜ ๋งต์ด max_entries ์ œํ•œ(์ตœ๋Œ€ ํ•ญ๋ชฉ ์ˆ˜)์— ๋„๋‹ฌํ–ˆ๋‹ค.
EACCES
BPF_PROG_LOAD์—์„œ, ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ ์ธ์ŠคํŠธ๋Ÿญ์…˜์ด ์œ ํšจํ•˜์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์ด ์•ˆ์ „ํ•˜์ง€ ์•Š์•„ ๋ณด์—ฌ์„œ ๊ฑฐ๋ถ€๋˜์—ˆ๋‹ค. ํ—ˆ์šฉ ์•ˆ ๋œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด๋‚˜ ์ดˆ๊ธฐํ™” ์•ˆ ๋œ ์Šคํƒ/๋ ˆ์ง€์Šคํ„ฐ์— ์ ‘๊ทผํ•ด์„œ์ผ ์ˆ˜๋„ ์žˆ๊ณ  ํ•จ์ˆ˜ ์ œ์•ฝ์ด ์‹ค์ œ ์ข…๋ฅ˜์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์•„์„œ์ผ ์ˆ˜๋„ ์žˆ๊ณ  ์ •๋ ฌ ์•ˆ ๋œ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด ์žˆ์–ด์„œ์ผ ์ˆ˜๋„ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ log_level = 1๋กœ bpf()๋ฅผ ๋‹ค์‹œ ํ˜ธ์ถœํ•ด์„œ ๊ฒ€์ฆ๊ธฐ๊ฐ€ ์ œ์‹œํ•œ ๊ตฌ์ฒด์  ์ด์œ ๋ฅผ log_buf์—์„œ ํ™•์ธํ•ด ๋ณด๋Š” ๊ฒŒ ์ข‹๋‹ค.
EBADF
fd๊ฐ€ ์—ด๋ฆฐ ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ์•„๋‹ˆ๋‹ค.
EFAULT
ํฌ์ธํ„ฐ๋“ค(key, value, log_buf, insns) ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์ฃผ์†Œ ๊ณต๊ฐ„ ๋ฐ–์ด๋‹ค.
EINVAL
cmd์— ์ง€์ •ํ•œ ๊ฐ’์„ ์ด ์ปค๋„์ด ์•Œ์ง€ ๋ชปํ•œ๋‹ค.
EINVAL
BPF_MAP_CREATE์—์„œ, map_type์ด๋‚˜ ์†์„ฑ์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค.
EINVAL
BPF_MAP_*_ELEM ๋ช…๋ น๋“ค์—์„œ, union bpf_attr์˜ ํ•„๋“œ๋“ค ์ค‘ ์ผ๋ถ€๋ฅผ ์ด ๋ช…๋ น์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋ฐ 0์œผ๋กœ ์„ค์ •๋ผ ์žˆ์ง€ ์•Š๋‹ค.
EINVAL
BPF_PROG_LOAD์—์„œ, ์œ ํšจํ•˜์ง€ ์•Š์€ ํ”„๋กœ๊ทธ๋žจ ์ ์žฌ ์‹œ๋„๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ์ธ์‹ ๋ถˆ๊ฐ€๋Šฅํ•œ ์ธ์ŠคํŠธ๋Ÿญ์…˜, ์˜ˆ์•ฝ๋œ ํ•„๋“œ ์‚ฌ์šฉ, ๋ฒ”์œ„ ๋ฐ–์œผ๋กœ์˜ ์ ํ”„, ๋ฌดํ•œ ๋ฃจํ”„, ์•Œ ์ˆ˜ ์—†๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ ๋•Œ๋ฌธ์— eBPF ํ”„๋กœ๊ทธ๋žจ์ด ์œ ํšจํ•˜์ง€ ์•Š๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
ENOENT
BPF_MAP_LOOKUP_ELEM์ด๋‚˜ BPF_MAP_DELETE_ELEM์—์„œ, ํ•ด๋‹น key๋ฅผ ๊ฐ€์ง„ ํ•ญ๋ชฉ์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
ENOMEM
์ถฉ๋ถ„ํ•œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์—†๋‹ค.
EPERM
์ถฉ๋ถ„ํ•œ ํŠน๊ถŒ ์—†์ด (CAP_SYS_ADMIN ์—ญ๋Šฅ ์—†์ด) ํ˜ธ์ถœ์„ ํ–ˆ๋‹ค.

VERSIONS

๋ฆฌ๋ˆ…์Šค 3.18์—์„œ bpf() ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด ์ฒ˜์Œ ๋“ฑ์žฅํ–ˆ๋‹ค.

CONFORMING TO

bpf() ์‹œ์Šคํ…œ ํ˜ธ์ถœ์€ ๋ฆฌ๋ˆ…์Šค ์ „์šฉ์ด๋‹ค.

NOTES

ํ˜„์žฌ ๊ตฌํ˜„์—์„œ๋Š” ๋ชจ๋“  bpf() ๋ช…๋ น์—์„œ ํ˜ธ์ถœ์ž์—๊ฒŒ CAP_SYS_ADMIN ์—ญ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค.

eBPF ๊ฐ์ฒด(๋งต, ํ”„๋กœ๊ทธ๋žจ)๋ฅผ ํ”„๋กœ์„ธ์Šค๋“ค ๊ฐ„์— ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด fork(2) ํ›„์— ์ž์‹์ด ๊ฐ™์€ eBPF ๊ฐ์ฒด๋“ค์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋“ค์„ ๋ฌผ๋ ค๋ฐ›๋Š”๋‹ค. ๋”๋ถˆ์–ด eBPF ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ์œ ๋‹‰์Šค ๋„๋ฉ”์ธ ์†Œ์ผ“์„ ํ†ตํ•ด ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  eBPF ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๋ฅผ ํ‰์ƒ์‹œ์ฒ˜๋Ÿผ dup(2)์ด๋‚˜ ๋น„์Šทํ•œ ํ˜ธ์ถœ์„ ์ด์šฉํ•ด ๋ณต์ œํ•  ์ˆ˜ ์žˆ๋‹ค. eBPF ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ชจ๋“  ํŒŒ์ผ ๋””์Šคํฌ๋ฆฝํ„ฐ๊ฐ€ ๋‹ซํžŒ ํ›„์—๋งŒ ๊ทธ ๊ฐ์ฒด๊ฐ€ ํ• ๋‹น ํ•ด์ œ๋œ๋‹ค.

eBPF ํ”„๋กœ๊ทธ๋žจ์„ ์ œ์•ฝ๋œ C๋กœ ์ž‘์„ฑํ•ด์„œ (clang ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ด์šฉํ•ด) eBPF ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ์ œ์•ฝ๋œ C์—๋Š” ๋ฃจํ”„, ์ „์—ญ ๋ณ€์ˆ˜, ๊ฐ€๋ณ€ ์ธ์ž ํ•จ์ˆ˜, ๋ถ€๋™ ์†Œ์ˆ˜์ , ํ•จ์ˆ˜ ์ธ์ž๋กœ ๊ตฌ์กฐ์ฒด ์ „๋‹ฌํ•˜๊ธฐ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๋“ค์ด ๋น ์ ธ ์žˆ๋‹ค. ์ปค๋„ ์†Œ์Šค ํŠธ๋ฆฌ์˜ samples/bpf/*_kern.c ํŒŒ์ผ๋“ค์—์„œ ์˜ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ปค๋„์—๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด eBPF ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ๋„ค์ดํ‹ฐ๋ธŒ ๋จธ์‹  ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” JIT(just-in-time) ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํฌํ•จ๋ผ ์žˆ๋‹ค. ๋ฆฌ๋ˆ…์Šค 4.15 ์ „์˜ ์ปค๋„์—์„œ๋Š” JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊บผ์ ธ ์žˆ์œผ๋ฉฐ /proc/sys/net/core/bpf_jit_enable ํŒŒ์ผ์— ๋‹ค์Œ ์ •์ˆ˜ ๋ฌธ์ž์—ด ์ค‘ ํ•˜๋‚˜๋ฅผ ์จ๋„ฃ์–ด์„œ ๋™์ž‘ ๋ฐฉ์‹์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.

0
JIT ์ปดํŒŒ์ผ ๋„๊ธฐ. (๊ธฐ๋ณธ๊ฐ’)
1
์ผ๋ฐ˜ ์ปดํŒŒ์ผ.
2
๋””๋ฒ„๊น… ๋ชจ๋“œ. ์ƒ์„ฑ๋œ ๋ช…๋ น ์ฝ”๋“œ๋ฅผ ์‹ญ์œก์ง„์ˆ˜๋กœ ์ปค๋„ ๋กœ๊ทธ๋กœ ์ฐ๋Š”๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ปค๋„ ์†Œ์Šค ํŠธ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” tools/net/bpf_jit_disasm.c ํ”„๋กœ๊ทธ๋žจ์„ ์ด์šฉํ•ด ๊ทธ ๋ช…๋ น ์ฝ”๋“œ๋ฅผ ์—ญ์–ด์…ˆ๋ธ” ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฆฌ๋ˆ…์Šค 4.15๋ถ€ํ„ฐ ์ปค๋„ ๊ตฌ์„ฑ์— CONFIG_BPF_JIT_ALWAYS_ON ์˜ต์…˜์„ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํ•ญ์ƒ ์ผœ์ง€๋ฉฐ bpf_jit_enable์€ 1๋กœ ์ดˆ๊ธฐํ™” ๋˜๊ณ  ๋ณ€๊ฒฝ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. (์ด ์ปค๋„ ๊ตฌ์„ฑ ์˜ต์…˜์€ BPF ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋Š” ์–ด๋А ์ŠคํŽ™ํ„ฐ ๊ณต๊ฒฉ์— ๋Œ€ํ•œ ์™„ํ™”์ฑ…์œผ๋กœ ๋‚˜์˜จ ๊ฒƒ์ด๋‹ค.)

ํ˜„์žฌ ๋‹ค์Œ ์•„ํ‚คํ…์ฒ˜๋“ค์—์„œ eBPF JIT ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • x86-64 (๋ฆฌ๋ˆ…์Šค 3.18๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.0๋ถ€ํ„ฐ)
  • ARM32 (๋ฆฌ๋ˆ…์Šค 3.18๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.4๋ถ€ํ„ฐ)
  • SPARC 32 (๋ฆฌ๋ˆ…์Šค 3.18๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.5๋ถ€ํ„ฐ)
  • ARM-64 (๋ฆฌ๋ˆ…์Šค 3.18๋ถ€ํ„ฐ)
  • s390 (๋ฆฌ๋ˆ…์Šค 4.1๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.7๋ถ€ํ„ฐ)
  • PowerPC 64 (๋ฆฌ๋ˆ…์Šค 4.8๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.1๋ถ€ํ„ฐ)
  • SPARC 64 (๋ฆฌ๋ˆ…์Šค 4.12๋ถ€ํ„ฐ)
  • x86-32 (๋ฆฌ๋ˆ…์Šค 4.18๋ถ€ํ„ฐ)
  • MIPS 64 (๋ฆฌ๋ˆ…์Šค 4.18๋ถ€ํ„ฐ, cBPF๋Š” ๋ฆฌ๋ˆ…์Šค 3.16๋ถ€ํ„ฐ)
  • riscv (๋ฆฌ๋ˆ…์Šค 5.1๋ถ€ํ„ฐ)

SEE ALSO

seccomp(2), bpf-helpers(7), socket(7), tc(8), tc-bpf(8)

์ปค๋„ ์†Œ์Šค ํŒŒ์ผ Documentation/networking/filter.txt์—์„œ ์ „ํ†ต์  BPF์™€ ํ™•์žฅ BPF ๋ชจ๋‘๋ฅผ ์„ค๋ช…ํ•œ๋‹ค.


2019-08-02

โš ๏ธ **GitHub.com Fallback** โš ๏ธ