์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

ํƒœ์ดˆ์— BPF๋ผ๋Š” ๊ธฐ์ˆ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๋…€๋ฅผ ๋ฐ”๋ผ๋ณด์•˜๋‹ค ์ด์ „, ์ด ์‹œ๋ฆฌ์ฆˆ์˜ ๊ตฌ์•ฝ์„ฑ์„œ ๊ธฐ์‚ฌ. 2013๋…„์—๋Š” Alexei Starovoitov์™€ Daniel Borkman์˜ ๋…ธ๋ ฅ์„ ํ†ตํ•ด ์ตœ์‹  64๋น„ํŠธ ์‹œ์Šคํ…œ์— ์ตœ์ ํ™”๋œ ํ–ฅ์ƒ๋œ ๋ฒ„์ „์ด ๊ฐœ๋ฐœ๋˜์–ด Linux ์ปค๋„์— ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์€ ๊ฐ„๋‹จํžˆ Internal BPF๋ผ๊ณ  ๋ถˆ๋ ธ๋‹ค๊ฐ€ Extended BPF๋กœ ์ด๋ฆ„์ด ๋ฐ”๋€Œ์—ˆ๊ณ  ๋ช‡ ๋…„์ด ์ง€๋‚œ ์ง€๊ธˆ์€ ๋ชจ๋‘๊ฐ€ ๊ฐ„๋‹จํžˆ BPF๋ผ๊ณ  ๋ถ€๋ฆ…๋‹ˆ๋‹ค.

๋Œ€๋žต์ ์œผ๋กœ ๋งํ•˜๋ฉด BPF๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Linux ์ปค๋„ ๊ณต๊ฐ„์—์„œ ์ž„์˜์˜ ์‚ฌ์šฉ์ž ์ œ๊ณต ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ƒˆ ์•„ํ‚คํ…์ฒ˜๋Š” ๋งค์šฐ ์„ฑ๊ณต์ ์ด์–ด์„œ ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์„ค๋ช…ํ•˜๋ ค๋ฉด XNUMX๊ฐœ์˜ ๊ธฐ์‚ฌ๊ฐ€ ๋” ํ•„์š”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์•„๋ž˜ ์„ฑ๋Šฅ ์ฝ”๋“œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ๊ฐœ๋ฐœ์ž๋“ค์ด ์œ ์ผํ•˜๊ฒŒ ์ž˜ ๋ชปํ•œ ๊ฒƒ์€ ๊ดœ์ฐฎ์€ ๋กœ๊ณ ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.)

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” BPF ๊ฐ€์ƒ ๋จธ์‹ ์˜ ๊ตฌ์กฐ, BPF ์ž‘์—…์„ ์œ„ํ•œ ์ปค๋„ ์ธํ„ฐํŽ˜์ด์Šค, ๊ฐœ๋ฐœ ๋„๊ตฌ ๋ฐ ๊ธฐ์กด ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•˜๊ณ  ๊ฐ„๋‹จํ•œ ๊ฐœ์š”๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. BPF์˜ ์‹ค์ œ ์ ์šฉ์— ๋Œ€ํ•œ ๋” ๊นŠ์€ ์—ฐ๊ตฌ๋ฅผ ์œ„ํ•ด ๋ฏธ๋ž˜์— ํ•„์š”ํ•œ ๋ชจ๋“  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

๊ธฐ์‚ฌ ์š”์•ฝ

BPF ์•„ํ‚คํ…์ฒ˜ ์†Œ๊ฐœ. ๋จผ์ € BPF ์•„ํ‚คํ…์ฒ˜๋ฅผ ์กฐ๊ฐ๋„๋กœ ์‚ดํŽด๋ณด๊ณ  ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฐœ์š”๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

BPF ๊ฐ€์ƒ ๋จธ์‹ ์˜ ๋ ˆ์ง€์Šคํ„ฐ ๋ฐ ๋ช…๋ น ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์ด๋ฏธ ์•„ํ‚คํ…์ฒ˜ ์ „์ฒด์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋ฏ€๋กœ BPF ๊ฐ€์ƒ ๋จธ์‹ ์˜ ๊ตฌ์กฐ๋ฅผ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

BPF ๊ฐ์ฒด์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ, bpffs ํŒŒ์ผ ์‹œ์Šคํ…œ. ์ด ์„น์…˜์—์„œ๋Š” BPF ๊ฐ์ฒด(ํ”„๋กœ๊ทธ๋žจ ๋ฐ ๋งต)์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

bpf ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ๊ตฌ์ถ•๋œ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ์–ด๋Š ์ •๋„ ์ดํ•ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋งˆ์ง€๋ง‰์œผ๋กœ ํŠน์ˆ˜ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpf(2).

ะŸะธัˆะตะผ ะฟั€ะพะณั€ะฐะผะผั‹ BPF ั ะฟะพะผะพั‰ัŒัŽ libbpf. ๋ฌผ๋ก  ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๋ณด๋‹ค ํ˜„์‹ค์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์œ„ํ•ด ํ•ต ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœํ–ˆ์Šต๋‹ˆ๋‹ค. libbpf. ํ›„์† ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉํ•  ๊ธฐ๋ณธ BPF ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ผˆ๋Œ€๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ปค๋„ ๋„์šฐ๋ฏธ. ์—ฌ๊ธฐ์„œ๋Š” BPF ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„ ๋„์šฐ๋ฏธ ๊ธฐ๋Šฅ(๋งต๊ณผ ํ•จ๊ป˜ ๊ธฐ๋ณธ BPF์— ๋น„ํ•ด ์ƒˆ๋กœ์šด BPF์˜ ๊ธฐ๋Šฅ์„ ๊ทผ๋ณธ์ ์œผ๋กœ ํ™•์žฅํ•˜๋Š” ๋„๊ตฌ)์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ด…๋‹ˆ๋‹ค.

BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ง€๋„์— ์•ก์„ธ์Šคํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ์šฐ๋ฆฌ๋Š” ์ง€๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•  ๋งŒํผ ์ถฉ๋ถ„ํžˆ ์•Œ๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์œ„๋Œ€ํ•˜๊ณ  ๋ง‰๊ฐ•ํ•œ ๊ฒ€์ฆ์ž์— ๋Œ€ํ•ด์„œ๋„ ์ž ๊น ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ ๋„๊ตฌ. ์‹คํ—˜์— ํ•„์š”ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ์ปค๋„์„ ์กฐ๋ฆฝํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋„์›€๋ง ์„น์…˜์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก . ์—ฌ๊ธฐ๊นŒ์ง€ ์ฝ์€ ์‚ฌ๋žŒ๋“ค์€ ๊ธฐ์‚ฌ ๋๋ถ€๋ถ„์—์„œ ๋™๊ธฐ๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ๋‹จ์–ด์™€ ๋‹ค์Œ ๊ธฐ์‚ฌ์—์„œ ์ผ์–ด๋‚  ์ผ์— ๋Œ€ํ•œ ๊ฐ„๋žตํ•œ ์„ค๋ช…์„ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ณ„์†๋˜๋Š” ํ•™์Šต์„ ๊ธฐ๋‹ค๋ฆด ์˜์ง€๋‚˜ ๋Šฅ๋ ฅ์ด ์—†๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ์ž์œจ ํ•™์Šต์„ ์œ„ํ•œ ์—ฌ๋Ÿฌ ๋งํฌ๋„ ๋‚˜์—ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

BPF ์•„ํ‚คํ…์ฒ˜ ์†Œ๊ฐœ

BPF ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ณ ๋ คํ•˜๊ธฐ ์ „์— ๋งˆ์ง€๋ง‰์œผ๋กœ (์˜ค) ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํด๋ž˜์‹ BPF๋Š” RISC ๋จธ์‹ ์˜ ์ถœํ˜„์— ๋Œ€์‘ํ•˜์—ฌ ๊ฐœ๋ฐœ๋˜์—ˆ์œผ๋ฉฐ ํšจ์œจ์ ์ธ ํŒจํ‚ท ํ•„ํ„ฐ๋ง ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์•„ํ‚คํ…์ฒ˜๋Š” ๋งค์šฐ ์„ฑ๊ณต์ ์ธ ๊ฒƒ์œผ๋กœ ํŒ๋ช…๋˜์–ด XNUMX๋…„๋Œ€ Berkeley UNIX์—์„œ ํƒ„์ƒํ•˜์—ฌ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ์กด ์šด์˜ ์ฒด์ œ๋กœ ํฌํŒ…๋˜์—ˆ์œผ๋ฉฐ ๋ฏธ์นœ XNUMX๋…„๋Œ€๊นŒ์ง€ ์‚ด์•„๋‚จ์•˜์œผ๋ฉฐ ์—ฌ์ „ํžˆ ์ƒˆ๋กœ์šด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด BPF๋Š” 64๋น„ํŠธ ๋จธ์‹ , ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค์˜ ํŽธ์žฌ์„ฑ ๋ฐ SDN ์ƒ์„ฑ์„ ์œ„ํ•œ ๋„๊ตฌ์— ๋Œ€ํ•œ ํ•„์š”์„ฑ ์ฆ๊ฐ€์— ๋Œ€ํ•œ ๋Œ€์‘์œผ๋กœ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(Software-d์ •๊ตํ•œ n์—ํŠธ์›Œํ‚น). ๊ธฐ์กด BPF์˜ ๊ฐœ์„ ๋œ ๋Œ€์ฒดํ’ˆ์œผ๋กœ ์ปค๋„ ๋„คํŠธ์›Œํฌ ์—”์ง€๋‹ˆ์–ด์— ์˜ํ•ด ๊ฐœ๋ฐœ๋œ ์ƒˆ๋กœ์šด BPF๋Š” ๋ฌธ์ž ๊ทธ๋Œ€๋กœ XNUMX๊ฐœ์›” ํ›„์— Linux ์‹œ์Šคํ…œ์„ ์ถ”์ ํ•˜๋Š” ์–ด๋ ค์šด ์ž‘์—…์—์„œ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋ฐœ๊ฒฌํ–ˆ์œผ๋ฉฐ ์ด์ œ ๋“ฑ์žฅํ•œ ์ง€ XNUMX๋…„์ด ์ง€๋‚ฌ์œผ๋ฏ€๋กœ ๋‹ค์Œ ๊ธฐ์‚ฌ ์ „์ฒด๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ํ”„๋กœ๊ทธ๋žจ์„ ๋‚˜์—ดํ•ด ๋ณด์„ธ์š”.

์žฌ๋ฐŒ๋Š” ์‚ฌ์ง„

๊ธฐ๋ณธ์ ์œผ๋กœ BPF๋Š” ๋ณด์•ˆ์„ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๊ณ  ์ปค๋„ ๊ณต๊ฐ„์—์„œ "์ž„์˜" ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์ƒŒ๋“œ๋ฐ•์Šค ๊ฐ€์ƒ ๋จธ์‹ ์ž…๋‹ˆ๋‹ค. BPF ํ”„๋กœ๊ทธ๋žจ์€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ƒ์„ฑ๋˜๊ณ  ์ปค๋„์— ๋กœ๋“œ๋˜๋ฉฐ ์ผ๋ถ€ ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋กœ์˜ ํŒจํ‚ท ์ „๋‹ฌ, ์ผ๋ถ€ ์ปค๋„ ๊ธฐ๋Šฅ ์‹คํ–‰ ๋“ฑ์ด ์ด๋ฒคํŠธ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŒจํ‚ค์ง€์˜ ๊ฒฝ์šฐ BPF ํ”„๋กœ๊ทธ๋žจ์€ ํŒจํ‚ค์ง€์˜ ๋ฐ์ดํ„ฐ ๋ฐ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•์— ๋”ฐ๋ผ ์ฝ๊ธฐ ๋ฐ ์“ฐ๊ธฐ๋ฅผ ์œ„ํ•ด). ์ปค๋„ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์ปค๋„ ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋“ฑ์„ ํฌํ•จํ•œ ํ•จ์ˆ˜

์ด ๊ณผ์ •์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ์„ , ์–ด์…ˆ๋ธ”๋Ÿฌ๋กœ ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์ธ ํด๋ž˜์‹ BPF์™€์˜ ์ฒซ ๋ฒˆ์งธ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ƒˆ ๋ฒ„์ „์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๊ณ ๊ธ‰ ์–ธ์–ด(์ฃผ๋กœ C)๋กœ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์•„ํ‚คํ…์ฒ˜๊ฐ€ ํ™•์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด BPF ์•„ํ‚คํ…์ฒ˜์šฉ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” llvm์šฉ ๋ฐฑ์—”๋“œ๊ฐ€ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

BPF ์•„ํ‚คํ…์ฒ˜๋Š” ๋ถ€๋ถ„์ ์œผ๋กœ ์ตœ์‹  ๋จธ์‹ ์—์„œ ํšจ์œจ์ ์œผ๋กœ ์‹คํ–‰๋˜๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ปค๋„์— ๋กœ๋“œ๋œ BPF ๋ฐ”์ดํŠธ์ฝ”๋“œ๋Š” JIT ์ปดํŒŒ์ผ๋Ÿฌ(Just In T์ž„). ๋‹ค์Œ์œผ๋กœ, ํด๋ž˜์‹ BPF์—์„œ ํ”„๋กœ๊ทธ๋žจ์€ ๋‹จ์ผ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์˜ ๋งฅ๋ฝ์—์„œ ์ปค๋„์— ๋กœ๋“œ๋˜๊ณ  ์ด๋ฒคํŠธ ์†Œ์Šค์— ์›์ž์ ์œผ๋กœ ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์•„ํ‚คํ…์ฒ˜์—์„œ๋Š” ์ด ์ž‘์—…์ด ๋‘ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ฒซ์งธ, ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ”๋“œ๊ฐ€ ์ปค๋„์— ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. bpf(2)๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚˜์ค‘์— ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋Š” ๋‹ค๋ฅธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๋…์ž๋Š” ์งˆ๋ฌธ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋Ÿฌํ•œ ์ฝ”๋“œ์˜ ์‹คํ–‰ ์•ˆ์ „์„ฑ์€ ์–ด๋–ป๊ฒŒ ๋ณด์žฅ๋ฉ๋‹ˆ๊นŒ? verifier๋ผ๊ณ  ํ•˜๋Š” BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๋Š” ๋‹จ๊ณ„์—์„œ ์‹คํ–‰ ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค(์˜์–ด์—์„œ๋Š” ์ด ๋‹จ๊ณ„๋ฅผ verifier๋ผ๊ณ  ํ•˜๋ฉฐ ๊ณ„์†ํ•ด์„œ ์˜์–ด ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค).

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

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

๊ทธ๋Ÿผ ์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ ๋ฌด์—‡์„ ๋ฐฐ์› ๋‚˜์š”? ์‚ฌ์šฉ์ž๋Š” C๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ณ  ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์ปค๋„์— ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. bpf(2), ๊ฒ€์ฆ์ž์— ์˜ํ•ด ํ™•์ธ๋˜๊ณ  ๊ธฐ๋ณธ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋™์ผํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ํ”„๋กœ๊ทธ๋žจ์„ ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐํ•˜๊ณ  ์‹คํ–‰์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ด์œ ๋กœ ๋ถ€ํŒ…๊ณผ ์—ฐ๊ฒฐ์„ ๋ถ„๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฒซ์งธ, ๊ฒ€์ฆ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์ƒ๋Œ€์ ์œผ๋กœ ๋น„์šฉ์ด ๋งŽ์ด ๋“ค๊ณ  ๋™์ผํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ์—ฌ๋Ÿฌ ๋ฒˆ ๋‹ค์šด๋กœ๋“œํ•จ์œผ๋กœ์จ ์ปดํ“จํ„ฐ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ํ•ฉ๋‹ˆ๋‹ค. ๋‘˜์งธ, ํ”„๋กœ๊ทธ๋žจ์ด ์—ฐ๊ฒฐ๋˜๋Š” ์ •ํ™•ํ•œ ๋ฐฉ์‹์€ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋ฉฐ, XNUMX๋…„ ์ „์— ๊ฐœ๋ฐœ๋œ ํ•˜๋‚˜์˜ "์œ ๋‹ˆ๋ฒ„์„ค" ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ƒˆ๋กœ์šด ์œ ํ˜•์˜ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ง€๊ธˆ์€ ์•„ํ‚คํ…์ฒ˜๊ฐ€ ์„ฑ์ˆ™ํ•ด์ง€๊ณ  ์žˆ์ง€๋งŒ, ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ ˆ๋ฒจ์—์„œ ํ†ตํ•ฉํ•˜๋ ค๋Š” ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. libbpf.)

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

๋งต์€ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค์—์„œ ์•ก์„ธ์Šค๋ฉ๋‹ˆ๋‹ค. bpf(2), ๊ทธ๋ฆฌ๊ณ  ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์—์„œ ์‹คํ–‰๋˜๋Š” BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ. ๋”์šฑ์ด, ๋งต ์ž‘์—…๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์ปค๋„ ๊ธฐ๋Šฅ์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ ํ—ฌํผ๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด BPF ํ”„๋กœ๊ทธ๋žจ์€ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŒจํ‚ท์„ ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ „๋‹ฌํ•˜๊ณ , ์„ฑ๋Šฅ ์ด๋ฒคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ปค๋„ ๊ตฌ์กฐ์— ์•ก์„ธ์Šคํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

์š”์•ฝํ•˜์ž๋ฉด, BPF๋Š” ๊ฒ€์ฆ์ž ํ…Œ์ŠคํŠธ๋ฅผ ๊ฑฐ์นœ ์ž„์˜์˜ ์‚ฌ์šฉ์ž ์ฝ”๋“œ๋ฅผ ์ปค๋„ ๊ณต๊ฐ„์— ๋กœ๋“œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ํ˜ธ์ถœ ๊ฐ„ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๊ณ  ์‚ฌ์šฉ์ž ๊ณต๊ฐ„๊ณผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Ÿฌํ•œ ์œ ํ˜•์˜ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ—ˆ์šฉํ•˜๋Š” ์ปค๋„ ํ•˜์œ„ ์‹œ์Šคํ…œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ์˜ ์กด์žฌ๋กœ ์ธํ•ด BPF๋Š” ์ปค๋„ ํ™•์žฅ์„ ์œ„ํ•œ ๋ณดํŽธ์ ์ธ ๋„๊ตฌ๊ฐ€ ๋˜์—ˆ์œผ๋ฉฐ ์ด๋Š” ์‹ค์ œ๋กœ ํ™•์ธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ ์  ๋” ๋งŽ์€ ์ƒˆ๋กœ์šด ์œ ํ˜•์˜ ํ”„๋กœ๊ทธ๋žจ์ด BPF์— ์ถ”๊ฐ€๋˜๊ณ  ์ ์  ๋” ๋งŽ์€ ๋Œ€๊ธฐ์—…์ด ์ „ํˆฌ ์„œ๋ฒ„์—์„œ BPF๋ฅผ 24ร—7 ์‚ฌ์šฉํ•˜๋Š” ๋“ฑ ์ ์  ๋” ๋งŽ์•„์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์Šคํƒ€ํŠธ์—…์€ BPF ๊ธฐ๋ฐ˜ ์†”๋ฃจ์…˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„์ฆˆ๋‹ˆ์Šค๋ฅผ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค. BPF๋Š” DDoS ๊ณต๊ฒฉ ๋ฐฉ์ง€, SDN ์ƒ์„ฑ(์˜ˆ: ์ฟ ๋ฒ„๋„คํ‹ฐ์Šค์šฉ ๋„คํŠธ์›Œํฌ ๊ตฌํ˜„), ์ฃผ์š” ์‹œ์Šคํ…œ ์ถ”์  ๋„๊ตฌ ๋ฐ ํ†ต๊ณ„ ์ˆ˜์ง‘๊ธฐ, ์นจ์ž… ํƒ์ง€ ์‹œ์Šคํ…œ ๋ฐ ์ƒŒ๋“œ๋ฐ•์Šค ์‹œ์Šคํ…œ ๋“ฑ ๋ชจ๋“  ๊ณณ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ๊ธฐ์‚ฌ์˜ ๊ฐœ์š” ๋ถ€๋ถ„์„ ๋งˆ๋ฌด๋ฆฌํ•˜๊ณ  ๊ฐ€์ƒ ๋จธ์‹ ๊ณผ BPF ์ƒํƒœ๊ณ„๋ฅผ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์—ฌ๋‹ด: ์œ ํ‹ธ๋ฆฌํ‹ฐ

๋‹ค์Œ ์„น์…˜์˜ ์˜ˆ์ œ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด ์ตœ์†Œํ•œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. llvm/clang bpf ์ง€์› ๋ฐ bpftool. ์„น์…˜ ๊ฐœ๋ฐœ ๋„๊ตฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ์ปค๋„์„ ์กฐ๋ฆฝํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ง€์นจ์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„น์…˜์€ ์šฐ๋ฆฌ ๋ฐœํ‘œ์˜ ์กฐํ™”๋ฅผ ๋ฐฉํ•ดํ•˜์ง€ ์•Š๋„๋ก ์•„๋ž˜์— ๋ฐฐ์น˜๋ฉ๋‹ˆ๋‹ค.

BPF ๊ฐ€์ƒ ๋จธ์‹  ๋ ˆ์ง€์Šคํ„ฐ ๋ฐ ๋ช…๋ น ์‹œ์Šคํ…œ

BPF์˜ ์•„ํ‚คํ…์ฒ˜์™€ ๋ช…๋ น ์‹œ์Šคํ…œ์€ ํ”„๋กœ๊ทธ๋žจ์ด C ์–ธ์–ด๋กœ ์ž‘์„ฑ๋˜๊ณ  ์ปค๋„์— ๋กœ๋“œ๋œ ํ›„ ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๊ณ ๋ คํ•˜์—ฌ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ ˆ์ง€์Šคํ„ฐ ์ˆ˜์™€ ๋ช…๋ น ์„ธํŠธ๋Š” ์ˆ˜ํ•™์  ์˜๋ฏธ์—์„œ ํ˜„๋Œ€ ๊ธฐ๊ณ„ ๊ธฐ๋Šฅ์˜ ๊ต์ฐจ์ ์„ ๊ณ ๋ คํ•˜์—ฌ ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ๋‹ค์–‘ํ•œ ์ œํ•œ์ด ์ ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ตœ๊ทผ๊นŒ์ง€ ๋ฃจํ”„์™€ ์„œ๋ธŒ๋ฃจํ‹ด์„ ์ž‘์„ฑํ•  ์ˆ˜ ์—†์—ˆ๊ณ  ๋ช…๋ น ์ˆ˜๊ฐ€ 4096๊ฐœ๋กœ ์ œํ•œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(ํ˜„์žฌ ๊ถŒํ•œ ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์€ ์ตœ๋Œ€ ๋ฐฑ๋งŒ ๊ฐœ์˜ ๋ช…๋ น์„ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค).

BPF์—๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” 64๊ฐœ์˜ XNUMX๋น„ํŠธ ๋ ˆ์ง€์Šคํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. r0-r10 ๊ทธ๋ฆฌ๊ณ  ํ”„๋กœ๊ทธ๋žจ ์นด์šดํ„ฐ. ๋“ฑ๋กํ•˜๋‹ค r10 ํ”„๋ ˆ์ž„ ํฌ์ธํ„ฐ๋ฅผ ํฌํ•จํ•˜๋ฉฐ ์ฝ๊ธฐ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์€ ๋Ÿฐํƒ€์ž„ ์‹œ 512๋ฐ”์ดํŠธ ์Šคํƒ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋งต ํ˜•ํƒœ์˜ ๋ฌด์ œํ•œ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

BPF ํ”„๋กœ๊ทธ๋žจ์€ ํŠน์ • ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜• ์ปค๋„ ๋„์šฐ๋ฏธ ์„ธํŠธ์™€ ์ตœ๊ทผ์—๋Š” ์ผ๋ฐ˜ ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜ธ์ถœ๋œ ๊ฐ ํ•จ์ˆ˜๋Š” ๋ ˆ์ง€์Šคํ„ฐ์— ์ „๋‹ฌ๋œ ์ตœ๋Œ€ XNUMX๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. r1-r5, ๋ฐ˜ํ™˜ ๊ฐ’์€ ๋‹ค์Œ์œผ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. r0. ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜๋œ ํ›„ ๋ ˆ์ง€์Šคํ„ฐ์˜ ๋‚ด์šฉ์ด ๋ณด์žฅ๋ฉ๋‹ˆ๋‹ค. r6-r9 ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํšจ์œจ์ ์ธ ํ”„๋กœ๊ทธ๋žจ ๋ฒˆ์—ญ์„ ์œ„ํ•ด ๋ ˆ์ง€์Šคํ„ฐ r0-r11 ์ง€์›๋˜๋Š” ๋ชจ๋“  ์•„ํ‚คํ…์ฒ˜๋Š” ํ˜„์žฌ ์•„ํ‚คํ…์ฒ˜์˜ ABI ๊ธฐ๋Šฅ์„ ๊ณ ๋ คํ•˜์—ฌ ์‹ค์ œ ๋ ˆ์ง€์Šคํ„ฐ์— ๊ณ ์œ ํ•˜๊ฒŒ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, x86_64 ๋ ˆ์ง€์Šคํ„ฐ r1-r5ํ•จ์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” ๋Š” ๋‹ค์Œ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. rdi, rsi, rdx, rcx, r8, ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ํ•จ์ˆ˜์— ์ „๋‹ฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. x86_64. ์˜ˆ๋ฅผ ๋“ค์–ด ์™ผ์ชฝ์˜ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์˜ค๋ฅธ์ชฝ์˜ ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

1:  (b7) r1 = 1                    mov    $0x1,%rdi
2:  (b7) r2 = 2                    mov    $0x2,%rsi
3:  (b7) r3 = 3                    mov    $0x3,%rdx
4:  (b7) r4 = 4                    mov    $0x4,%rcx
5:  (b7) r5 = 5                    mov    $0x5,%r8
6:  (85) call pc+1                 callq  0x0000000000001ee8

๋ ˆ์ง€์Šคํ„ฐ r0 ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ์—๋„ ์‚ฌ์šฉ๋˜๋ฉฐ ๋ ˆ์ง€์Šคํ„ฐ์—์„œ r1 ํ”„๋กœ๊ทธ๋žจ์—๋Š” ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•์— ๋”ฐ๋ผ ์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ์กฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. struct xdp_md (XDP์˜ ๊ฒฝ์šฐ) ๋˜๋Š” ๊ตฌ์กฐ struct __sk_buff (๋‹ค๋ฅธ ๋„คํŠธ์›Œํฌ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ) ๋˜๋Š” ๊ตฌ์กฐ struct pt_regs (๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์šฉ) ๋“ฑ

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ๋ ˆ์ง€์Šคํ„ฐ ์„ธํŠธ, ์ปค๋„ ๋„์šฐ๋ฏธ, ์Šคํƒ, ์ปจํ…์ŠคํŠธ ํฌ์ธํ„ฐ ๋ฐ ๋งต ํ˜•ํƒœ์˜ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ–๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌํ–‰์—์„œ ์ด ๋ชจ๋“  ๊ฒƒ์ด ๊ผญ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ...

๊ณ„์†ํ•ด์„œ ์„ค๋ช…ํ•˜๊ณ  ์ด๋Ÿฌํ•œ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ช…๋ น ์‹œ์Šคํ…œ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ (๊ฑฐ์˜ ๋ชจ๋“ ) BPF ๋ช…๋ น์–ด์˜ ํฌ๊ธฐ๋Š” 64๋น„ํŠธ๋กœ ๊ณ ์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. 64๋น„ํŠธ Big Endian ์‹œ์Šคํ…œ์—์„œ ํ•œ ๋ช…๋ น์–ด๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‚ด์šฉ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

์—ฌ๊ธฐ์— Code - ์ด๊ฒƒ์€ ๋ช…๋ น์–ด์˜ ์ธ์ฝ”๋”ฉ์ž…๋‹ˆ๋‹ค. Dst/Src ๋Š” ๊ฐ๊ฐ ์ˆ˜์‹ ์ž์™€ ์†Œ์Šค์˜ ์ธ์ฝ”๋”ฉ์ž…๋‹ˆ๋‹ค. Off - 16๋น„ํŠธ ๋ถ€ํ˜ธ ์žˆ๋Š” ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฐ Imm ์ผ๋ถ€ ๋ช…๋ น์–ด์— ์‚ฌ์šฉ๋˜๋Š” 32๋น„ํŠธ ๋ถ€ํ˜ธ ์žˆ๋Š” ์ •์ˆ˜์ž…๋‹ˆ๋‹ค(cBPF ์ƒ์ˆ˜ K์™€ ์œ ์‚ฌ). ๋ถ€ํ˜ธํ™” Code ๋‘ ๊ฐ€์ง€ ์œ ํ˜• ์ค‘ ํ•˜๋‚˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

๋ช…๋ น์–ด ํด๋ž˜์Šค 0, 1, 2, 3์€ ๋ฉ”๋ชจ๋ฆฌ ์ž‘์—…์„ ์œ„ํ•œ ๋ช…๋ น์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค ๋ถ€๋ฅด๋‹ค, BPF_LD, BPF_LDX, BPF_ST, BPF_STX, ๊ฐ๊ฐ. 4, 7๊ธ‰ (BPF_ALU, BPF_ALU64)์€ ALU ๋ช…๋ น์–ด ์„ธํŠธ๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. 5, 6๊ธ‰ (BPF_JMP, BPF_JMP32) ์ ํ”„ ๋ช…๋ น์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

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

๊ฐœ๋ณ„ ์ง€์นจ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•  ๋•Œ ํ•ต์‹ฌ ํŒŒ์ผ์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. bpf.h ะธ bpf_common.h, BPF ๋ช…๋ น์–ด์˜ ์ˆซ์ž ์ฝ”๋“œ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ž์ฒด์ ์œผ๋กœ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์—ฐ๊ตฌํ•˜๊ฑฐ๋‚˜ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ๋•Œ ๋ณต์žกํ•œ ์ˆœ์„œ๋กœ ์ •๋ ฌ๋œ ๋‹ค์Œ ์†Œ์Šค์—์„œ ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น„๊ณต์‹ eBPF ์‚ฌ์–‘, BPF ๋ฐ XDP ์ฐธ์กฐ ๊ฐ€์ด๋“œ, ๋ช…๋ น์–ด ์„ธํŠธ, ๋ฌธ์„œ/๋„คํŠธ์›Œํ‚น/filter.txt ๋ฌผ๋ก  Linux ์†Œ์Šค ์ฝ”๋“œ์—๋Š” ๊ฒ€์ฆ์ž, JIT, BPF ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ: ๋จธ๋ฆฌ ์†์—์„œ BPF๋ฅผ ๋ถ„ํ•ดํ•˜๋Š” ์ค‘

ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๋Š” ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. readelf-example.c ๊ฒฐ๊ณผ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‚ดํŽด๋ณด์„ธ์š”. ์›๋ณธ ๋‚ด์šฉ์„ ๊ณต๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค readelf-example.c ์•„๋ž˜์—์„œ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฝ”๋“œ์—์„œ ๋…ผ๋ฆฌ๋ฅผ ๋ณต์›ํ•œ ํ›„์ž…๋‹ˆ๋‹ค.

$ clang -target bpf -c readelf-example.c -o readelf-example.o -O2
$ llvm-readelf -x .text readelf-example.o
Hex dump of section '.text':
0x00000000 b7000000 01000000 15010100 00000000 ................
0x00000010 b7000000 02000000 95000000 00000000 ................

์ถœ๋ ฅ์˜ ์ฒซ ๋ฒˆ์งธ ์—ด readelf ๋“ค์—ฌ์“ฐ๊ธฐ์ด๋ฏ€๋กœ ํ”„๋กœ๊ทธ๋žจ์€ ๋„ค ๊ฐ€์ง€ ๋ช…๋ น์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

Code Dst Src Off  Imm
b7   0   0   0000 01000000
15   0   1   0100 00000000
b7   0   0   0000 02000000
95   0   0   0000 00000000

๋ช…๋ น ์ฝ”๋“œ๊ฐ€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. b7, 15, b7 ะธ 95. ์ตœํ•˜์œ„ 7๋น„ํŠธ๋Š” ๋ช…๋ น์–ด ํด๋ž˜์Šค๋ผ๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ๋ชจ๋“  ๋ช…๋ น์–ด์˜ ๋„ค ๋ฒˆ์งธ ๋น„ํŠธ๊ฐ€ ๋น„์–ด ์žˆ์œผ๋ฏ€๋กœ ๋ช…๋ น์–ด ํด๋ž˜์Šค๋Š” ๊ฐ๊ฐ 5, 7, 5, 7์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค XNUMX์€ BPF_ALU64, ๊ทธ๋ฆฌ๊ณ  5๋Š” BPF_JMP. ๋‘ ํด๋ž˜์Šค ๋ชจ๋‘ ๋ช…๋ น ํ˜•์‹์€ ๋™์ผํ•˜๋ฉฐ(์œ„ ์ฐธ์กฐ) ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์‹œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋™์‹œ์— ๋‚˜๋จธ์ง€ ์—ด๋„ ์‚ฌ๋žŒ ํ˜•์‹์œผ๋กœ ๋‹ค์‹œ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค).

Op S  Class   Dst Src Off  Imm
b  0  ALU64   0   0   0    1
1  0  JMP     0   1   1    0
b  0  ALU64   0   0   0    2
9  0  JMP     0   0   0    0

์šด์ „ b ํด๋ž˜์Šค ALU64 -๊ฐ€์š” BPF_MOV. ๋Œ€์ƒ ๋ ˆ์ง€์Šคํ„ฐ์— ๊ฐ’์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ๋น„ํŠธ๊ฐ€ ์„ค์ •๋œ ๊ฒฝ์šฐ s (์†Œ์Šค)์ด๋ฉด ์†Œ์Šค ๋ ˆ์ง€์Šคํ„ฐ์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ , ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ์ฒ˜๋Ÿผ ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•„๋“œ์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. Imm. ๋”ฐ๋ผ์„œ ์ฒซ ๋ฒˆ์งธ์™€ ์„ธ ๋ฒˆ์งธ ์ง€์นจ์—์„œ๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. r0 = Imm. ๋˜ํ•œ JMP ํด๋ž˜์Šค 1 ์ž‘์—…์€ BPF_JEQ (๊ฐ™์œผ๋ฉด ์ ํ”„). ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ๋น„ํŠธ๋ถ€ํ„ฐ S XNUMX์ด๋ฉด ์†Œ์Šค ๋ ˆ์ง€์Šคํ„ฐ์˜ ๊ฐ’์„ ํ•„๋“œ์™€ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค. Imm. ๊ฐ’์ด ์ผ์น˜ํ•˜๋ฉด ๋‹ค์Œ์œผ๋กœ ์ „ํ™˜์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. PC + Off์–ด๋””์—์„œ PC์—๋Š” ํ‰์†Œ์™€ ๊ฐ™์ด ๋‹ค์Œ ๋ช…๋ น์–ด์˜ ์ฃผ์†Œ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ JMP ํด๋ž˜์Šค 9 ์ž‘์—…์€ BPF_EXIT. ์ด ๋ช…๋ น์–ด๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•˜๊ณ  ์ปค๋„๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. r0. ํ…Œ์ด๋ธ”์— ์ƒˆ ์—ด์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Op    S  Class   Dst Src Off  Imm    Disassm
MOV   0  ALU64   0   0   0    1      r0 = 1
JEQ   0  JMP     0   1   1    0      if (r1 == 0) goto pc+1
MOV   0  ALU64   0   0   0    2      r0 = 2
EXIT  0  JMP     0   0   0    0      exit

์ด๋ฅผ ๋ณด๋‹ค ํŽธ๋ฆฌํ•œ ํ˜•์‹์œผ๋กœ ๋‹ค์‹œ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     r0 = 1
     if (r1 == 0) goto END
     r0 = 2
END:
     exit

๊ธฐ๋ก๋ถ€์— ์žˆ๋Š” ๋‚ด์šฉ์„ ๊ธฐ์–ตํ•œ๋‹ค๋ฉด r1 ํ”„๋กœ๊ทธ๋žจ์€ ์ปค๋„๋กœ๋ถ€ํ„ฐ ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›๊ณ  ๋ ˆ์ง€์Šคํ„ฐ์— r0 ๊ฐ’์ด ์ปค๋„์— ๋ฐ˜ํ™˜๋˜๋ฉด ์ปจํ…์ŠคํŠธ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ 1์ด๋ฉด 2์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด - XNUMX๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†Œ์Šค๋ฅผ ๋ณด๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์˜ณ์€์ง€ ํ™•์ธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ cat readelf-example.c
int foo(void *ctx)
{
        return ctx ? 2 : 1;
}

์˜ˆ, ์˜๋ฏธ ์—†๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋Š” ๋‹จ์ง€ ๋„ค ๊ฐ€์ง€ ๊ฐ„๋‹จํ•œ ์ง€์นจ์œผ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์™ธ ์˜ˆ: 16๋ฐ”์ดํŠธ ๋ช…๋ น์–ด

์•ž์—์„œ ์ผ๋ถ€ ๋ช…๋ น์–ด๋Š” 64๋น„ํŠธ ์ด์ƒ์„ ์ฐจ์ง€ํ•œ๋‹ค๊ณ  ์–ธ๊ธ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ์ง€์นจ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. lddw (์ฝ”๋“œ = 0x18 = BPF_LD | BPF_DW | BPF_IMM) โ€” ํ•„๋“œ์˜ ๋”๋ธ” ์›Œ๋“œ๋ฅผ ๋ ˆ์ง€์Šคํ„ฐ์— ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. Imm. ํฌ์ธํŠธ์ด๋‹ค Imm ํฌ๊ธฐ๋Š” 32์ด๊ณ  ๋”๋ธ” ์›Œ๋“œ๋Š” 64๋น„ํŠธ์ด๋ฏ€๋กœ ํ•˜๋‚˜์˜ 64๋น„ํŠธ ๋ช…๋ น์–ด๋กœ 64๋น„ํŠธ ์ฆ‰์‹œ๊ฐ’์„ ๋ ˆ์ง€์Šคํ„ฐ์— ๋กœ๋“œํ•˜๋Š” ๊ฒƒ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‘ ๊ฐœ์˜ ์ธ์ ‘ํ•œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„๋“œ์— 64๋น„ํŠธ ๊ฐ’์˜ ๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. Imm. ์˜ˆ:

$ cat x64.c
long foo(void *ctx)
{
        return 0x11223344aabbccdd;
}
$ clang -target bpf -c x64.c -o x64.o -O2
$ llvm-readelf -x .text x64.o
Hex dump of section '.text':
0x00000000 18000000 ddccbbaa 00000000 44332211 ............D3".
0x00000010 95000000 00000000                   ........

๋ฐ”์ด๋„ˆ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ๋ช…๋ น์–ด๊ฐ€ ๋‘ ๊ฐœ๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

Binary                                 Disassm
18000000 ddccbbaa 00000000 44332211    r0 = Imm[0]|Imm[1]
95000000 00000000                      exit

์šฐ๋ฆฌ๋Š” ์ง€์‹œ๋ฅผ ๊ฐ€์ง€๊ณ  ๋‹ค์‹œ ๋งŒ๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค lddw, ์žฌ๋ฐฐ์น˜ ๋ฐ ์ง€๋„ ์ž‘์—…์— ๊ด€ํ•ด ์ด์•ผ๊ธฐํ•  ๋•Œ

์˜ˆ: ํ‘œ์ค€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BPF ๋ถ„ํ•ด

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

$ llvm-objdump -d x64.o

Disassembly of section .text:

0000000000000000 <foo>:
 0: 18 00 00 00 dd cc bb aa 00 00 00 00 44 33 22 11 r0 = 1234605617868164317 ll
 2: 95 00 00 00 00 00 00 00 exit

BPF ๊ฐ์ฒด์˜ ์ˆ˜๋ช…์ฃผ๊ธฐ, bpffs ํŒŒ์ผ ์‹œ์Šคํ…œ

(๋‚˜๋Š” ์ด ํ•˜์œ„ ์„น์…˜์— ์„ค๋ช…๋œ ์„ธ๋ถ€ ์‚ฌํ•ญ ์ค‘ ์ผ๋ถ€๋ฅผ ์ฒ˜์Œ์œผ๋กœ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค. ๊ธˆ์‹ ์•Œ๋ ‰์„ธ์ด ์Šคํƒ€๋กœ๋ณด์ดํ† ํ”„ BPF ๋ธ”๋กœ๊ทธ.)

BPF ๊ฐ์ฒด(ํ”„๋กœ๊ทธ๋žจ ๋ฐ ๋งต)๋Š” ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. BPF_PROG_LOAD ะธ BPF_MAP_CREATE ์‹œ์Šคํ…œ ํ˜ธ์ถœ bpf(2), ๋‹ค์Œ ์„น์…˜์—์„œ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ๋ฐœ์ƒํ•˜๋Š”์ง€ ์ •ํ™•ํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ปค๋„ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ฐ๊ฐ์— ๋Œ€ํ•ด refcount (์ฐธ์กฐ ํšŸ์ˆ˜)๊ฐ€ XNUMX๋กœ ์„ค์ •๋˜๊ณ  ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํŒŒ์ผ ์„ค๋ช…์ž๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์†์žก์ด๋ฅผ ๋‹ซ์€ ํ›„ refcount ๊ฐœ์ฒด๋Š” XNUMX๋งŒํผ ๊ฐ์†Œํ•˜๊ณ , XNUMX์— ๋„๋‹ฌํ•˜๋ฉด ๊ฐœ์ฒด๊ฐ€ ํŒŒ๊ดด๋ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ๊ทธ๋žจ์ด ์ง€๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ refcount ์ด ์ง€๋„๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•œ ํ›„ XNUMX์”ฉ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•ด๋‹น ํŒŒ์ผ ์„ค๋ช…์ž๋Š” ์‚ฌ์šฉ์ž ํ”„๋กœ์„ธ์Šค์—์„œ ๋‹ซํž ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ refcount XNUMX์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค:

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

ํ”„๋กœ๊ทธ๋žจ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œํ•œ ํ›„ ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ฅผ ์ผ์ข…์˜ ์ด๋ฒคํŠธ ์ƒ์„ฑ๊ธฐ์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฅผ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ๋ฐฐ์น˜ํ•˜์—ฌ ๋“ค์–ด์˜ค๋Š” ํŒจํ‚ท์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ์ผ๋ถ€ ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. tracepoint ํ•ต์‹ฌ์—. ์ด ์‹œ์ ์—์„œ ์ฐธ์กฐ ์นด์šดํ„ฐ๋„ XNUMX์”ฉ ์ฆ๊ฐ€ํ•˜๊ณ  ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ์—์„œ ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๋ถ€ํŠธ๋กœ๋”๋ฅผ ์ข…๋ฃŒํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”? ์ด๋ฒคํŠธ ์ƒ์„ฑ๊ธฐ(ํ›„ํฌ)์˜ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋ชจ๋“  ๋„คํŠธ์›Œํฌ ํ›„ํฌ๋Š” ๋กœ๋”๊ฐ€ ์™„๋ฃŒ๋œ ํ›„์— ์กด์žฌํ•˜๊ฒŒ ๋˜๋ฉฐ, ์ด๋ฅผ ๊ธ€๋กœ๋ฒŒ ํ›„ํฌ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์€ ์ด๋ฅผ ์ƒ์„ฑํ•œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์— ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค(๋”ฐ๋ผ์„œ "๋กœ์ปฌ์—์„œ ํ”„๋กœ์„ธ์Šค๋กœ"๋ผ๋Š” ๋œป์œผ๋กœ ๋กœ์ปฌ์ด๋ผ๊ณ  ํ•จ). ๊ธฐ์ˆ ์ ์œผ๋กœ ๋กœ์ปฌ ํ›„ํฌ๋Š” ํ•ญ์ƒ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์— ํ•ด๋‹น ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋ฏ€๋กœ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ซํž ๋•Œ ๋‹ซํžˆ์ง€๋งŒ ๊ธ€๋กœ๋ฒŒ ํ›„ํฌ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ทธ๋ฆผ์—์„œ๋Š” ๋นจ๊ฐ„์ƒ‰ ์‹ญ์ž๊ฐ€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ ๋ฐ ์ „์—ญ ํ›„ํฌ์˜ ๊ฒฝ์šฐ ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ๊ฐ€ ๊ฐœ์ฒด ์ˆ˜๋ช…์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

๋กœ์ปฌ ํ›„ํฌ์™€ ๊ธ€๋กœ๋ฒŒ ํ›„ํฌ๊ฐ€ ๊ตฌ๋ณ„๋˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ผ๋ถ€ ์œ ํ˜•์˜ ๋„คํŠธ์›Œํฌ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„ ์—†์ด๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด DDoS ๋ณดํ˜ธ๋ฅผ ์ƒ์ƒํ•ด ๋ณด์„ธ์š”. ๋ถ€ํŠธ๋กœ๋”๊ฐ€ ๊ทœ์น™์„ ์ž‘์„ฑํ•˜๊ณ  BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐํ•œ ํ›„ ๋ถ€ํŠธ๋กœ๋”๊ฐ€ ์Šค์Šค๋กœ ์ข…๋ฃŒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— XNUMX๋ถ„ ๋งŒ์— ๋ฌด๋ฆŽ์„ ๊ฟ‡๊ณ  ์ž‘์„ฑํ•œ ๋””๋ฒ„๊น… ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์„ ์ƒ์ƒํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์‹œ์Šคํ…œ์— ์“ฐ๋ ˆ๊ธฐ๊ฐ€ ๋‚จ์•„ ์žˆ์ง€ ์•Š๊ธฐ๋ฅผ ์›ํ•˜๋ฉฐ ๋กœ์ปฌ ํ›„ํฌ๊ฐ€ ์ด๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด์— ์ปค๋„์˜ ์ถ”์ ์ ์— ์—ฐ๊ฒฐํ•˜์—ฌ ์ˆ˜๋…„์— ๊ฑธ์ณ ํ†ต๊ณ„๋ฅผ ์ˆ˜์ง‘ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž ๋ถ€๋ถ„์„ ์™„๋ฃŒํ•˜๊ณ  ๋•Œ๋•Œ๋กœ ํ†ต๊ณ„๋กœ ๋Œ์•„๊ฐ€๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. bpf ํŒŒ์ผ ์‹œ์Šคํ…œ์€ ์ด๋Ÿฌํ•œ ๊ธฐํšŒ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. BPF ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” ํŒŒ์ผ ์ƒ์„ฑ์„ ํ—ˆ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋‚ด ์ „์šฉ ์˜์‚ฌ ํŒŒ์ผ ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. refcount ์‚ฌ๋ฌผ. ๊ทธ ํ›„์—๋Š” ๋กœ๋”๊ฐ€ ์ข…๋ฃŒ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ƒ์„ฑ๋œ ๊ฐœ์ฒด๋Š” ๊ณ„์† ์‚ด์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋ฆฐ์ด๋ฅผ ์œ„ํ•œ BPF XNUMX๋ถ€: ํ™•์žฅ๋œ BPF

BPF ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•˜๋Š” bpffs์— ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ "๊ณ ์ •"์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค(๋‹ค์Œ ๊ตฌ๋ฌธ์—์„œ์™€ ๊ฐ™์ด "ํ”„๋กœ์„ธ์Šค๋Š” BPF ํ”„๋กœ๊ทธ๋žจ ๋˜๋Š” ๋งต์„ ๊ณ ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค"). BPF ๊ฐ์ฒด์— ๋Œ€ํ•œ ํŒŒ์ผ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ๋กœ์ปฌ ๊ฐ์ฒด์˜ ์ˆ˜๋ช…์„ ์—ฐ์žฅํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ „์—ญ ๊ฐ์ฒด์˜ ์œ ์šฉ์„ฑ์„ ์œ„ํ•ด์„œ๋„ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์—ญ DDoS ๋ณดํ˜ธ ํ”„๋กœ๊ทธ๋žจ์˜ ์˜ˆ๋กœ ๋Œ์•„๊ฐ€์„œ ํ†ต๊ณ„๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ.

BPF ํŒŒ์ผ ์‹œ์Šคํ…œ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ ์œ„์น˜์— ๋งˆ์šดํŠธ๋ฉ๋‹ˆ๋‹ค. /sys/fs/bpfํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋กœ์ปฌ๋กœ ๋งˆ์šดํŠธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint

ํŒŒ์ผ ์‹œ์Šคํ…œ ์ด๋ฆ„์€ ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. BPF_OBJ_PIN BPF ์‹œ์Šคํ…œ ํ˜ธ์ถœ. ์„ค๋ช…์„ ์œ„ํ•ด ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ€์ ธ์™€์„œ ์ปดํŒŒ์ผํ•˜๊ณ  ์—…๋กœ๋“œํ•œ ํ›„ ํ•€์œผ๋กœ ๊ณ ์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpffs. ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์˜ˆ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ฝ”๋“œ๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

$ cat test.c
__attribute__((section("xdp"), used))
int test(void *ctx)
{
        return 0;
}

char _license[] __attribute__((section("license"), used)) = "GPL";

์ด ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ํŒŒ์ผ ์‹œ์Šคํ…œ์˜ ๋กœ์ปฌ ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpffs:

$ clang -target bpf -c test.c -o test.o
$ mkdir bpf-mountpoint
$ sudo mount -t bpf none bpf-mountpoint

์ด์ œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์šด๋กœ๋“œํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpftool ๊ทธ๋ฆฌ๊ณ  ๊ทธ์— ๋”ฐ๋ฅธ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ดํŽด๋ณด์„ธ์š” bpf(2) (strace ์ถœ๋ ฅ์—์„œ โ€‹โ€‹์ผ๋ถ€ ๊ด€๋ จ ์—†๋Š” ํ–‰์ด ์ œ๊ฑฐ๋จ):

$ sudo strace -e bpf bpftool prog load ./test.o bpf-mountpoint/test
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, prog_name="test", ...}, 120) = 3
bpf(BPF_OBJ_PIN, {pathname="bpf-mountpoint/test", bpf_fd=3}, 120) = 0

์—ฌ๊ธฐ์—์„œ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค. BPF_PROG_LOAD, ์ปค๋„๋กœ๋ถ€ํ„ฐ ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. 3 ๊ทธ๋ฆฌ๊ณ  ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ BPF_OBJ_PIN ์ด ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ํŒŒ์ผ๋กœ ๊ณ ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. "bpf-mountpoint/test". ๊ทธ ํ›„ ๋ถ€ํŠธ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ bpftool ์ž‘์—…์ด ์™„๋ฃŒ๋˜์—ˆ์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์„ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐํ•˜์ง€๋Š” ์•Š์•˜์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์€ ์ปค๋„์— ๋‚จ์•„ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

$ sudo bpftool prog | tail -3
783: xdp  name test  tag 5c8ba0cf164cb46c  gpl
        loaded_at 2020-05-05T13:27:08+0000  uid 0
        xlated 24B  jited 41B  memlock 4096B

์ •์ƒ์ ์œผ๋กœ ํŒŒ์ผ ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค unlink(2) ๊ทธ ํ›„์—๋Š” ํ•ด๋‹น ํ”„๋กœ๊ทธ๋žจ์ด ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค.

$ sudo rm ./bpf-mountpoint/test
$ sudo bpftool prog show id 783
Error: get by id (783): No such file or directory

๊ฐ์ฒด ์‚ญ์ œ

๊ฐ์ฒด ์‚ญ์ œ์— ๊ด€ํ•ด ๋งํ•˜๋ฉด, ํ›„ํฌ(์ด๋ฒคํŠธ ์ƒ์„ฑ๊ธฐ)์—์„œ ํ”„๋กœ๊ทธ๋žจ ์—ฐ๊ฒฐ์„ ๋Š์€ ํ›„์—๋Š” ๋‹จ์ผ ์ƒˆ ์ด๋ฒคํŠธ๊ฐ€ ์‹คํ–‰์„ ํŠธ๋ฆฌ๊ฑฐํ•˜์ง€ ์•Š์ง€๋งŒ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ชจ๋“  ํ˜„์žฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ •์ƒ์ ์ธ ์ˆœ์„œ๋กœ ์™„๋ฃŒ๋œ๋‹ค๋Š” ์ ์„ ๋ช…ํ™•ํžˆ ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. .

์ผ๋ถ€ ์œ ํ˜•์˜ BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ฆ‰์‹œ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹œํ€€์Šค ์›์ž์„ฑ์„ ์ œ๊ณต replace = detach old program, attach new program. ์ด ๊ฒฝ์šฐ ์ด์ „ ๋ฒ„์ „ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ชจ๋“  ํ™œ์„ฑ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ณ  ์ƒˆ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ƒˆ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์ƒ์„ฑ๋˜๋ฉฐ ์—ฌ๊ธฐ์„œ "์›์ž์„ฑ"์€ ๋‹จ์ผ ์ด๋ฒคํŠธ๊ฐ€ ๋ˆ„๋ฝ๋˜์ง€ ์•Š์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ ์†Œ์Šค์— ํ”„๋กœ๊ทธ๋žจ ์—ฐ๊ฒฐ

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณ„๋„๋กœ ์„ค๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํŠน์ • ์œ ํ˜•์˜ ํ”„๋กœ๊ทธ๋žจ ๋งฅ๋ฝ์—์„œ ์ด๋ฅผ ์—ฐ๊ตฌํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์„ผํ‹ฐ๋ฏธํ„ฐ. ์˜ˆ ์•„๋ž˜์—์„œ๋Š” XDP์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์ด ์–ด๋–ป๊ฒŒ ์—ฐ๊ฒฐ๋˜๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

bpf ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด ์กฐ์ž‘

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

๋ชจ๋“  BPF ๊ฐ์ฒด๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ƒ์„ฑ๋˜๊ณ  ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. bpf, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”„๋กœํ† ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

#include <linux/bpf.h>

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

์—ฌ๊ธฐ ํŒ€์ด ์žˆ์–ด์š” cmd ์œ ํ˜•์˜ ๊ฐ’ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค enum bpf_cmd, attr โ€” ํŠน์ • ํ”„๋กœ๊ทธ๋žจ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋ฐ size โ€” ํฌ์ธํ„ฐ์— ๋”ฐ๋ฅธ ๊ฐ์ฒด ํฌ๊ธฐ, ์ฆ‰ ๋ณดํ†ต ์ด sizeof(*attr). ์ปค๋„ 5.8์—์„œ๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ bpf 34๊ฐ€์ง€์˜ ๋‹ค์–‘ํ•œ ๋ช…๋ น์„ ์ง€์›ํ•˜๋ฉฐ, ๊ฒฐ์ • union bpf_attr 200์ค„์„ ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ธฐ์‚ฌ๋ฅผ ํ†ตํ•ด ๋ช…๋ น๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ต์ˆ™ํ•ด์งˆ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์— ๊ฒ๋จน์„ ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.

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

์ด์ œ ๊ฐ„๋‹จํ•œ BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋จผ์ € ๋กœ๋“œํ•  ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฅ˜๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ั‚ะธะฟ ๊ทธ๋ฆฌ๊ณ  ์ด ์œ ํ˜•์˜ ํ”„๋ ˆ์ž„์›Œํฌ ๋‚ด์—์„œ ๊ฒ€์ฆ์ž ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ•  ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋Ÿฌ๋‚˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ณต์žกํ•˜๊ฒŒ ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ๊ธฐ์„ฑ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. BPF_PROG_TYPE_XDP, ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. XDP_PASS (๋ชจ๋“  ํŒจํ‚ค์ง€ ๊ฑด๋„ˆ๋›ฐ๊ธฐ) BPF ์–ด์…ˆ๋ธ”๋Ÿฌ์—์„œ๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

r0 = 2
exit

์šฐ๋ฆฌ๊ฐ€ ๊ฒฐ์ •ํ•œ ํ›„์— ๊ทธ ์—…๋กœ๋“œํ•  ์˜ˆ์ •์ด๋ฉฐ ์–ด๋–ป๊ฒŒ ํ•  ๊ฒƒ์ธ์ง€ ์•Œ๋ ค๋“œ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/bpf.h>

static inline __u64 ptr_to_u64(const void *ptr)
{
        return (__u64) (unsigned long) ptr;
}

int main(void)
{
    struct bpf_insn insns[] = {
        {
            .code = BPF_ALU64 | BPF_MOV | BPF_K,
            .dst_reg = BPF_REG_0,
            .imm = XDP_PASS
        },
        {
            .code = BPF_JMP | BPF_EXIT
        },
    };

    union bpf_attr attr = {
        .prog_type = BPF_PROG_TYPE_XDP,
        .insns     = ptr_to_u64(insns),
        .insn_cnt  = sizeof(insns)/sizeof(insns[0]),
        .license   = ptr_to_u64("GPL"),
    };

    strncpy(attr.prog_name, "woo", sizeof(attr.prog_name));
    syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));

    for ( ;; )
        pause();
}

ํ”„๋กœ๊ทธ๋žจ์˜ ํฅ๋ฏธ๋กœ์šด ์ด๋ฒคํŠธ๋Š” ๋ฐฐ์—ด ์ •์˜๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. insns - ๊ธฐ๊ณ„์–ด ์ฝ”๋“œ์˜ BPF ํ”„๋กœ๊ทธ๋žจ. ์ด ๊ฒฝ์šฐ BPF ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ ๋ช…๋ น์–ด๋Š” ๊ตฌ์กฐ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. bpf_insn. ์ฒซ ๋ฒˆ์งธ ์š”์†Œ insns ์ง€์‹œ๋ฅผ ๋”ฐ๋ฅธ๋‹ค r0 = 2, ๋‘๋ฒˆ์งธ - exit.

ํ›„ํ‡ด. ์ปค๋„์€ ๊ธฐ๊ณ„ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฐ ์ปค๋„ ํ—ค๋” ํŒŒ์ผ ์‚ฌ์šฉ์„ ์œ„ํ•œ ๋ณด๋‹ค ํŽธ๋ฆฌํ•œ ๋งคํฌ๋กœ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. tools/include/linux/filter.h ์šฐ๋ฆฌ๋Š” ์“ธ ์ˆ˜ ์žˆ์—ˆ๋‹ค

struct bpf_insn insns[] = {
    BPF_MOV64_IMM(BPF_REG_0, XDP_PASS),
    BPF_EXIT_INSN()
};

๊ทธ๋Ÿฌ๋‚˜ ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋กœ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์€ ์ปค๋„์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  BPF์— ๊ด€ํ•œ ๊ธฐ์‚ฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•˜๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ๋งคํฌ๋กœ๊ฐ€ ์—†๋‹ค๊ณ  ํ•ด์„œ ๊ฐœ๋ฐœ์ž์˜ ์ƒํ™œ์ด ์‹ค์ œ๋กœ ๋ณต์žกํ•ด์ง€๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ •์˜ํ•œ ํ›„ ์ด๋ฅผ ์ปค๋„์— ๋กœ๋“œํ•˜๋Š” ๋‹จ๊ณ„๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ธํŠธ attr ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•, ์ง€์นจ ์„ธํŠธ ๋ฐ ์ˆ˜, ํ•„์š”ํ•œ ๋ผ์ด์„ผ์Šค ๋ฐ ์ด๋ฆ„์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. "woo", ๋‹ค์šด๋กœ๋“œ ํ›„ ์‹œ์Šคํ…œ์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์•ฝ์†ํ•œ ๋Œ€๋กœ ํ”„๋กœ๊ทธ๋žจ์€ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ์Šคํ…œ์— ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. bpf.

ํ”„๋กœ๊ทธ๋žจ์ด ๋๋‚˜๋ฉด ํŽ˜์ด๋กœ๋“œ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์—†์œผ๋ฉด ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ด ๋ฐ˜ํ™˜ํ•œ ํŒŒ์ผ ์„ค๋ช…์ž๊ฐ€ ๋‹ซํž ๋•Œ ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„์— ์˜ํ•ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. bpf, ์‹œ์Šคํ…œ์—์„œ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด์ œ ํ…Œ์ŠคํŠธํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์—์„œ ํ”„๋กœ๊ทธ๋žจ์„ ์–ด์…ˆ๋ธ”ํ•˜๊ณ  ์‹คํ–‰ํ•ด ๋ด…์‹œ๋‹ค. strace๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

$ clang -g -O2 simple-prog.c -o simple-prog

$ sudo strace ./simple-prog
execve("./simple-prog", ["./simple-prog"], 0x7ffc7b553480 /* 13 vars */) = 0
...
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=2, insns=0x7ffe03c4ed50, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_V
ERSION(0, 0, 0), prog_flags=0, prog_name="woo", prog_ifindex=0, expected_attach_type=BPF_CGROUP_INET_INGRESS}, 72) = 3
pause(

๋ชจ๋“  ๊ฒƒ์ด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. bpf(2) ํ•ธ๋“ค 3์„ ์šฐ๋ฆฌ์—๊ฒŒ ๋ฐ˜ํ™˜ํ–ˆ๊ณ  ์šฐ๋ฆฌ๋Š” ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์กŒ์Šต๋‹ˆ๋‹ค. pause(). ์‹œ์Šคํ…œ์—์„œ ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„๋กœ ์ด๋™ํ•˜์—ฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. bpftool:

# bpftool prog | grep -A3 woo
390: xdp  name woo  tag 3b185187f1855c4c  gpl
        loaded_at 2020-08-31T24:66:44+0000  uid 0
        xlated 16B  jited 40B  memlock 4096B
        pids simple-prog(10381)

์‹œ์Šคํ…œ์— ๋กœ๋“œ๋œ ํ”„๋กœ๊ทธ๋žจ์ด ์žˆ์Œ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. woo ๊ธ€๋กœ๋ฒŒ ID๋Š” 390์ด๊ณ  ํ˜„์žฌ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. simple-prog ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์—ด๋ฆฐ ํŒŒ์ผ ์„ค๋ช…์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋ฆฌ๊ณ  ๋งŒ์•ฝ simple-prog ๊ทธ๋Ÿผ ์ผ ๋๋‚ด์ค„๊ฒŒ woo ์‚ฌ๋ผ์งˆ ๊ฒƒ์ด๋‹ค). ์˜ˆ์ƒ๋Œ€๋กœ ํ”„๋กœ๊ทธ๋žจ์€ woo BPF ์•„ํ‚คํ…์ฒ˜์—์„œ๋Š” 16๋ฐ”์ดํŠธ(86๊ฐœ ๋ช…๋ น์–ด)์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ํ˜•์‹(x64_40)์—์„œ๋Š” ์ด๋ฏธ XNUMX๋ฐ”์ดํŠธ์ž…๋‹ˆ๋‹ค. ์›๋ž˜ ํ˜•์‹์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# bpftool prog dump xlated id 390
   0: (b7) r0 = 2
   1: (95) exit

๋†€๋ž„ ์ผ๋„ ์•„๋‹ˆ๋‹ค. ์ด์ œ JIT ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์ƒ์„ฑ๋œ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

# bpftool prog dump jited id 390
bpf_prog_3b185187f1855c4c_woo:
   0:   nopl   0x0(%rax,%rax,1)
   5:   push   %rbp
   6:   mov    %rsp,%rbp
   9:   sub    $0x0,%rsp
  10:   push   %rbx
  11:   push   %r13
  13:   push   %r14
  15:   push   %r15
  17:   pushq  $0x0
  19:   mov    $0x2,%eax
  1e:   pop    %rbx
  1f:   pop    %r15
  21:   pop    %r14
  23:   pop    %r13
  25:   pop    %rbx
  26:   leaveq
  27:   retq

๋ณ„๋กœ ํšจ๊ณผ์ ์ด์ง€ ์•Š๋‹ค exit(2), ํ•˜์ง€๋งŒ ๊ณตํ‰ํ•˜๊ฒŒ ๋งํ•˜๋ฉด ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ๋„ˆ๋ฌด ๊ฐ„๋‹จํ•˜๊ณ  ์ค‘์š”ํ•˜์ง€ ์•Š์€ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฒฝ์šฐ JIT ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์ถ”๊ฐ€ํ•œ ํ”„๋กค๋กœ๊ทธ์™€ ์—ํ•„๋กœ๊ทธ๊ฐ€ ๋ฌผ๋ก  ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ง€๋„

BPF ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค๋ฅธ BPF ํ”„๋กœ๊ทธ๋žจ๊ณผ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์˜ ํ”„๋กœ๊ทธ๋žจ ๋ชจ๋‘์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐํ™”๋œ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ์ฒด๋ฅผ ๋งต์ด๋ผ๊ณ  ํ•˜๋ฉฐ ์ด ์„น์…˜์—์„œ๋Š” ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. bpf.

๋งต์˜ ๊ธฐ๋Šฅ์ด ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค์—๋งŒ ๊ตญํ•œ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋ฐ”๋กœ ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด BPF ํ”„๋กœ๊ทธ๋žจ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋˜๋Š” ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ, ์„ฑ๋Šฅ ์ด๋ฒคํŠธ ์ž‘์—…์„ ์œ„ํ•œ ๋งต ๋“ฑ์„ ํฌํ•จํ•˜๋Š” ํŠน์ˆ˜ ๋ชฉ์  ๋งต์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋…์ž๋ฅผ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฒŒ ํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด ์—ฌ๊ธฐ์„œ๋Š” ์ด์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ์™ธ์—๋„ ๋™๊ธฐํ™” ๋ฌธ์ œ๋Š” ์˜ˆ์ œ์—์„œ๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ง€๋„ ์œ ํ˜•์˜ ์ „์ฒด ๋ชฉ๋ก์€ ๋‹ค์Œ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <linux/bpf.h>, ๊ทธ๋ฆฌ๊ณ  ์ด ์„น์…˜์—์„œ๋Š” ์—ญ์‚ฌ์ ์œผ๋กœ ์ฒซ ๋ฒˆ์งธ ์œ ํ˜•์ธ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์˜ˆ๋กœ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. BPF_MAP_TYPE_HASH.

์˜ˆ๋ฅผ ๋“ค์–ด C++๋กœ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ๋‹ˆ๋‹ค. unordered_map<int,long> woo, ๋Ÿฌ์‹œ์•„์–ด๋กœ "ํ…Œ์ด๋ธ”์ด ํ•„์š”ํ•ด์š”"๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. woo ํ‚ค ์œ ํ˜•์ด ๋ฌด์ œํ•œ์ธ ํฌ๊ธฐ int, ๊ฐ’์€ ์œ ํ˜•์ž…๋‹ˆ๋‹ค. long" BPF ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•˜๋ ค๋ฉด ํ…Œ์ด๋ธ”์˜ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ๊ณผ ํ‚ค์™€ ๊ฐ’์˜ ์œ ํ˜•์„ ์ง€์ •ํ•˜๋Š” ๋Œ€์‹  ํฌ๊ธฐ๋ฅผ ๋ฐ”์ดํŠธ ๋‹จ์œ„๋กœ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๋ฉด ๊ฑฐ์˜ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. . ์ง€๋„๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์„ธ์š”. BPF_MAP_CREATE ์‹œ์Šคํ…œ ํ˜ธ์ถœ bpf. ์ง€๋„๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ตœ์†Œํ•œ์˜ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๋Š” ์ด์ „ ํ”„๋กœ๊ทธ๋žจ ์ดํ›„์—๋Š” ๋‹ค์Œ ํ”„๋กœ๊ทธ๋žจ์ด ๊ฐ„๋‹จํ•ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

$ cat simple-map.c
#define _GNU_SOURCE
#include <string.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/bpf.h>

int main(void)
{
    union bpf_attr attr = {
        .map_type = BPF_MAP_TYPE_HASH,
        .key_size = sizeof(int),
        .value_size = sizeof(int),
        .max_entries = 4,
    };
    strncpy(attr.map_name, "woo", sizeof(attr.map_name));
    syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));

    for ( ;; )
        pause();
}

์—ฌ๊ธฐ์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ธํŠธ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. attr, ์—ฌ๊ธฐ์„œ๋Š” "ํ‚ค์™€ ํฌ๊ธฐ ๊ฐ’์ด ํฌํ•จ๋œ ํ•ด์‹œ ํ…Œ์ด๋ธ”์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. sizeof(int), ์ตœ๋Œ€ XNUMX๊ฐœ์˜ ์š”์†Œ๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค." BPF ๋งต์„ ์ƒ์„ฑํ•  ๋•Œ ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํ”„๋กœ๊ทธ๋žจ ์˜ˆ์ œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ฐ์ฒด ์ด๋ฆ„์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. "woo".

ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์‹คํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ clang -g -O2 simple-map.c -o simple-map
$ sudo strace ./simple-map
execve("./simple-map", ["./simple-map"], 0x7ffd40a27070 /* 14 vars */) = 0
...
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_HASH, key_size=4, value_size=4, max_entries=4, map_name="woo", ...}, 72) = 3
pause(

๋‹ค์Œ์€ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค. bpf(2) ์„ค๋ช…์ž ๋งต ๋ฒˆํ˜ธ๋ฅผ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค. 3 ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ”„๋กœ๊ทธ๋žจ์€ ์˜ˆ์ƒ๋Œ€๋กœ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์—์„œ ์ถ”๊ฐ€ ๋ช…๋ น์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. pause(2).

์ด์ œ ํ”„๋กœ๊ทธ๋žจ์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ๋ณด๋‚ด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ„ฐ๋ฏธ๋„์„ ์—ด๊ณ  ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ์ฒด๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpftool (์šฐ๋ฆฌ ์ง€๋„๋Š” ์ด๋ฆ„์œผ๋กœ ๋‹ค๋ฅธ ์ง€๋„์™€ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค):

$ sudo bpftool map
...
114: hash  name woo  flags 0x0
        key 4B  value 4B  max_entries 4  memlock 4096B
...

์ˆซ์ž 114๋Š” ๊ฐ์ฒด์˜ ์ „์—ญ ID์ž…๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  ํ”„๋กœ๊ทธ๋žจ์€ ์ด ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ์กด ์ง€๋„๋ฅผ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. BPF_MAP_GET_FD_BY_ID ์‹œ์Šคํ…œ ํ˜ธ์ถœ bpf.

์ด์ œ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ฐ€์ง€๊ณ  ๋†€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด์ž:

$ sudo bpftool map dump id 114
Found 0 elements

๋น„์–ด ์žˆ๋Š”. ๊ฐ’์„ ๋„ฃ์–ด๋ณด์ž hash[1] = 1:

$ sudo bpftool map update id 114 key 1 0 0 0 value 1 0 0 0

ํ‘œ๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo bpftool map dump id 114
key: 01 00 00 00  value: 01 00 00 00
Found 1 element

๋งŒ์„ธ! ์šฐ๋ฆฌ๋Š” ํ•˜๋‚˜์˜ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋ฐ”์ดํŠธ ์ˆ˜์ค€์—์„œ ์ž‘์—…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. bptftool ํ•ด์‹œ ํ…Œ์ด๋ธ”์˜ ๊ฐ’์ด ์–ด๋–ค ์œ ํ˜•์ธ์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. (์ด ์ง€์‹์€ BTF๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ทธ๋…€์—๊ฒŒ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์ง€๊ธˆ์€ ์ด์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.)

bpftool์€ ์š”์†Œ๋ฅผ ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์ฝ๊ณ  ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๊นŒ? ๋‚ด๋ถ€๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo strace -e bpf bpftool map dump id 114
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_MAP_GET_NEXT_KEY, {map_fd=3, key=NULL, next_key=0x55856ab65280}, 120) = 0
bpf(BPF_MAP_LOOKUP_ELEM, {map_fd=3, key=0x55856ab65280, value=0x55856ab652a0}, 120) = 0
key: 01 00 00 00  value: 01 00 00 00
bpf(BPF_MAP_GET_NEXT_KEY, {map_fd=3, key=0x55856ab65280, next_key=0x55856ab65280}, 120) = -1 ENOENT

๋จผ์ € ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ์ „์—ญ ID๋กœ ์ง€๋„๋ฅผ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. BPF_MAP_GET_FD_BY_ID ะธ bpf(2) ์„ค๋ช…์ž 3์„ ์šฐ๋ฆฌ์—๊ฒŒ ๋ฐ˜ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ถ”๊ฐ€๋กœ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ BPF_MAP_GET_NEXT_KEY ๋‹ค์Œ์„ ์ „๋‹ฌํ•˜์—ฌ ํ…Œ์ด๋ธ”์˜ ์ฒซ ๋ฒˆ์งธ ํ‚ค๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. NULL "์ด์ „" ํ‚ค์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์—ด์‡ ๊ฐ€ ์žˆ๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ํ•  ์ˆ˜ ์žˆ๋‹ค BPF_MAP_LOOKUP_ELEMํฌ์ธํ„ฐ์— ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. value. ๋‹ค์Œ ๋‹จ๊ณ„๋Š” ํ˜„์žฌ ํ‚ค์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๋‹ค์Œ ์š”์†Œ๋ฅผ ์ฐพ์œผ๋ ค๊ณ  ์‹œ๋„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ…Œ์ด๋ธ”์—๋Š” ํ•˜๋‚˜์˜ ์š”์†Œ์™€ ๋ช…๋ น๋งŒ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. BPF_MAP_GET_NEXT_KEY ๋ฐ˜ํ™˜ ENOENT.

์ข‹์•„์š”, ํ‚ค 1์˜ ๊ฐ’์„ ๋ณ€๊ฒฝํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋“ฑ๋ก์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. hash[1] = 2:

$ sudo strace -e bpf bpftool map update id 114 key 1 0 0 0 value 2 0 0 0
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x55dcd72be260, value=0x55dcd72be280, flags=BPF_ANY}, 120) = 0

์˜ˆ์ƒ๋Œ€๋กœ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. BPF_MAP_GET_FD_BY_ID ID๋กœ ์ง€๋„๋ฅผ ์—ด๊ณ  ๋‹ค์Œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. BPF_MAP_UPDATE_ELEM ์š”์†Œ๋ฅผ ๋ฎ์–ด์”๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ•œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“  ํ›„ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ์—์„œ ํ•ด๋‹น ๋‚ด์šฉ์„ ์ฝ๊ณ  ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช…๋ น์ค„์—์„œ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋žจ๋„ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ช…๋ น ์™ธ์—๋„ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ง€๋„ ์ž‘์—…์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ:

  • BPF_MAP_LOOKUP_ELEM: ํ‚ค๋กœ ๊ฐ’ ์ฐพ๊ธฐ
  • BPF_MAP_UPDATE_ELEM: ๊ฐ’ ์—…๋ฐ์ดํŠธ/์ƒ์„ฑ
  • BPF_MAP_DELETE_ELEM: ํ‚ค ์ œ๊ฑฐ
  • BPF_MAP_GET_NEXT_KEY: ๋‹ค์Œ(๋˜๋Š” ์ฒซ ๋ฒˆ์งธ) ํ‚ค๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
  • BPF_MAP_GET_NEXT_ID: ๊ธฐ์กด์˜ ๋ชจ๋“  ์ง€๋„๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์ž‘๋™ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. bpftool map
  • BPF_MAP_GET_FD_BY_ID: ๊ธ€๋กœ๋ฒŒ ID๋กœ ๊ธฐ์กด ์ง€๋„๋ฅผ ์—ฝ๋‹ˆ๋‹ค.
  • BPF_MAP_LOOKUP_AND_DELETE_ELEM: ๊ฐ์ฒด์˜ ๊ฐ’์„ ์›์ž์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ์ด์ „ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • BPF_MAP_FREEZE: ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ง€๋„๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋„๋ก ๋งŒ๋“ญ๋‹ˆ๋‹ค(์ด ์ž‘์—…์€ ์ทจ์†Œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค).
  • BPF_MAP_LOOKUP_BATCH, BPF_MAP_LOOKUP_AND_DELETE_BATCH, BPF_MAP_UPDATE_BATCH, BPF_MAP_DELETE_BATCH: ๋Œ€๋Ÿ‰ ์ž‘์—…. ์˜ˆ๋ฅผ ๋“ค์–ด, BPF_MAP_LOOKUP_AND_DELETE_BATCH - ์ง€๋„์—์„œ ๋ชจ๋“  ๊ฐ’์„ ์ฝ๊ณ  ์žฌ์„ค์ •ํ•˜๋Š” ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ชจ๋“  ๋ช…๋ น์ด ๋ชจ๋“  ๋งต ์œ ํ˜•์— ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ๋‹ค๋ฅธ ์œ ํ˜•์˜ ๋งต์„ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์€ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…๊ณผ ์™„์ „ํžˆ ๋™์ผํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

์ˆœ์„œ๋ฅผ ์œ„ํ•ด ํ•ด์‹œ ํ…Œ์ด๋ธ” ์‹คํ—˜์„ ๋งˆ์น˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ตœ๋Œ€ XNUMX๊ฐœ์˜ ํ‚ค๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์‹œ๋‚˜์š”? ๋ช‡ ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ๋” ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo bpftool map update id 114 key 2 0 0 0 value 1 0 0 0
$ sudo bpftool map update id 114 key 3 0 0 0 value 1 0 0 0
$ sudo bpftool map update id 114 key 4 0 0 0 value 1 0 0 0

์—ฌํƒœ๊นŒ์ง€๋Š” ๊ทธ๋Ÿฐ๋Œ€๋กœ ์ž˜๋๋‹ค:

$ sudo bpftool map dump id 114
key: 01 00 00 00  value: 01 00 00 00
key: 02 00 00 00  value: 01 00 00 00
key: 04 00 00 00  value: 01 00 00 00
key: 03 00 00 00  value: 01 00 00 00
Found 4 elements

ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo bpftool map update id 114 key 5 0 0 0 value 1 0 0 0
Error: update failed: Argument list too long

์˜ˆ์ƒ๋Œ€๋กœ ์šฐ๋ฆฌ๋Š” ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜๋ฅผ ๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo strace -e bpf bpftool map update id 114 key 5 0 0 0 value 1 0 0 0
bpf(BPF_MAP_GET_FD_BY_ID, {map_id=114, next_id=0, open_flags=0}, 120) = 3
bpf(BPF_OBJ_GET_INFO_BY_FD, {info={bpf_fd=3, info_len=80, info=0x7ffe6c626da0}}, 120) = 0
bpf(BPF_MAP_UPDATE_ELEM, {map_fd=3, key=0x56049ded5260, value=0x56049ded5280, flags=BPF_ANY}, 120) = -1 E2BIG (Argument list too long)
Error: update failed: Argument list too long
+++ exited with 255 +++

๋ชจ๋“  ๊ฒƒ์ด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ƒ๋Œ€๋กœ ํŒ€์€ BPF_MAP_UPDATE_ELEM ์ƒˆ๋กœ์šด ๋‹ค์„ฏ ๋ฒˆ์งธ ํ‚ค๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. E2BIG.

๋”ฐ๋ผ์„œ BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ  ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ์ง€๋„๋ฅผ ๋งŒ๋“ค๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ BPF ํ”„๋กœ๊ทธ๋žจ ์ž์ฒด์˜ ๋งต์„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ์ด ๋…ผ๋ฆฌ์ ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ธฐ๊ณ„ ๋งคํฌ๋กœ ์ฝ”๋“œ์—์„œ ์ฝ๊ธฐ ์–ด๋ ค์šด ํ”„๋กœ๊ทธ๋žจ์˜ ์–ธ์–ด๋กœ ์ด์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” BPF ํ”„๋กœ๊ทธ๋žจ์ด ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑ๋˜๊ณ  ์œ ์ง€๋˜๋Š”์ง€ ๋ณด์—ฌ์ค„ ๋•Œ๊ฐ€ ์™”์Šต๋‹ˆ๋‹ค. libbpf.

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

libbpf๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BPF ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ

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

์‹ค์ œ๋กœ, ์ด ๊ธฐ์‚ฌ์™€ ํ›„์† ๊ธฐ์‚ฌ์—์„œ ์‚ดํŽด๋ณด๊ฒ ์ง€๋งŒ, libbpf ๊ทธ๊ฒƒ(๋˜๋Š” ์œ ์‚ฌํ•œ ๋„๊ตฌ) ์—†์ด๋„ ๊ฝค ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. iproute2, libbcc, libbpf-go, ๋“ฑ) ์‚ฌ๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ํ‚ฌ๋Ÿฌ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜ libbpf BPF CO-RE(Compile Once, Run Everywhere) - ๋‹ค๋ฅธ API์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•œ ์ปค๋„์—์„œ ๋‹ค๋ฅธ ์ปค๋„๋กœ ์ด์‹ ๊ฐ€๋Šฅํ•œ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค(์˜ˆ: ์ปค๋„ ๊ตฌ์กฐ๊ฐ€ ๋ฒ„์ „์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ) ๋ฒ„์ „). CO-RE๋กœ ์ž‘์—…ํ•˜๋ ค๋ฉด ์ปค๋„์ด BTF ์ง€์›์œผ๋กœ ์ปดํŒŒ์ผ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์„น์…˜์—์„œ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค). ๊ฐœ๋ฐœ ๋„๊ตฌ. ๋‹ค์Œ ํŒŒ์ผ์ด ์žˆ์œผ๋ฉด ์ปค๋„์ด BTF๋กœ ๋นŒ๋“œ๋˜์—ˆ๋Š”์ง€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ ls -lh /sys/kernel/btf/vmlinux
-r--r--r-- 1 root root 2.6M Jul 29 15:30 /sys/kernel/btf/vmlinux

์ด ํŒŒ์ผ์€ ์ปค๋„์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์œ ํ˜•์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋ฉฐ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์˜ˆ์ œ์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. libbpf. ๋‹ค์Œ ๊ธฐ์‚ฌ์—์„œ CO-RE์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์ง€๋งŒ, ์ด๋ฒˆ ๊ธฐ์‚ฌ์—์„œ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์„ ์ง์ ‘ ๋นŒ๋“œํ•ด ๋ณด์„ธ์š”. CONFIG_DEBUG_INFO_BTF.

๋„์„œ๊ด€ libbpf ๋””๋ ‰ํ† ๋ฆฌ์— ๋ฐ”๋กœ ์‚ด์•„์š” tools/lib/bpf ์ปค๋„๊ณผ ๊ทธ ๊ฐœ๋ฐœ์€ ๋ฉ”์ผ๋ง ๋ฆฌ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. [email protected]. ๊ทธ๋Ÿฌ๋‚˜ ์ปค๋„ ์™ธ๋ถ€์— ์žˆ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์š”๊ตฌ์— ๋”ฐ๋ผ ๋ณ„๋„์˜ ์ €์žฅ์†Œ๊ฐ€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. https://github.com/libbpf/libbpf ์ปค๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ฝ๊ธฐ ์•ก์„ธ์Šค๋ฅผ ์œ„ํ•ด ๊ฑฐ์˜ ๊ทธ๋Œ€๋กœ ๋ฏธ๋Ÿฌ๋ง๋ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ ์„น์…˜์—์„œ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. libbpf, ์—ฌ๋Ÿฌ ๊ฐ€์ง€(๋‹ค์†Œ ์˜๋ฏธ ์—†๋Š”) ํ…Œ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ณ  ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž์„ธํžˆ ๋ถ„์„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋‹ค์Œ ์„น์…˜์—์„œ BPF ํ”„๋กœ๊ทธ๋žจ์ด ๋งต, ์ปค๋„ ๋„์šฐ๋ฏธ, BTF ๋“ฑ๊ณผ ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š”์ง€ ์ •ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ libbpf GitHub ์ €์žฅ์†Œ๋ฅผ git ํ•˜์œ„ ๋ชจ๋“ˆ๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

$ mkdir /tmp/libbpf-example
$ cd /tmp/libbpf-example/
$ git init-db
Initialized empty Git repository in /tmp/libbpf-example/.git/
$ git submodule add https://github.com/libbpf/libbpf.git
Cloning into '/tmp/libbpf-example/libbpf'...
remote: Enumerating objects: 200, done.
remote: Counting objects: 100% (200/200), done.
remote: Compressing objects: 100% (103/103), done.
remote: Total 3354 (delta 101), reused 118 (delta 79), pack-reused 3154
Receiving objects: 100% (3354/3354), 2.05 MiB | 10.22 MiB/s, done.
Resolving deltas: 100% (2176/2176), done.

๊ฐ€๋‹ค libbpf ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค :

$ cd libbpf/src
$ mkdir build
$ OBJDIR=build DESTDIR=root make -s install
$ find root
root
root/usr
root/usr/include
root/usr/include/bpf
root/usr/include/bpf/bpf_tracing.h
root/usr/include/bpf/xsk.h
root/usr/include/bpf/libbpf_common.h
root/usr/include/bpf/bpf_endian.h
root/usr/include/bpf/bpf_helpers.h
root/usr/include/bpf/btf.h
root/usr/include/bpf/bpf_helper_defs.h
root/usr/include/bpf/bpf.h
root/usr/include/bpf/libbpf_util.h
root/usr/include/bpf/libbpf.h
root/usr/include/bpf/bpf_core_read.h
root/usr/lib64
root/usr/lib64/libbpf.so.0.1.0
root/usr/lib64/libbpf.so.0
root/usr/lib64/libbpf.a
root/usr/lib64/libbpf.so
root/usr/lib64/pkgconfig
root/usr/lib64/pkgconfig/libbpf.pc

์ด ์„น์…˜์˜ ๋‹ค์Œ ๊ณ„ํš์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. BPF_PROG_TYPE_XDP, ์ด์ „ ์˜ˆ์ œ์™€ ๋™์ผํ•˜์ง€๋งŒ C์—์„œ๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํŒŒ์ผํ•ฉ๋‹ˆ๋‹ค. clang, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์ปค๋„์— ๋กœ๋“œํ•  ๋„์šฐ๋ฏธ ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” BPF ํ”„๋กœ๊ทธ๋žจ๊ณผ ๋ณด์กฐ ํ”„๋กœ๊ทธ๋žจ์˜ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ํ™•์žฅํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ: libbpf๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™„์ „ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค๊ธฐ

์šฐ์„ , ์šฐ๋ฆฌ๋Š” ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค /sys/kernel/btf/vmlinux์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ํ—ค๋” ํŒŒ์ผ ํ˜•์‹์œผ๋กœ ์ด์— ์ƒ์‘ํ•˜๋Š” ํ•ญ๋ชฉ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

$ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

์ด ํŒŒ์ผ์€ ์ปค๋„์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์ปค๋„์—์„œ IPv4 ํ—ค๋”๊ฐ€ ์ •์˜๋˜๋Š” ๋ฐฉ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

$ grep -A 12 'struct iphdr {' vmlinux.h
struct iphdr {
    __u8 ihl: 4;
    __u8 version: 4;
    __u8 tos;
    __be16 tot_len;
    __be16 id;
    __be16 frag_off;
    __u8 ttl;
    __u8 protocol;
    __sum16 check;
    __be32 saddr;
    __be32 daddr;
};

์ด์ œ C๋กœ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

$ cat xdp-simple.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

SEC("xdp/simple")
int simple(void *ctx)
{
        return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ๊ฒƒ์œผ๋กœ ํŒ๋ช…๋˜์—ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋งŽ์€ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ์ฃผ์˜๋ฅผ ๊ธฐ์šธ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋จผ์ €, ์šฐ๋ฆฌ๊ฐ€ ํฌํ•จํ•˜๋Š” ์ฒซ ๋ฒˆ์งธ ํ—ค๋” ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. vmlinux.h, ๋ฐฉ๊ธˆ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. bpftool btf dump - ์ด์ œ ์ปค๋„ ๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด kernel-headers ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ํ—ค๋” ํŒŒ์ผ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์šฐ๋ฆฌ์—๊ฒŒ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค libbpf. ์ด์ œ ๋งคํฌ๋กœ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐ๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. SEC, ELF ๊ฐœ์ฒด ํŒŒ์ผ์˜ ํ•ด๋‹น ์„น์…˜์œผ๋กœ ๋ฌธ์ž๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ์„น์…˜์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค xdp/simple, ์Šฌ๋ž˜์‹œ ์•ž์—๋Š” ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜• BPF๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค์Œ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๊ทœ์น™์ž…๋‹ˆ๋‹ค. libbpf, ์„น์…˜ ์ด๋ฆ„์— ๋”ฐ๋ผ ์‹œ์ž‘ ์‹œ ์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜•์œผ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. bpf(2). BPF ํ”„๋กœ๊ทธ๋žจ ์ž์ฒด๋Š” C - ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋ฉฐ ํ•œ ์ค„๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. return XDP_PASS. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ณ„๋„์˜ ์„น์…˜ "license" ๋ผ์ด์„ผ์Šค ์ด๋ฆ„์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

llvm/clang, ๋ฒ„์ „ >= 10.0.0 ๋˜๋Š” ๋” ๋‚˜์€ ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์„น์…˜ ์ฐธ์กฐ). ๊ฐœ๋ฐœ ๋„๊ตฌ):

$ clang --version
clang version 11.0.0 (https://github.com/llvm/llvm-project.git afc287e0abec710398465ee1f86237513f2b5091)
...

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o

ํฅ๋ฏธ๋กœ์šด ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ๋Œ€์ƒ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. -target bpf ๊ทธ๋ฆฌ๊ณ  ํ—ค๋”์˜ ๊ฒฝ๋กœ libbpf, ์šฐ๋ฆฌ๊ฐ€ ์ตœ๊ทผ์— ์„ค์น˜ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์žŠ์ง€ ๋งˆ์„ธ์š” -O2, ์ด ์˜ต์…˜์ด ์—†์œผ๋ฉด ๋‚˜์ค‘์— ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์ผ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‚˜์š”?

$ llvm-objdump --section=xdp/simple --no-show-raw-insn -D xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       r0 = 2
       1:       exit

์˜ˆ, ํšจ๊ณผ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค! ์ด์ œ ํ”„๋กœ๊ทธ๋žจ์ด ํฌํ•จ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์ด ์žˆ๊ณ  ์ด๋ฅผ ์ปค๋„์— ๋กœ๋“œํ•  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๋„์„œ๊ด€ libbpf ํ•˜์œ„ ์ˆ˜์ค€ API ๋˜๋Š” ์ƒ์œ„ ์ˆ˜์ค€ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ›„์† ์—ฐ๊ตฌ๋ฅผ ์œ„ํ•ด ์ตœ์†Œํ•œ์˜ ๋…ธ๋ ฅ์œผ๋กœ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑ, ๋กœ๋“œ ๋ฐ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ฐˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋จผ์ €, ๋™์ผํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ํ”„๋กœ๊ทธ๋žจ์˜ "๊ณจ๊ฒฉ"์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. bpftool โ€” BPF ์„ธ๊ณ„์˜ ์Šค์œ„์Šค ์นผ(BPF์˜ ์ฐฝ์‹œ์ž์ด์ž ์œ ์ง€๊ด€๋ฆฌ์ž ์ค‘ ํ•œ ๋ช…์ธ Daniel Borkman์ด ์Šค์œ„์Šค ์‚ฌ๋žŒ์ด๋ฏ€๋กœ ๋ฌธ์ž ๊ทธ๋Œ€๋กœ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ์Œ):

$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h

ํŒŒ์ผ์—์„œ xdp-simple.skel.h ์—ฌ๊ธฐ์—๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ์ฝ”๋“œ์™€ ๊ฐ์ฒด ๋กœ๋“œ, ์ฒจ๋ถ€, ์‚ญ์ œ ๋“ฑ์˜ ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ ์ด๋Š” ๊ณผ์ž‰์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ๊ฐ์ฒด ํŒŒ์ผ์— ๋งŽ์€ BPF ํ”„๋กœ๊ทธ๋žจ๊ณผ ๋งต์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ์ž‘๋™ํ•˜๋ฉฐ ์ด ๊ฑฐ๋Œ€ํ•œ ELF๋ฅผ ๋กœ๋“œํ•˜๋ ค๋ฉด ๋ผˆ๋Œ€๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ•˜๋‚˜ ๋˜๋Š” ๋‘ ๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ ์“ฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๊ณ„์† ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์šฐ๋ฆฌ์˜ ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค:

#include <err.h>
#include <unistd.h>
#include "xdp-simple.skel.h"

int main(int argc, char **argv)
{
    struct xdp_simple_bpf *obj;

    obj = xdp_simple_bpf__open_and_load();
    if (!obj)
        err(1, "failed to open and/or load BPF objectn");

    pause();

    xdp_simple_bpf__destroy(obj);
}

์—ฌ๊ธฐ์— struct xdp_simple_bpf ํŒŒ์ผ์— ์ •์˜๋˜์–ด ์žˆ์Œ xdp-simple.skel.h ๊ฐ์ฒด ํŒŒ์ผ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

struct xdp_simple_bpf {
    struct bpf_object_skeleton *skeleton;
    struct bpf_object *obj;
    struct {
        struct bpf_program *simple;
    } progs;
    struct {
        struct bpf_link *simple;
    } links;
};

์—ฌ๊ธฐ์„œ๋Š” ํ•˜์œ„ ์ˆ˜์ค€ API์˜ ํ”์ ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. struct bpf_program *simple ะธ struct bpf_link *simple. ์ฒซ ๋ฒˆ์งธ ๊ตฌ์กฐ๋Š” ์„น์…˜์— ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์„ ๊ตฌ์ฒด์ ์œผ๋กœ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. xdp/simple, ๋‘ ๋ฒˆ์งธ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋Šฅ xdp_simple_bpf__open_and_load, ELF ๊ฐœ์ฒด๋ฅผ ์—ด๊ณ  ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ณ  ๋ชจ๋“  ๊ตฌ์กฐ์™€ ํ•˜์œ„ ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•œ ๋‹ค์Œ(ํ”„๋กœ๊ทธ๋žจ ์™ธ์—๋„ ELF์—๋Š” ๋ฐ์ดํ„ฐ, ์ฝ๊ธฐ ์ „์šฉ ๋ฐ์ดํ„ฐ, ๋””๋ฒ„๊น… ์ •๋ณด, ๋ผ์ด์„ผ์Šค ๋“ฑ์˜ ๋‹ค๋ฅธ ์„น์…˜๋„ ํฌํ•จ๋˜์–ด ์žˆ์Œ) ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์— ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ๋ถ€๋ฅด๋‹ค bpf, ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์‹คํ–‰ํ•˜์—ฌ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ clang -O2 -I ./libbpf/src/root/usr/include/ xdp-simple.c -o xdp-simple ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz

$ sudo strace -e bpf ./xdp-simple
...
bpf(BPF_BTF_LOAD, 0x7ffdb8fd9670, 120)  = 3
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=2, insns=0xdfd580, license="GPL", log_level=0, log_size=0, log_buf=NULL, kern_version=KERNEL_VERSION(5, 8, 0), prog_flags=0, prog_name="simple", prog_ifindex=0, expected_attach_type=0x25 /* BPF_??? */, ...}, 120) = 4

์ด์ œ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpftool. ๊ทธ๋…€์˜ ID๋ฅผ ์ฐพ์•„๋ณด์ž:

# bpftool p | grep -A4 simple
463: xdp  name simple  tag 3b185187f1855c4c  gpl
        loaded_at 2020-08-01T01:59:49+0000  uid 0
        xlated 16B  jited 40B  memlock 4096B
        btf_id 185
        pids xdp-simple(16498)

๋ฐ ๋คํ”„(๋ช…๋ น์˜ ๋‹จ์ถ• ํ˜•์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. bpftool prog dump xlated):

# bpftool p d x id 463
int simple(void *ctx):
; return XDP_PASS;
   0: (b7) r0 = 2
   1: (95) exit

๋ญ”๊ฐ€ ์ƒˆ๋กœ์šด ๊ฒƒ์„! ํ”„๋กœ๊ทธ๋žจ์€ C ์†Œ์Šค ํŒŒ์ผ์˜ ๋ฉ์–ด๋ฆฌ๋ฅผ ์ธ์‡„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์˜ํ•ด ์ˆ˜ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. libbpf, ๋ฐ”์ด๋„ˆ๋ฆฌ์—์„œ ๋””๋ฒ„๊ทธ ์„น์…˜์„ ์ฐพ์•„ BTF ๊ฐœ์ฒด๋กœ ์ปดํŒŒ์ผํ•˜๊ณ  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์— ๋กœ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค. BPF_BTF_LOAD, ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•  ๋•Œ ๊ฒฐ๊ณผ ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. BPG_PROG_LOAD.

์ปค๋„ ๋„์šฐ๋ฏธ

BPF ํ”„๋กœ๊ทธ๋žจ์€ "์™ธ๋ถ€" ๊ธฐ๋Šฅ(์ปค๋„ ๋„์šฐ๋ฏธ)์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋„์šฐ๋ฏธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด BPF ํ”„๋กœ๊ทธ๋žจ์ด ์ปค๋„ ๊ตฌ์กฐ์— ์•ก์„ธ์Šคํ•˜๊ณ , ๋งต์„ ๊ด€๋ฆฌํ•˜๊ณ , ์„ฑ๋Šฅ ์ด๋ฒคํŠธ ์ƒ์„ฑ, ํ•˜๋“œ์›จ์–ด ์ œ์–ด(์˜ˆ: ํŒจํ‚ท ๋ฆฌ๋””๋ ‰์…˜) ๋“ฑ "์‹ค์ œ ์„ธ๊ณ„"์™€ ํ†ต์‹ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ: bpf_get_smp_processor_id

"์˜ˆ๋ฅผ ํ†ตํ•œ ํ•™์Šต" ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ํ‹€ ๋‚ด์—์„œ ๋„์šฐ๋ฏธ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ณ ๋ คํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpf_get_smp_processor_id(), ํ™•์‹คํ•œ ํŒŒ์ผ์— kernel/bpf/helpers.c. ์ด๋ฅผ ํ˜ธ์ถœํ•œ BPF ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์„œ์˜ ๋ฒˆํ˜ธ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ๊ตฌํ˜„์ด ํ•œ ์ค„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค๋Š” ์‚ฌ์‹ค๋งŒํผ ์˜๋ฏธ๋ก ์— ๊ด€์‹ฌ์ด ์—†์Šต๋‹ˆ๋‹ค.

BPF_CALL_0(bpf_get_smp_processor_id)
{
    return smp_processor_id();
}

BPF ๋„์šฐ๋ฏธ ํ•จ์ˆ˜ ์ •์˜๋Š” Linux ์‹œ์Šคํ…œ ํ˜ธ์ถœ ์ •์˜์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ˆ˜๊ฐ€ ์—†๋Š” ํ•จ์ˆ˜๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. (๊ฐ€๋ น ์„ธ ๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ์ทจํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์˜๋ฉ๋‹ˆ๋‹ค. BPF_CALL_3. ์ตœ๋Œ€ ์ธ์ˆ˜ ์ˆ˜๋Š” XNUMX๊ฐœ์ž…๋‹ˆ๋‹ค.) ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์ •์˜์˜ ์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ถ€๋ถ„์€ ์œ ํ˜• ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. struct bpf_func_proto์—๋Š” ๊ฒ€์ฆ์ž๊ฐ€ ์ดํ•ดํ•˜๋Š” ๋„์šฐ๋ฏธ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ์„ค๋ช…์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

const struct bpf_func_proto bpf_get_smp_processor_id_proto = {
    .func     = bpf_get_smp_processor_id,
    .gpl_only = false,
    .ret_type = RET_INTEGER,
};

๋„์šฐ๋ฏธ ํ•จ์ˆ˜ ๋“ฑ๋ก

ํŠน์ • ์œ ํ˜•์˜ BPF ํ”„๋กœ๊ทธ๋žจ์ด ์ด ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ด๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. BPF_PROG_TYPE_XDP ํ•จ์ˆ˜๋Š” ์ปค๋„์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค xdp_func_proto, ๋„์šฐ๋ฏธ ๊ธฐ๋Šฅ ID๋ฅผ ํ†ตํ•ด XDP๊ฐ€ ์ด ๊ธฐ๋Šฅ์„ ์ง€์›ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ ๊ธฐ๋Šฅ์€ ะฟะพะดะดะตั€ะถะธะฒะฐะตั‚:

static const struct bpf_func_proto *
xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
    switch (func_id) {
    ...
    case BPF_FUNC_get_smp_processor_id:
        return &bpf_get_smp_processor_id_proto;
    ...
    }
}

์ƒˆ๋กœ์šด BPF ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•์€ ํŒŒ์ผ์— "์ •์˜"๋ฉ๋‹ˆ๋‹ค. include/linux/bpf_types.h ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ BPF_PROG_TYPE. ๋…ผ๋ฆฌ์ ์ธ ์ •์˜์ด๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ์˜ดํ‘œ๋กœ ์ •์˜ํ•˜๊ณ , C ์–ธ์–ด ์šฉ์–ด์—์„œ๋Š” ๊ตฌ์ฒด์ ์ธ ๊ตฌ์กฐ ์ „์ฒด ์ง‘ํ•ฉ์˜ ์ •์˜๊ฐ€ ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ํŒŒ์ผ์—๋Š” kernel/bpf/verifier.c ํŒŒ์ผ์˜ ๋ชจ๋“  ์ •์˜ bpf_types.h ๊ตฌ์กฐ์ฒด ๋ฐฐ์—ด์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. bpf_verifier_ops[]:

static const struct bpf_verifier_ops *const bpf_verifier_ops[] = {
#define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type) 
    [_id] = & _name ## _verifier_ops,
#include <linux/bpf_types.h>
#undef BPF_PROG_TYPE
};

์ฆ‰, BPF ํ”„๋กœ๊ทธ๋žจ์˜ ๊ฐ ์œ ํ˜•์— ๋Œ€ํ•ด ํ•ด๋‹น ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ์ •์˜๋ฉ๋‹ˆ๋‹ค. struct bpf_verifier_ops, ์ด๋Š” ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. _name ## _verifier_ops, ์ฆ‰., xdp_verifier_ops ์— xdp. ๊ตฌ์กฐ xdp_verifier_ops ์— ์˜ํ•ด ๊ฒฐ์ • ํŒŒ์ผ์— net/core/filter.c ๋‹ค์Œ๊ณผ ๊ฐ™์ด

const struct bpf_verifier_ops xdp_verifier_ops = {
    .get_func_proto     = xdp_func_proto,
    .is_valid_access    = xdp_is_valid_access,
    .convert_ctx_access = xdp_convert_ctx_access,
    .gen_prologue       = bpf_noop_prologue,
};

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ์นœ์ˆ™ํ•œ ๊ธฐ๋Šฅ์„ ๋ด…๋‹ˆ๋‹ค. xdp_func_proto, ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๊ฒ€์ฆ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ์ข…๋ฅ˜ BPF ํ”„๋กœ๊ทธ๋žจ ๋‚ด๋ถ€์˜ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”. verifier.c.

๊ฐ€์ƒ์˜ BPF ํ”„๋กœ๊ทธ๋žจ์ด ์ด ํ•จ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. bpf_get_smp_processor_id. ์ด๋ฅผ ์œ„ํ•ด ์ด์ „ ์„น์…˜์˜ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์‹œ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

SEC("xdp/simple")
int simple(void *ctx)
{
    if (bpf_get_smp_processor_id() != 0)
        return XDP_DROP;
    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

์ƒ์ง• bpf_get_smp_processor_id ์— ์˜ํ•ด ๊ฒฐ์ • ะฒ <bpf/bpf_helper_defs.h> ๋„์„œ๊ด€ libbpf ะบะฐะบ

static u32 (*bpf_get_smp_processor_id)(void) = (void *) 8;

๊ทธ๊ฑด, bpf_get_smp_processor_id ๊ฐ’์ด 8์ธ ํ•จ์ˆ˜ ํฌ์ธํ„ฐ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ 8์€ ๊ฐ’์ž…๋‹ˆ๋‹ค. BPF_FUNC_get_smp_processor_id ั‚ะธะฟะฐ enum bpf_fun_id, ์ด๋Š” ํŒŒ์ผ์— ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. vmlinux.h (ํŒŒ์ผ bpf_helper_defs.h ์ปค๋„์—์„œ๋Š” ์Šคํฌ๋ฆฝํŠธ์— ์˜ํ•ด ์ƒ์„ฑ๋˜๋ฏ€๋กœ "๋งˆ๋ฒ•์˜" ์ˆซ์ž๋Š” ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค). ์ด ํ•จ์ˆ˜๋Š” ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹ค์Œ ์œ ํ˜•์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. __u32. ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด๋ฅผ ์‹คํ–‰ํ•˜๋ฉด, clang ๋ช…๋ น์–ด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค BPF_CALL "์˜ฌ๋ฐ”๋ฅธ ์ข…๋ฅ˜" ํ”„๋กœ๊ทธ๋žจ์„ ์ปดํŒŒ์ผํ•˜๊ณ  ์„น์…˜์„ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. xdp/simple:

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o
$ llvm-objdump -D --section=xdp/simple xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       bf 01 00 00 00 00 00 00 r1 = r0
       2:       67 01 00 00 20 00 00 00 r1 <<= 32
       3:       77 01 00 00 20 00 00 00 r1 >>= 32
       4:       b7 00 00 00 02 00 00 00 r0 = 2
       5:       15 01 01 00 00 00 00 00 if r1 == 0 goto +1 <LBB0_2>
       6:       b7 00 00 00 01 00 00 00 r0 = 1

0000000000000038 <LBB0_2>:
       7:       95 00 00 00 00 00 00 00 exit

์ฒซ ๋ฒˆ์งธ ์ค„์—๋Š” ์ง€์นจ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. call, ๋งค๊ฐœ๋ณ€์ˆ˜ IMM ์ด๋Š” 8๊ณผ ๊ฐ™๊ณ , SRC_REG - ์˜. ๊ฒ€์ฆ์ž๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ABI ๊ณ„์•ฝ์— ๋”ฐ๋ฅด๋ฉด ์ด๋Š” ๋„์šฐ๋ฏธ ํ•จ์ˆ˜ ๋ฒˆํ˜ธ XNUMX์— ๋Œ€ํ•œ ํ˜ธ์ถœ์ž…๋‹ˆ๋‹ค. ์ผ๋‹จ ์‹คํ–‰๋˜๋ฉด ๋…ผ๋ฆฌ๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ ˆ์ง€์Šคํ„ฐ์˜ ๋ฐ˜ํ™˜ ๊ฐ’ r0 ๋ณต์‚ฌ๋จ r1 2,3ํ–‰์—์„œ๋Š” ๋‹ค์Œ ์œ ํ˜•์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. u32 โ€” ์ƒ์œ„ 32๋น„ํŠธ๊ฐ€ ์ง€์›Œ์ง‘๋‹ˆ๋‹ค. 4,5,6,7ํ–‰์—์„œ๋Š” 2(XDP_PASS) ๋˜๋Š” 1(XDP_DROP) 0ํ–‰์˜ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜๊ฐ€ XNUMX ๋˜๋Š” XNUMX์ด ์•„๋‹Œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์Šค์Šค๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด์ž: ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๊ณ  ์ถœ๋ ฅ์„ ์‚ดํŽด๋ณด์ž. bpftool prog dump xlated:

$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
$ clang -O2 -g -I ./libbpf/src/root/usr/include/ -o xdp-simple xdp-simple.c ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz
$ sudo ./xdp-simple &
[2] 10914

$ sudo bpftool p | grep simple
523: xdp  name simple  tag 44c38a10c657e1b0  gpl
        pids xdp-simple(10915)

$ sudo bpftool p d x id 523
int simple(void *ctx):
; if (bpf_get_smp_processor_id() != 0)
   0: (85) call bpf_get_smp_processor_id#114128
   1: (bf) r1 = r0
   2: (67) r1 <<= 32
   3: (77) r1 >>= 32
   4: (b7) r0 = 2
; }
   5: (15) if r1 == 0x0 goto pc+1
   6: (b7) r0 = 1
   7: (95) exit

์ข‹์Šต๋‹ˆ๋‹ค. ๊ฒ€์ฆ์ž๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ปค๋„ ๋„์šฐ๋ฏธ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.

์˜ˆ: ์ธ์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค!

๋ชจ๋“  ์‹คํ–‰ ์ˆ˜์ค€ ๋„์šฐ๋ฏธ ํ•จ์ˆ˜์—๋Š” ํ”„๋กœํ† ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

u64 fn(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)

๋„์šฐ๋ฏธ ํ•จ์ˆ˜์— ๋Œ€ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ ˆ์ง€์Šคํ„ฐ์— ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค. r1-r5, ๊ฐ’์€ ๋ ˆ์ง€์Šคํ„ฐ์— ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. r0. XNUMX๊ฐœ ์ด์ƒ์˜ ์ธ์ˆ˜๋ฅผ ์ทจํ•˜๋Š” ํ•จ์ˆ˜๋Š” ์—†์œผ๋ฉฐ ์ด์— ๋Œ€ํ•œ ์ง€์›์€ ํ–ฅํ›„ ์ถ”๊ฐ€๋˜์ง€ ์•Š์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒ๋ฉ๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ์ปค๋„ ๋„์šฐ๋ฏธ์™€ BPF๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ์“ฐ์ž xdp-simple.bpf.c ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(๋‚˜๋จธ์ง€ ์ค„์€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค).

SEC("xdp/simple")
int simple(void *ctx)
{
    bpf_printk("running on CPU%un", bpf_get_smp_processor_id());
    return XDP_PASS;
}

์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์€ ์‹คํ–‰ ์ค‘์ธ CPU์˜ ๋ฒˆํ˜ธ๋ฅผ ์ธ์‡„ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์ปดํŒŒ์ผํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ llvm-objdump -D --section=xdp/simple --no-show-raw-insn xdp-simple.bpf.o

0000000000000000 <simple>:
       0:       r1 = 10
       1:       *(u16 *)(r10 - 8) = r1
       2:       r1 = 8441246879787806319 ll
       4:       *(u64 *)(r10 - 16) = r1
       5:       r1 = 2334956330918245746 ll
       7:       *(u64 *)(r10 - 24) = r1
       8:       call 8
       9:       r1 = r10
      10:       r1 += -24
      11:       r2 = 18
      12:       r3 = r0
      13:       call 6
      14:       r0 = 2
      15:       exit

0-7ํ–‰์—์„œ ๋ฌธ์ž์—ด์„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. running on CPU%un, ๊ทธ๋ฆฌ๊ณ  8๋ฒˆ์งธ ์ค„์—์„œ ์ต์ˆ™ํ•œ ๊ฒƒ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. bpf_get_smp_processor_id. 9-12ํ–‰์—์„œ๋Š” ๋„์šฐ๋ฏธ ์ธ์ˆ˜๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค. bpf_printk - ๋ ˆ์ง€์Šคํ„ฐ r1, r2, r3. ์™œ XNUMX๊ฐœ๊ฐ€ ์•„๋‹ˆ๊ณ  XNUMX๊ฐœ๊ฐ€ ์žˆ๋Š” ๊ฑธ๊นŒ์š”? ์™œ๋ƒํ•˜๋ฉด bpf_printk์ด๊ฒƒ์€ ๋งคํฌ๋กœ ๋ž˜ํผ์ž…๋‹ˆ๋‹ค ์ง„์งœ ๋„์šฐ๋ฏธ ์ฃผ์œ„์— bpf_trace_printk, ํ˜•์‹ ๋ฌธ์ž์—ด์˜ ํฌ๊ธฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋‘ ์ค„์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. xdp-simple.c์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์ด ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐ๋˜๋„๋ก lo ๊ทธ๋ฆฌ๊ณ  ์ •๋ง ์‹œ์ž‘ํ–ˆ์–ด์š”!

$ cat xdp-simple.c
#include <linux/if_link.h>
#include <err.h>
#include <unistd.h>
#include "xdp-simple.skel.h"

int main(int argc, char **argv)
{
    __u32 flags = XDP_FLAGS_SKB_MODE;
    struct xdp_simple_bpf *obj;

    obj = xdp_simple_bpf__open_and_load();
    if (!obj)
        err(1, "failed to open and/or load BPF objectn");

    bpf_set_link_xdp_fd(1, -1, flags);
    bpf_set_link_xdp_fd(1, bpf_program__fd(obj->progs.simple), flags);

cleanup:
    xdp_simple_bpf__destroy(obj);
}

์—ฌ๊ธฐ์„œ๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. bpf_set_link_xdp_fd, XDP ์œ ํ˜• BPF ํ”„๋กœ๊ทธ๋žจ์„ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ๋ฒˆํ˜ธ๋ฅผ ํ•˜๋“œ์ฝ”๋”ฉํ–ˆ์Šต๋‹ˆ๋‹ค. lo, ์ด๋Š” ํ•ญ์ƒ 1์ž…๋‹ˆ๋‹ค. ์ด์ „ ํ”„๋กœ๊ทธ๋žจ์ด ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ๋จผ์ € ๊ธฐ์กด ํ”„๋กœ๊ทธ๋žจ์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ํ•จ์ˆ˜๋ฅผ ๋‘ ๋ฒˆ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ๋Š” ๋„์ „์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. pause ๋˜๋Š” ๋ฌดํ•œ ๋ฃจํ”„: ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ์€ ์ข…๋ฃŒ๋˜์ง€๋งŒ BPF ํ”„๋กœ๊ทธ๋žจ์€ ์ด๋ฒคํŠธ ์†Œ์Šค์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์šด๋กœ๋“œ ๋ฐ ์—ฐ๊ฒฐ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด, ๋„์ฐฉํ•˜๋Š” ๊ฐ ๋„คํŠธ์›Œํฌ ํŒจํ‚ท์— ๋Œ€ํ•ด ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. lo.

ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ดํŽด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. lo:

$ sudo ./xdp-simple
$ sudo bpftool p | grep simple
669: xdp  name simple  tag 4fca62e77ccb43d6  gpl
$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 669

๋‹ค์šด๋กœ๋“œํ•œ ํ”„๋กœ๊ทธ๋žจ์˜ ID๋Š” 669์ด๋ฉฐ ์ธํ„ฐํŽ˜์ด์Šค์—๋„ ๋™์ผํ•œ ID๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. lo. ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ ์ฃผ์†Œ๋กœ ๋ช‡ ๊ฐœ์˜ ํŒจํ‚ค์ง€๋ฅผ ๋ณด๋‚ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. 127.0.0.1 (์š”์ฒญ + ์‘๋‹ต):

$ ping -c1 localhost

์ด์ œ ๋””๋ฒ„๊ทธ ๊ฐ€์ƒ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. /sys/kernel/debug/tracing/trace_pipe, ์–ด๋Š bpf_printk ๊ทธ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์”๋‹ˆ๋‹ค:

# cat /sys/kernel/debug/tracing/trace_pipe
ping-13937 [000] d.s1 442015.377014: bpf_trace_printk: running on CPU0
ping-13937 [000] d.s1 442015.377027: bpf_trace_printk: running on CPU0

๋‘ ๊ฐœ์˜ ํŒจํ‚ค์ง€๊ฐ€ ๋ฐœ๊ฒฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. lo CPU0์—์„œ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ณธ๊ฒฉ์ ์ธ ์˜๋ฏธ ์—†๋Š” BPF ํ”„๋กœ๊ทธ๋žจ์ด ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค!

์ฃผ๋ชฉํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. bpf_printk ๋””๋ฒ„๊ทธ ํŒŒ์ผ์— ๊ธฐ๋กํ•˜๋Š” ๊ฒƒ์€ ์•„๋ฌด๊ฒƒ๋„ ์•„๋‹™๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ”„๋กœ๋•์…˜์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ์— ๊ฐ€์žฅ ์„ฑ๊ณต์ ์ธ ๋„์šฐ๋ฏธ๋Š” ์•„๋‹ˆ์ง€๋งŒ ์šฐ๋ฆฌ์˜ ๋ชฉํ‘œ๋Š” ๊ฐ„๋‹จํ•œ ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ง€๋„์— ์•ก์„ธ์Šค

์˜ˆ: BPF ํ”„๋กœ๊ทธ๋žจ์˜ ๋งต ์‚ฌ์šฉ

์ด์ „ ์„น์…˜์—์„œ๋Š” ์‚ฌ์šฉ์ž ๊ณต๊ฐ„์—์„œ ๋งต์„ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์œผ๋ฉฐ ์ด์ œ ์ปค๋„ ๋ถ€๋ถ„์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ‰์†Œ์ฒ˜๋Ÿผ ์˜ˆ๋ฅผ ๋“ค์–ด ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ์ž‘์„ฑํ•ด๋ณด์ž xdp-simple.bpf.c ๋‹ค์Œ๊ณผ ๊ฐ™์ด

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, 8);
    __type(key, u32);
    __type(value, u64);
} woo SEC(".maps");

SEC("xdp/simple")
int simple(void *ctx)
{
    u32 key = bpf_get_smp_processor_id();
    u32 *val;

    val = bpf_map_lookup_elem(&woo, &key);
    if (!val)
        return XDP_ABORTED;

    *val += 1;

    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ๋ถ€๋ถ„์— ์ง€๋„ ์ •์˜๋ฅผ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. woo: ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์ €์žฅํ•˜๋Š” 8์š”์†Œ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. u64 (C์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฐ์—ด์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. u64 woo[8]). ํ”„๋กœ๊ทธ๋žจ์—์„œ "xdp/simple" ํ˜„์žฌ ํ”„๋กœ์„ธ์„œ ๋ฒˆํ˜ธ๋ฅผ ๋ณ€์ˆ˜๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. key ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋„์šฐ๋ฏธ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ bpf_map_lookup_element ๋ฐฐ์—ด์˜ ํ•ด๋‹น ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์–ป๊ณ  XNUMX์”ฉ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋Ÿฌ์‹œ์•„์–ด๋กœ ๋ฒˆ์—ญ: CPU๊ฐ€ ๋“ค์–ด์˜ค๋Š” ํŒจํ‚ท์„ ์ฒ˜๋ฆฌํ•œ ํ†ต๊ณ„๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•ด ๋ด…์‹œ๋‹ค:

$ clang -O2 -g -c -target bpf -I libbpf/src/root/usr/include xdp-simple.bpf.c -o xdp-simple.bpf.o
$ bpftool gen skeleton xdp-simple.bpf.o > xdp-simple.skel.h
$ clang -O2 -g -I ./libbpf/src/root/usr/include/ -o xdp-simple xdp-simple.c ./libbpf/src/root/usr/lib64/libbpf.a -lelf -lz
$ sudo ./xdp-simple

๊ทธ๋…€๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž lo ๊ทธ๋ฆฌ๊ณ  ํŒจํ‚ท์„ ๋ณด๋‚ด์„ธ์š”:

$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 108

$ for s in `seq 234`; do sudo ping -f -c 100 127.0.0.1 >/dev/null 2>&1; done

์ด์ œ ๋ฐฐ์—ด์˜ ๋‚ด์šฉ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo bpftool map dump name woo
[
    { "key": 0, "value": 0 },
    { "key": 1, "value": 400 },
    { "key": 2, "value": 0 },
    { "key": 3, "value": 0 },
    { "key": 4, "value": 0 },
    { "key": 5, "value": 0 },
    { "key": 6, "value": 0 },
    { "key": 7, "value": 46400 }
]

๊ฑฐ์˜ ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค๊ฐ€ CPU7์—์„œ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ํ”„๋กœ๊ทธ๋žจ์ด ์ž‘๋™ํ•˜๊ณ  BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋งต์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ั…ะตะปะฟะตั€ะพะฒ bpf_mp_*.

์‹ ๋น„ํ•œ ์ƒ‰์ธ

๋”ฐ๋ผ์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ BPF ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ง€๋„์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

val = bpf_map_lookup_elem(&woo, &key);

๋„์šฐ๋ฏธ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)

ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ํฌ์ธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค &woo ์ด๋ฆ„์—†๋Š” ๊ตฌ์กฐ๋กœ struct { ... }...

ํ”„๋กœ๊ทธ๋žจ ์–ด์…ˆ๋ธ”๋Ÿฌ๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฐ’์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. &woo ์‹ค์ œ๋กœ ์ •์˜๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค(๋ผ์ธ 4):

llvm-objdump -D --section xdp/simple xdp-simple.bpf.o

xdp-simple.bpf.o:       file format elf64-bpf

Disassembly of section xdp/simple:

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0
       2:       bf a2 00 00 00 00 00 00 r2 = r10
       3:       07 02 00 00 fc ff ff ff r2 += -4
       4:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
       6:       85 00 00 00 01 00 00 00 call 1
...

์žฌ๋ฐฐ์น˜์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

$ llvm-readelf -r xdp-simple.bpf.o | head -4

Relocation section '.relxdp/simple' at offset 0xe18 contains 1 entries:
    Offset             Info             Type               Symbol's Value  Symbol's Name
0000000000000020  0000002700000001 R_BPF_64_64            0000000000000000 woo

๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฏธ ๋กœ๋“œ๋œ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณด๋ฉด ์˜ฌ๋ฐ”๋ฅธ ๋งต์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๋ผ์ธ 4).

$ sudo bpftool prog dump x name simple
int simple(void *ctx):
   0: (85) call bpf_get_smp_processor_id#114128
   1: (63) *(u32 *)(r10 -4) = r0
   2: (bf) r2 = r10
   3: (07) r2 += -4
   4: (18) r1 = map[id:64]
...

๋”ฐ๋ผ์„œ ์šฐ๋ฆฌ๋Š” ๋กœ๋” ํ”„๋กœ๊ทธ๋žจ์„ ์‹œ์ž‘ํ•  ๋•Œ ๋‹ค์Œ ๋งํฌ์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฒฐ๋ก ์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. &woo ๋„์„œ๊ด€์ด ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒด๋˜์—ˆ์Šต๋‹ˆ๋‹ค libbpf. ๋จผ์ € ์ถœ๋ ฅ์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. strace:

$ sudo strace -e bpf ./xdp-simple
...
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=8, max_entries=8, map_name="woo", ...}, 120) = 4
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, prog_name="simple", ...}, 120) = 5

์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋ณธ๋‹ค. libbpf ์ง€๋„๋ฅผ ๋งŒ๋“ค์—ˆ์–ด์š” woo ๊ทธ๋Ÿฐ ๋‹ค์Œ ์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์šด๋กœ๋“œํ–ˆ์Šต๋‹ˆ๋‹ค. simple. ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ๋ถ€๋ฅด๋‹ค xdp_simple_bpf__open_and_load ํŒŒ์ผ์—์„œ xdp-simple.skel.h
  • ์›์ธ์ด ๋˜๋Š” xdp_simple_bpf__load ํŒŒ์ผ์—์„œ xdp-simple.skel.h
  • ์›์ธ์ด ๋˜๋Š” bpf_object__load_skeleton ํŒŒ์ผ์—์„œ libbpf/src/libbpf.c
  • ์›์ธ์ด ๋˜๋Š” bpf_object__load_xattr ์œผ๋กœ libbpf/src/libbpf.c

๋ฌด์—‡๋ณด๋‹ค๋„ ๋งˆ์ง€๋ง‰ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. bpf_object__create_maps, ๊ธฐ์กด ๋งต์„ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์—ด์–ด ์ด๋ฅผ ํŒŒ์ผ ์„ค๋ช…์ž๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. (์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ๋ณด๋Š” ๊ณณ์€ BPF_MAP_CREATE ์ถœ๋ ฅ์—์„œ strace.) ๋‹ค์Œ์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. bpf_object__relocate ์šฐ๋ฆฌ๊ฐ€ ๋ณธ ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ์—๊ฒŒ ๊ด€์‹ฌ์ด ์žˆ๋Š” ์‚ฌ๋žŒ์€ ๋ฐ”๋กœ ๊ทธ๋…€์ž…๋‹ˆ๋‹ค. woo ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์—์„œ. ๊ทธ๊ฒƒ์„ ํƒ๊ตฌํ•˜๋ฉด์„œ ์šฐ๋ฆฌ๋Š” ๊ฒฐ๊ตญ ๋‹ค์Œ ํ•จ์ˆ˜์— ์žˆ๋Š” ์ž์‹ ์„ ๋ฐœ๊ฒฌํ•ฉ๋‹ˆ๋‹ค. bpf_program__relocate, ๊ทธ๋ฆฌ๊ณ  ์ง€๋„ ์žฌ๋ฐฐ์น˜๋ฅผ ๋‹ค๋ฃฌ๋‹ค:

case RELO_LD64:
    insn[0].src_reg = BPF_PSEUDO_MAP_FD;
    insn[0].imm = obj->maps[relo->map_idx].fd;
    break;

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ์ง€์‹œ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll

๊ทธ ์•ˆ์˜ ์†Œ์Šค ๋ ˆ์ง€์Šคํ„ฐ๋ฅผ ๋‹ค์Œ์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. BPF_PSEUDO_MAP_FD, ์ฒซ ๋ฒˆ์งธ IMM์€ ๋งต์˜ ํŒŒ์ผ ์„ค๋ช…์ž์ด๋ฉฐ, ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ 0xdeadbeef, ๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ์ง€์‹œ๋ฅผ ๋ฐ›๊ฒŒ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค

18 11 00 00 ef eb ad de 00 00 00 00 00 00 00 00 r1 = 0 ll

์ด๋Š” ์ง€๋„ ์ •๋ณด๊ฐ€ ๋กœ๋“œ๋œ ํŠน์ • BPF ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ „์†ก๋˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€๋„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. BPF_MAP_CREATE, ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ID๋กœ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. BPF_MAP_GET_FD_BY_ID.

ํ•ฉ๊ณ„, ์‚ฌ์šฉ์‹œ libbpf ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ปดํŒŒ์ผํ•˜๋Š” ๋™์•ˆ ์ง€๋„์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์œ„ํ•ด ์žฌ๋ฐฐ์น˜ ํ…Œ์ด๋ธ”์— ๋ ˆ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.
  • libbpf ELF ๊ฐ์ฒด ๋ถ์„ ์—ด๊ณ , ์‚ฌ์šฉ๋œ ๋ชจ๋“  ๋งต์„ ์ฐพ์•„ ๊ทธ์— ๋Œ€ํ•œ ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ํŒŒ์ผ ์„ค๋ช…์ž๋Š” ๋ช…๋ น์–ด์˜ ์ผ๋ถ€๋กœ ์ปค๋„์— ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. LD64

์—ฌ๋Ÿฌ๋ถ„์ด ์ƒ์ƒํ•  ์ˆ˜ ์žˆ๋“ฏ์ด ์•ž์œผ๋กœ ๋” ๋งŽ์€ ๊ฒƒ์ด ์žˆ์„ ๊ฒƒ์ด๋ฉฐ ์šฐ๋ฆฌ๋Š” ํ•ต์‹ฌ์„ ์กฐ์‚ฌํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹คํ–‰ํžˆ๋„ ๋‹จ์„œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜๋ฏธ๋ฅผ ์ ์–ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. BPF_PSEUDO_MAP_FD ์†Œ์Šค ๊ธฐ๋ก๋ถ€์— ๊ธฐ๋กํ•˜๋ฉด ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋ฌป์–ด ๋ชจ๋“  ์„ฑ๋„๋“ค์˜ ์„ฑ์†Œ๋กœ ์ธ๋„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. kernel/bpf/verifier.c, ๊ณ ์œ ํ•œ ์ด๋ฆ„์„ ๊ฐ€์ง„ ํ•จ์ˆ˜๋Š” ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ์œ ํ˜• ๊ตฌ์กฐ์˜ ์ฃผ์†Œ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. struct bpf_map:

static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env) {
    ...

    f = fdget(insn[0].imm);
    map = __bpf_map_get(f);
    if (insn->src_reg == BPF_PSEUDO_MAP_FD) {
        addr = (unsigned long)map;
    }
    insn[0].imm = (u32)addr;
    insn[1].imm = addr >> 32;

(์ „์ฒด ์ฝ”๋“œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๋งํฌ). ๋”ฐ๋ผ์„œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ”„๋กœ๊ทธ๋žจ์„ ๋กœ๋“œํ•˜๋Š” ๋™์•ˆ ๊ฒ€์ฆ์ž๋Š” ๋งต์˜ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ์„ ํ™•์ธํ•˜๊ณ  ํ•ด๋‹น ๊ตฌ์กฐ์˜ ์ฃผ์†Œ๋ฅผ ์”๋‹ˆ๋‹ค. struct bpf_map

๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ELF ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ๋•Œ libbpf ๋” ๋งŽ์€ ์ผ์ด ์ง„ํ–‰๋˜๊ณ  ์žˆ์ง€๋งŒ ์ด์— ๋Œ€ํ•ด์„œ๋Š” ๋‹ค๋ฅธ ๊ธฐ์‚ฌ์—์„œ ๋…ผ์˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

libbpf ์—†์ด ํ”„๋กœ๊ทธ๋žจ ๋ฐ ๋งต ๋กœ๋“œ

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

๋…ผ๋ฆฌ๋ฅผ ๋” ์‰ฝ๊ฒŒ ๋”ฐ๋ฅด๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ๋ชฉ์ ์— ๋งž๊ฒŒ ์˜ˆ์ œ๋ฅผ ๋‹ค์‹œ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. xdp-simple. ์ด ์˜ˆ์—์„œ ๋…ผ์˜๋œ ํ”„๋กœ๊ทธ๋žจ์˜ ์ „์ฒด ๋ฐ ์•ฝ๊ฐ„ ํ™•์žฅ๋œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์š”์ .

์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋…ผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์œ ํ˜• ๋งต ์ƒ์„ฑ BPF_MAP_TYPE_ARRAY ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ BPF_MAP_CREATE,
  • ์ด ์ง€๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ณ ,
  • ํ”„๋กœ๊ทธ๋žจ์„ ์ธํ„ฐํŽ˜์ด์Šค์— ์—ฐ๊ฒฐ lo,

์ธ๊ฐ„์œผ๋กœ ๋ฒˆ์—ญํ•˜๋ฉด

int main(void)
{
    int map_fd, prog_fd;

    map_fd = map_create();
    if (map_fd < 0)
        err(1, "bpf: BPF_MAP_CREATE");

    prog_fd = prog_load(map_fd);
    if (prog_fd < 0)
        err(1, "bpf: BPF_PROG_LOAD");

    xdp_attach(1, prog_fd);
}

์—ฌ๊ธฐ์— map_create ์‹œ์Šคํ…œ ํ˜ธ์ถœ์— ๋Œ€ํ•œ ์ฒซ ๋ฒˆ์งธ ์˜ˆ์—์„œ ํ–ˆ๋˜ ๊ฒƒ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋งต์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. bpf - โ€œ์ปค๋„, ๋‹ค์Œ๊ณผ ๊ฐ™์€ 8๊ฐœ ์š”์†Œ์˜ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ƒˆ ๋งต์„ ๋งŒ๋“ค์–ด ์ฃผ์„ธ์š”. __u64 ํŒŒ์ผ ์„ค๋ช…์ž๋ฅผ ๋Œ๋ ค์ฃผ์„ธ์š”.":

static int map_create()
{
    union bpf_attr attr;

    memset(&attr, 0, sizeof(attr));
    attr.map_type = BPF_MAP_TYPE_ARRAY,
    attr.key_size = sizeof(__u32),
    attr.value_size = sizeof(__u64),
    attr.max_entries = 8,
    strncpy(attr.map_name, "woo", sizeof(attr.map_name));
    return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
}

ํ”„๋กœ๊ทธ๋žจ์€ ๋กœ๋“œํ•˜๊ธฐ๋„ ์‰ฝ์Šต๋‹ˆ๋‹ค.

static int prog_load(int map_fd)
{
    union bpf_attr attr;
    struct bpf_insn insns[] = {
        ...
    };

    memset(&attr, 0, sizeof(attr));
    attr.prog_type = BPF_PROG_TYPE_XDP;
    attr.insns     = ptr_to_u64(insns);
    attr.insn_cnt  = sizeof(insns)/sizeof(insns[0]);
    attr.license   = ptr_to_u64("GPL");
    strncpy(attr.prog_name, "woo", sizeof(attr.prog_name));
    return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
}

๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„ prog_load BPF ํ”„๋กœ๊ทธ๋žจ์„ ๊ตฌ์กฐ์ฒด์˜ ๋ฐฐ์—ด๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. struct bpf_insn insns[]. ํ•˜์ง€๋งŒ ์šฐ๋ฆฌ๋Š” C์— ์žˆ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์•ฝ๊ฐ„์˜ ์†์ž„์ˆ˜๋ฅผ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ llvm-objdump -D --section xdp/simple xdp-simple.bpf.o

0000000000000000 <simple>:
       0:       85 00 00 00 08 00 00 00 call 8
       1:       63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0
       2:       bf a2 00 00 00 00 00 00 r2 = r10
       3:       07 02 00 00 fc ff ff ff r2 += -4
       4:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
       6:       85 00 00 00 01 00 00 00 call 1
       7:       b7 01 00 00 00 00 00 00 r1 = 0
       8:       15 00 04 00 00 00 00 00 if r0 == 0 goto +4 <LBB0_2>
       9:       61 01 00 00 00 00 00 00 r1 = *(u32 *)(r0 + 0)
      10:       07 01 00 00 01 00 00 00 r1 += 1
      11:       63 10 00 00 00 00 00 00 *(u32 *)(r0 + 0) = r1
      12:       b7 01 00 00 02 00 00 00 r1 = 2

0000000000000068 <LBB0_2>:
      13:       bf 10 00 00 00 00 00 00 r0 = r1
      14:       95 00 00 00 00 00 00 00 exit

์ „์ฒด์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ตฌ์กฐ์˜ ํ˜•ํƒœ๋กœ 14๊ฐœ์˜ ๋ช…๋ น์–ด๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. struct bpf_insn (์กฐ์–ธ: ์œ„์—์„œ ๋คํ”„๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์ง€์นจ ์„น์…˜์„ ๋‹ค์‹œ ์ฝ๊ณ  ์—ฝ๋‹ˆ๋‹ค. linux/bpf.h ะธ linux/bpf_common.h ๊ทธ๋ฆฌ๊ณ  ๊ฒฐ์ •ํ•˜๋ ค๊ณ  struct bpf_insn insns[] ์Šค์Šค๋กœ):

struct bpf_insn insns[] = {
    /* 85 00 00 00 08 00 00 00 call 8 */
    {
        .code = BPF_JMP | BPF_CALL,
        .imm = 8,
    },

    /* 63 0a fc ff 00 00 00 00 *(u32 *)(r10 - 4) = r0 */
    {
        .code = BPF_MEM | BPF_STX,
        .off = -4,
        .src_reg = BPF_REG_0,
        .dst_reg = BPF_REG_10,
    },

    /* bf a2 00 00 00 00 00 00 r2 = r10 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_X,
        .src_reg = BPF_REG_10,
        .dst_reg = BPF_REG_2,
    },

    /* 07 02 00 00 fc ff ff ff r2 += -4 */
    {
        .code = BPF_ALU64 | BPF_ADD | BPF_K,
        .dst_reg = BPF_REG_2,
        .imm = -4,
    },

    /* 18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll */
    {
        .code = BPF_LD | BPF_DW | BPF_IMM,
        .src_reg = BPF_PSEUDO_MAP_FD,
        .dst_reg = BPF_REG_1,
        .imm = map_fd,
    },
    { }, /* placeholder */

    /* 85 00 00 00 01 00 00 00 call 1 */
    {
        .code = BPF_JMP | BPF_CALL,
        .imm = 1,
    },

    /* b7 01 00 00 00 00 00 00 r1 = 0 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 0,
    },

    /* 15 00 04 00 00 00 00 00 if r0 == 0 goto +4 <LBB0_2> */
    {
        .code = BPF_JMP | BPF_JEQ | BPF_K,
        .off = 4,
        .src_reg = BPF_REG_0,
        .imm = 0,
    },

    /* 61 01 00 00 00 00 00 00 r1 = *(u32 *)(r0 + 0) */
    {
        .code = BPF_MEM | BPF_LDX,
        .off = 0,
        .src_reg = BPF_REG_0,
        .dst_reg = BPF_REG_1,
    },

    /* 07 01 00 00 01 00 00 00 r1 += 1 */
    {
        .code = BPF_ALU64 | BPF_ADD | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 1,
    },

    /* 63 10 00 00 00 00 00 00 *(u32 *)(r0 + 0) = r1 */
    {
        .code = BPF_MEM | BPF_STX,
        .src_reg = BPF_REG_1,
        .dst_reg = BPF_REG_0,
    },

    /* b7 01 00 00 02 00 00 00 r1 = 2 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_K,
        .dst_reg = BPF_REG_1,
        .imm = 2,
    },

    /* <LBB0_2>: bf 10 00 00 00 00 00 00 r0 = r1 */
    {
        .code = BPF_ALU64 | BPF_MOV | BPF_X,
        .src_reg = BPF_REG_1,
        .dst_reg = BPF_REG_0,
    },

    /* 95 00 00 00 00 00 00 00 exit */
    {
        .code = BPF_JMP | BPF_EXIT
    },
};

์ด ๊ธ€์„ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š์€ ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ์—ฐ์Šต - ์ฐพ๊ธฐ map_fd.

์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ๊ณต๊ฐœ๋˜์ง€ ์•Š์€ ๋ถ€๋ถ„์ด ํ•˜๋‚˜ ๋” ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. xdp_attach. ์•ˆํƒ€๊น๊ฒŒ๋„ XDP์™€ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋žจ์€ ์‹œ์Šคํ…œ ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. bpf. BPF์™€ XDP๋ฅผ ๋งŒ๋“  ์‚ฌ๋žŒ๋“ค์€ ์˜จ๋ผ์ธ Linux ์ปค๋ฎค๋‹ˆํ‹ฐ ์ถœ์‹ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๊ทธ๋“ค์€ ๊ทธ๋“ค์—๊ฒŒ ๊ฐ€์žฅ ์นœ์ˆ™ํ•œ ๊ฒƒ์„ ์‚ฌ์šฉํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต์˜ people) ์ปค๋„๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค: ๋„ท๋งํฌ ์†Œ์ผ“, ๋˜ํ•œ๋ณด์‹ญ์‹œ์˜ค RFC3549. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„ ๋ฐฉ๋ฒ• xdp_attach ๋‹ค์Œ์—์„œ ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. libbpf, ์ฆ‰ ํŒŒ์ผ์—์„œ netlink.c, ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ํ•œ ์ผ์ด๋ฉฐ, ์กฐ๊ธˆ ๋‹จ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค:

netlink ์†Œ์ผ“์˜ ์„ธ๊ณ„์— ์˜ค์‹  ๊ฒƒ์„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค

netlink ์†Œ์ผ“ ์œ ํ˜• ์—ด๊ธฐ NETLINK_ROUTE:

int netlink_open(__u32 *nl_pid)
{
    struct sockaddr_nl sa;
    socklen_t addrlen;
    int one = 1, ret;
    int sock;

    memset(&sa, 0, sizeof(sa));
    sa.nl_family = AF_NETLINK;

    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if (sock < 0)
        err(1, "socket");

    if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK, &one, sizeof(one)) < 0)
        warnx("netlink error reporting not supported");

    if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0)
        err(1, "bind");

    addrlen = sizeof(sa);
    if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0)
        err(1, "getsockname");

    *nl_pid = sa.nl_pid;
    return sock;
}

์šฐ๋ฆฌ๋Š” ์ด ์†Œ์ผ“์—์„œ ๋‹ค์Œ์„ ์ฝ์Šต๋‹ˆ๋‹ค:

static int bpf_netlink_recv(int sock, __u32 nl_pid, int seq)
{
    bool multipart = true;
    struct nlmsgerr *errm;
    struct nlmsghdr *nh;
    char buf[4096];
    int len, ret;

    while (multipart) {
        multipart = false;
        len = recv(sock, buf, sizeof(buf), 0);
        if (len < 0)
            err(1, "recv");

        if (len == 0)
            break;

        for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
                nh = NLMSG_NEXT(nh, len)) {
            if (nh->nlmsg_pid != nl_pid)
                errx(1, "wrong pid");
            if (nh->nlmsg_seq != seq)
                errx(1, "INVSEQ");
            if (nh->nlmsg_flags & NLM_F_MULTI)
                multipart = true;
            switch (nh->nlmsg_type) {
                case NLMSG_ERROR:
                    errm = (struct nlmsgerr *)NLMSG_DATA(nh);
                    if (!errm->error)
                        continue;
                    ret = errm->error;
                    // libbpf_nla_dump_errormsg(nh); too many code to copy...
                    goto done;
                case NLMSG_DONE:
                    return 0;
                default:
                    break;
            }
        }
    }
    ret = 0;
done:
    return ret;
}

๋งˆ์ง€๋ง‰์œผ๋กœ ์†Œ์ผ“์„ ์—ด๊ณ  ํŒŒ์ผ ์„ค๋ช…์ž๊ฐ€ ํฌํ•จ๋œ ํŠน๋ณ„ํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

static int xdp_attach(int ifindex, int prog_fd)
{
    int sock, seq = 0, ret;
    struct nlattr *nla, *nla_xdp;
    struct {
        struct nlmsghdr  nh;
        struct ifinfomsg ifinfo;
        char             attrbuf[64];
    } req;
    __u32 nl_pid = 0;

    sock = netlink_open(&nl_pid);
    if (sock < 0)
        return sock;

    memset(&req, 0, sizeof(req));
    req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nh.nlmsg_type = RTM_SETLINK;
    req.nh.nlmsg_pid = 0;
    req.nh.nlmsg_seq = ++seq;
    req.ifinfo.ifi_family = AF_UNSPEC;
    req.ifinfo.ifi_index = ifindex;

    /* started nested attribute for XDP */
    nla = (struct nlattr *)(((char *)&req)
            + NLMSG_ALIGN(req.nh.nlmsg_len));
    nla->nla_type = NLA_F_NESTED | IFLA_XDP;
    nla->nla_len = NLA_HDRLEN;

    /* add XDP fd */
    nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
    nla_xdp->nla_type = IFLA_XDP_FD;
    nla_xdp->nla_len = NLA_HDRLEN + sizeof(int);
    memcpy((char *)nla_xdp + NLA_HDRLEN, &prog_fd, sizeof(prog_fd));
    nla->nla_len += nla_xdp->nla_len;

    /* if user passed in any flags, add those too */
    __u32 flags = XDP_FLAGS_SKB_MODE;
    nla_xdp = (struct nlattr *)((char *)nla + nla->nla_len);
    nla_xdp->nla_type = IFLA_XDP_FLAGS;
    nla_xdp->nla_len = NLA_HDRLEN + sizeof(flags);
    memcpy((char *)nla_xdp + NLA_HDRLEN, &flags, sizeof(flags));
    nla->nla_len += nla_xdp->nla_len;

    req.nh.nlmsg_len += NLA_ALIGN(nla->nla_len);

    if (send(sock, &req, req.nh.nlmsg_len, 0) < 0)
        err(1, "send");
    ret = bpf_netlink_recv(sock, nl_pid, seq);

cleanup:
    close(sock);
    return ret;
}

์ด์ œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์ค€๋น„๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

$ cc nolibbpf.c -o nolibbpf
$ sudo strace -e bpf ./nolibbpf
bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, map_name="woo", ...}, 72) = 3
bpf(BPF_PROG_LOAD, {prog_type=BPF_PROG_TYPE_XDP, insn_cnt=15, prog_name="woo", ...}, 72) = 4
+++ exited with 0 +++

์šฐ๋ฆฌ ํ”„๋กœ๊ทธ๋žจ์ด ๋‹ค์Œ๊ณผ ์—ฐ๊ฒฐ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด ๋ด…์‹œ๋‹ค. lo:

$ ip l show dev lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    prog/xdp id 160

ํ•‘์„ ๋ณด๋‚ด๊ณ  ์ง€๋„๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

$ for s in `seq 234`; do sudo ping -f -c 100 127.0.0.1 >/dev/null 2>&1; done
$ sudo bpftool m dump name woo
key: 00 00 00 00  value: 90 01 00 00 00 00 00 00
key: 01 00 00 00  value: 00 00 00 00 00 00 00 00
key: 02 00 00 00  value: 00 00 00 00 00 00 00 00
key: 03 00 00 00  value: 00 00 00 00 00 00 00 00
key: 04 00 00 00  value: 00 00 00 00 00 00 00 00
key: 05 00 00 00  value: 00 00 00 00 00 00 00 00
key: 06 00 00 00  value: 40 b5 00 00 00 00 00 00
key: 07 00 00 00  value: 00 00 00 00 00 00 00 00
Found 8 elements

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

๊ฐœ๋ฐœ ๋„๊ตฌ

์ด ์„น์…˜์—์„œ๋Š” ์ตœ์†Œ BPF ๊ฐœ๋ฐœ์ž ํˆดํ‚ท์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ BPF ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ํŠน๋ณ„ํ•œ ๊ฒƒ์€ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. BPF๋Š” ๊ดœ์ฐฎ์€ ๋ฐฐํฌ ์ปค๋„์—์„œ ์‹คํ–‰๋˜๋ฉฐ ํ”„๋กœ๊ทธ๋žจ์€ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์ถ•๋ฉ๋‹ˆ๋‹ค. clang, ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ BPF๊ฐ€ ๊ฐœ๋ฐœ ์ค‘์ด๊ธฐ ๋•Œ๋ฌธ์— ์ปค๋„๊ณผ ๋„๊ตฌ๊ฐ€ ์ง€์†์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. 2019๋…„๋ถ€ํ„ฐ ๊ตฌ์‹ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ BPF ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ์ปดํŒŒ์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • llvm/clang
  • pahole
  • ๊ทธ ํ•ต์‹ฌ
  • bpftool

(์ฐธ๊ณ ๋กœ ์ด ์„น์…˜๊ณผ ๊ธฐ์‚ฌ์˜ ๋ชจ๋“  ์˜ˆ์ œ๋Š” Debian 10์—์„œ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.)

llvm/clang

BPF๋Š” LLVM๊ณผ ์นœํ™”์ ์ด๋ฉฐ ์ตœ๊ทผ BPF์šฉ ํ”„๋กœ๊ทธ๋žจ์€ gcc๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ํ˜„์žฌ์˜ ๋ชจ๋“  ๊ฐœ๋ฐœ์€ LLVM์šฉ์œผ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์šฐ์„  ํ˜„์žฌ ๋ฒ„์ „์„ ๋นŒ๋“œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. clang ์ž์‹์—์„œ :

$ sudo apt install ninja-build
$ git clone --depth 1 https://github.com/llvm/llvm-project.git
$ mkdir -p llvm-project/llvm/build/install
$ cd llvm-project/llvm/build
$ cmake .. -G "Ninja" -DLLVM_TARGETS_TO_BUILD="BPF;X86" 
                      -DLLVM_ENABLE_PROJECTS="clang" 
                      -DBUILD_SHARED_LIBS=OFF 
                      -DCMAKE_BUILD_TYPE=Release 
                      -DLLVM_BUILD_RUNTIME=OFF
$ time ninja
... ะผะฝะพะณะพ ะฒั€ะตะผะตะฝะธ ัะฟัƒัั‚ั
$

์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ฒฐํ•ฉ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

$ ./bin/llc --version
LLVM (http://llvm.org/):
  LLVM version 11.0.0git
  Optimized build.
  Default target: x86_64-unknown-linux-gnu
  Host CPU: znver1

  Registered Targets:
    bpf    - BPF (host endian)
    bpfeb  - BPF (big endian)
    bpfel  - BPF (little endian)
    x86    - 32-bit X86: Pentium-Pro and above
    x86-64 - 64-bit X86: EM64T and AMD64

(์กฐ๋ฆฝ ์„ค๋ช…์„œ clang ๋‚ด๊ฐ€ ๊ฐ€์ ธ์˜จ ๊ฒƒ bpf_devel_QA.)

๋ฐฉ๊ธˆ ๋งŒ๋“  ํ”„๋กœ๊ทธ๋žจ์„ ์„ค์น˜ํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹ ์— ํ”„๋กœ๊ทธ๋žจ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. PATH์˜ˆ :

export PATH="`pwd`/bin:$PATH"

(์ด๊ฒƒ์€ ๋‹ค์Œ์— ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. .bashrc ์•„๋‹ˆ๋ฉด ๋ณ„๋„์˜ ํŒŒ์ผ๋กœ. ๊ฐœ์ธ์ ์œผ๋กœ ์ €๋Š” ์ด๋Ÿฐ ๋‚ด์šฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ~/bin/activate-llvm.sh ๊ทธ๋ฆฌ๊ณ  ํ•„์š”ํ•  ๋•Œ ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ํ•œ๋‹ค . activate-llvm.sh.)

ํŒŒํ™€๊ณผ BTF

๊ณต์ต ์‚ฌ์—… pahole BTF ํ˜•์‹์˜ ๋””๋ฒ„๊น… ์ •๋ณด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ปค๋„์„ ๋นŒ๋“œํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. BTF ๊ธฐ์ˆ ์ด ํŽธ๋ฆฌํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋Š” ์‚ฌ์‹ค ์™ธ์—๋Š” ์ด ๊ธฐ์‚ฌ์—์„œ BTF ๊ธฐ์ˆ ์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•˜์ง€ ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ปค๋„์„ ๋นŒ๋“œํ•˜๋ ค๋ฉด ๋จผ์ € ๋นŒ๋“œํ•˜์‹ญ์‹œ์˜ค. pahole (์—†์ด pahole ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋„์„ ๋นŒ๋“œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. CONFIG_DEBUG_INFO_BTF:

$ git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git
$ cd pahole/
$ sudo apt install cmake
$ mkdir build
$ cd build/
$ cmake -D__LIB=lib ..
$ make
$ sudo make install
$ which pahole
/usr/local/bin/pahole

BPF ์‹คํ—˜์„ ์œ„ํ•œ ์ปค๋„

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

์ปค๋„์„ ๋นŒ๋“œํ•˜๋ ค๋ฉด ๋จผ์ € ์ปค๋„ ์ž์ฒด๊ฐ€ ํ•„์š”ํ•˜๊ณ  ๋‘ ๋ฒˆ์งธ๋กœ ์ปค๋„ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. BPF๋ฅผ ์‹คํ—˜ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๋ฐ”๋‹๋ผ ์ปค๋„ ๋˜๋Š” ๊ฐœ๋ฐœ ์ปค๋„ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์—ญ์‚ฌ์ ์œผ๋กœ BPF ๊ฐœ๋ฐœ์€ Linux ๋„คํŠธ์›Œํ‚น ์ปค๋ฎค๋‹ˆํ‹ฐ ๋‚ด์—์„œ ์ด๋ฃจ์–ด์กŒ์œผ๋ฏ€๋กœ ์กฐ๋งŒ๊ฐ„ ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ Linux ๋„คํŠธ์›Œํ‚น ๊ด€๋ฆฌ์ž์ธ David Miller๋ฅผ ํ†ตํ•ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ์„ฑ๊ฒฉ(ํŽธ์ง‘ ๋˜๋Š” ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ)์— ๋”ฐ๋ผ ๋„คํŠธ์›Œํฌ ๋ณ€๊ฒฝ์€ ๋‘ ๊ฐœ์˜ ์ฝ”์–ด ์ค‘ ํ•˜๋‚˜์— ์†ํ•ฉ๋‹ˆ๋‹ค. net ๋˜๋Š” net-next. BPF์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋ฐฐํฌ๋ฉ๋‹ˆ๋‹ค. bpf ะธ bpf-next, ์ด๋Š” ๊ฐ๊ฐ net๊ณผ net-next๋กœ ํ’€๋ง๋ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”. bpf_devel_QA ะธ netdev-FAQ. ๋”ฐ๋ผ์„œ ๊ท€ํ•˜์˜ ์ทจํ–ฅ๊ณผ ํ…Œ์ŠคํŠธ ์ค‘์ธ ์‹œ์Šคํ…œ์˜ ์•ˆ์ •์„ฑ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ์ปค๋„์„ ์„ ํƒํ•˜์‹ญ์‹œ์˜ค(*-next ์ปค๋„์€ ๋‚˜์—ด๋œ ๊ฒƒ ์ค‘ ๊ฐ€์žฅ ๋ถˆ์•ˆ์ •ํ•ฉ๋‹ˆ๋‹ค.)

์ปค๋„ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์€ ์ด ๊ธฐ์‚ฌ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์šธ ์ค€๋น„๊ฐ€ ์Šค์Šค๋กœ. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์Œ ์ง€์นจ์€ ์ž‘๋™ํ•˜๋Š” BPF ์ง€์› ์‹œ์Šคํ…œ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์–ด๋Š ์ •๋„ ์ถฉ๋ถ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์œ„ ์ปค๋„ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์‹ญ์‹œ์˜ค.

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
$ cd bpf-next

์ตœ์†Œํ•œ์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ์ปค๋„ ๊ตฌ์„ฑ์„ ๊ตฌ์ถ•ํ•ฉ๋‹ˆ๋‹ค.

$ cp /boot/config-`uname -r` .config
$ make localmodconfig

ํŒŒ์ผ์—์„œ BPF ์˜ต์…˜ ํ™œ์„ฑํ™” .config ์ž์‹ ์ด ์„ ํƒํ•œ ๊ฒƒ(์•„๋งˆ๋„ CONFIG_BPF systemd๊ฐ€ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฏธ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค). ๋‹ค์Œ์€ ์ด ๊ธฐ์‚ฌ์— ์‚ฌ์šฉ๋œ ์ปค๋„ ์˜ต์…˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค.

CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_LSM=y
CONFIG_BPF_SYSCALL=y
CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT_DEFAULT_ON=y
CONFIG_IPV6_SEG6_BPF=y
# CONFIG_NETFILTER_XT_MATCH_BPF is not set
# CONFIG_BPFILTER is not set
CONFIG_NET_CLS_BPF=y
CONFIG_NET_ACT_BPF=y
CONFIG_BPF_JIT=y
CONFIG_BPF_STREAM_PARSER=y
CONFIG_LWTUNNEL_BPF=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_BPF_KPROBE_OVERRIDE=y
CONFIG_DEBUG_INFO_BTF=y

๊ทธ๋Ÿฌ๋ฉด ๋ชจ๋“ˆ๊ณผ ์ปค๋„์„ ์‰ฝ๊ฒŒ ์กฐ๋ฆฝํ•˜๊ณ  ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฐ๋ฐ ์ƒˆ๋กœ ์กฐ๋ฆฝํ•œ ์ปค๋„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค๋„์„ ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค). clang์ถ”๊ฐ€ํ•˜์—ฌ CC=clang):

$ make -s -j $(getconf _NPROCESSORS_ONLN)
$ sudo make modules_install
$ sudo make install

๊ทธ๋ฆฌ๊ณ  ์ƒˆ ์ปค๋„๋กœ ์žฌ๋ถ€ํŒ…ํ•ฉ๋‹ˆ๋‹ค(์ €๋Š” ์ด๊ฒƒ์„ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค) kexec ํŒจํ‚ค์ง€์—์„œ kexec-tools):

v=5.8.0-rc6+ # ะตัะปะธ ะฒั‹ ะฟะตั€ะตัะพะฑะธั€ะฐะตั‚ะต ั‚ะตะบัƒั‰ะตะต ัะดั€ะพ, ั‚ะพ ะผะพะถะฝะพ ะดะตะปะฐั‚ัŒ v=`uname -r`
sudo kexec -l -t bzImage /boot/vmlinuz-$v --initrd=/boot/initrd.img-$v --reuse-cmdline &&
sudo kexec -e

bpftool

์ด ๊ธฐ์‚ฌ์—์„œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. bpftool, Linux ์ปค๋„์˜ ์ผ๋ถ€๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. BPF ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•ด BPF ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•˜๊ณ  ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋ฉฐ ํ”„๋กœ๊ทธ๋žจ ๋กœ๋“œ, ์ง€๋„ ์ƒ์„ฑ ๋ฐ ํŽธ์ง‘, BPF ์ƒํƒœ๊ณ„ ์ˆ˜๋ช… ํƒ์ƒ‰ ๋“ฑ ๋ชจ๋“  ์œ ํ˜•์˜ BPF ๊ฐœ์ฒด๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งค๋‰ด์–ผ ํŽ˜์ด์ง€์— ๋Œ€ํ•œ ์†Œ์Šค ์ฝ”๋“œ ํ˜•ํƒœ์˜ ๋ฌธ์„œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ต์‹ฌ์— ๋˜๋Š” ์ด๋ฏธ ์ปดํŒŒ์ผ๋œ ๊ฒฝ์šฐ ๋„คํŠธ์›Œํฌ์—์„œ.

์ด ๊ธ€์„ ์“ฐ๋Š” ์‹œ์ ์—์„œ bpftool RHEL, Fedora ๋ฐ Ubuntu์— ๋Œ€ํ•ด์„œ๋งŒ ๊ธฐ์„ฑํ’ˆ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค(์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”). ์ด ์Šค๋ ˆ๋“œํฌ์žฅ์˜ ๋๋‚˜์ง€ ์•Š์€ ์ด์•ผ๊ธฐ๋ฅผ ์ „ํ•˜๋Š” , bpftool ๋ฐ๋น„์•ˆ์—์„œ). ํ•˜์ง€๋งŒ ์ด๋ฏธ ์ปค๋„์„ ๊ตฌ์ถ•ํ–ˆ๋‹ค๋ฉด, ์ปค๋„์„ ๊ตฌ์ถ•ํ•˜์„ธ์š”. bpftool ํŒŒ์ด๋งŒํผ ์‰ฝ๋‹ค:

$ cd ${linux}/tools/bpf/bpftool
# ... ะฟั€ะพะฟะธัˆะธั‚ะต ะฟัƒั‚ะธ ะบ ะฟะพัะปะตะดะฝะตะผัƒ clang, ะบะฐะบ ั€ะฐััะบะฐะทะฐะฝะพ ะฒั‹ัˆะต
$ make -s

Auto-detecting system features:
...                        libbfd: [ on  ]
...        disassembler-four-args: [ on  ]
...                          zlib: [ on  ]
...                        libcap: [ on  ]
...               clang-bpf-co-re: [ on  ]

Auto-detecting system features:
...                        libelf: [ on  ]
...                          zlib: [ on  ]
...                           bpf: [ on  ]

$

(์—ฌ๊ธฐ ${linux} - ์ด๊ฒƒ์€ ์ปค๋„ ๋””๋ ‰ํ† ๋ฆฌ์ž…๋‹ˆ๋‹ค.) ์ด ๋ช…๋ น์„ ์‹คํ–‰ํ•œ ํ›„ bpftool ๋””๋ ‰ํ† ๋ฆฌ์— ์ˆ˜์ง‘๋ฉ๋‹ˆ๋‹ค ${linux}/tools/bpf/bpftool ๊ฒฝ๋กœ์— ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์šฐ์„  ์‚ฌ์šฉ์ž์—๊ฒŒ root) ๋˜๋Š” ๋‹ค์Œ์œผ๋กœ ๋ณต์‚ฌํ•˜์„ธ์š”. /usr/local/sbin.

์ˆ˜์ง‘ bpftool ํ›„์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค clang, ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ ์กฐ๋ฆฝํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์กฐ๋ฆฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

$ sudo bpftool feature probe kernel
Scanning system configuration...
bpf() syscall for unprivileged users is enabled
JIT compiler is enabled
JIT compiler hardening is disabled
JIT compiler kallsyms exports are enabled for root
...

์ปค๋„์—์„œ ์–ด๋–ค BPF ๊ธฐ๋Šฅ์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๋Š”์ง€ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด์ „ ๋ช…๋ น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

# bpftool f p k

์ด๋Š” ํŒจํ‚ค์ง€์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. iproute2, ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ip a s eth0 ๋Œ€์‹  ip addr show dev eth0.

๊ฒฐ๋ก 

BPF๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฒผ๋ฃฉ์„ ํšจ๊ณผ์ ์œผ๋กœ ์ธก์ •ํ•˜๊ณ  ์ฝ”์–ด์˜ ๊ธฐ๋Šฅ์„ ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ UNIX์˜ ์ตœ๊ณ  ์ „ํ†ต์— ๋”ฐ๋ผ ๋งค์šฐ ์„ฑ๊ณต์ ์ธ ๊ฒƒ์œผ๋กœ ํŒ๋ช…๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„์„ (์žฌ)ํ”„๋กœ๊ทธ๋ž˜๋ฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ†ตํ•ด ์ˆ˜๋งŽ์€ ์‚ฌ๋žŒ๊ณผ ์กฐ์ง์ด ์‹คํ—˜์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  BPF ์ธํ”„๋ผ ์ž์ฒด์˜ ๊ฐœ๋ฐœ๊ณผ ์‹คํ—˜์ด ์•„์ง ์™„๋ฃŒ๋˜์ง€ ์•Š์•˜์ง€๋งŒ ์‹œ์Šคํ…œ์—๋Š” ์ด๋ฏธ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•˜๊ฒŒ๋Š” ํšจ๊ณผ์ ์ธ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” ์•ˆ์ •์ ์ธ ABI๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ ์ƒ๊ฐ์—๋Š” ์ด ๊ธฐ์ˆ ์ด ํ•œํŽธ์œผ๋กœ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ๋งค์šฐ ๋Œ€์ค‘ํ™”๋˜์—ˆ๋‹ค๋Š” ์ ์— ์ฃผ๋ชฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋†€๋‹ค (๊ธฐ๊ณ„์˜ ๊ตฌ์กฐ๋Š” ์–ด๋Š ๋‚  ์ €๋…์— ์–ด๋Š ์ •๋„ ์ดํ•ด๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.) ๋‹ค๋ฅธ ํ•œํŽธ์œผ๋กœ๋Š” ๋“ฑ์žฅํ•˜๊ธฐ ์ „์—๋Š” (์•„๋ฆ„๋‹ต๊ฒŒ) ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์—ˆ๋˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๋‘ ๊ฐ€์ง€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๊ฒฐํ•ฉ๋˜์–ด ์‚ฌ๋žŒ๋“ค์€ ์‹คํ—˜ํ•˜๊ณ  ๊ฟˆ์„ ๊พธ๊ฒŒ ๋˜๋ฉฐ, ์ด๋Š” ์ ์  ๋” ํ˜์‹ ์ ์ธ ์†”๋ฃจ์…˜์˜ ์ถœํ˜„์œผ๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.

์ด ๊ธฐ์‚ฌ๋Š” ํŠน๋ณ„ํžˆ ์งง์ง€๋Š” ์•Š์ง€๋งŒ BPF์˜ ์„ธ๊ณ„์— ๋Œ€ํ•œ ์†Œ๊ฐœ์ผ ๋ฟ์ด๋ฉฐ "๊ณ ๊ธ‰" ๊ธฐ๋Šฅ๊ณผ ์•„ํ‚คํ…์ฒ˜์˜ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์„ ์„ค๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ์˜ ๊ณ„ํš์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ธฐ์‚ฌ์—์„œ๋Š” BPF ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜•(5.8 ์ปค๋„์—์„œ ์ง€์›๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ ์œ ํ˜• 30๊ฐœ)์— ๋Œ€ํ•œ ๊ฐœ์š”๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์ปค๋„ ์ถ”์  ํ”„๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ BPF ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด BPF ์•„ํ‚คํ…์ฒ˜์— ๋Œ€ํ•œ ๋ณด๋‹ค ์‹ฌ์ธต์ ์ธ ๊ณผ์ •์„ ์ง„ํ–‰ํ•œ ๋‹ค์Œ BPF ๋„คํŠธ์›Œํ‚น ๋ฐ ๋ณด์•ˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ์‹œ๋ฆฌ์ฆˆ์˜ ์ด์ „ ๊ธฐ์‚ฌ

  1. ์–ด๋ฆฐ ์•„์ด๋“ค์„ ์œ„ํ•œ BPF, ํŒŒํŠธ XNUMX: ํด๋ž˜์‹ BPF

์—ฐ๊ฒฐ

  1. BPF ๋ฐ XDP ์ฐธ์กฐ ๊ฐ€์ด๋“œ โ€” cilium์˜ BPF์— ๋Œ€ํ•œ ๋ฌธ์„œ, ๋” ์ •ํ™•ํ•˜๊ฒŒ๋Š” BPF์˜ ์ฐฝ์‹œ์ž์ด์ž ์œ ์ง€๊ด€๋ฆฌ์ž ์ค‘ ํ•œ ๋ช…์ธ Daniel Borkman์˜ ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค๋‹ˆ์—˜์ด ์ž์‹ ์ด ์“ฐ๊ณ  ์žˆ๋Š” ๋‚ด์šฉ์„ ์ •ํ™•ํžˆ ์•Œ๊ณ  ๊ฑฐ๊ธฐ์— ์‹ค์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ์ ์—์„œ ๋‹ค๋ฅธ ์„ค๋ช…๊ณผ ๋‹ค๋ฅธ ์ตœ์ดˆ์˜ ์ง„์ง€ํ•œ ์„ค๋ช… ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ์ด ๋ฌธ์„œ์—์„œ๋Š” ์ž˜ ์•Œ๋ ค์ง„ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ XDP ๋ฐ TC ์œ ํ˜•์˜ BPF ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ž‘์—…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ip ํŒจํ‚ค์ง€์—์„œ iproute2.

  2. ๋ฌธ์„œ/๋„คํŠธ์›Œํ‚น/filter.txt โ€” ํด๋ž˜์‹ ๋ฐ ํ™•์žฅ BPF์— ๋Œ€ํ•œ ๋ฌธ์„œ๊ฐ€ ํฌํ•จ๋œ ์›๋ณธ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ์–ด์…ˆ๋ธ”๋ฆฌ ์–ธ์–ด์™€ ๊ธฐ์ˆ ์ ์ธ ์•„ํ‚คํ…์ฒ˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์ฝ์–ด๋ณด๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค.

  3. Facebook์˜ BPF ๊ด€๋ จ ๋ธ”๋กœ๊ทธ. ๊ฑฐ์˜ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š์ง€๋งŒ Alexei Starovoitov(eBPF ์ž‘์„ฑ์ž)์™€ Andrii Nakryiko(๊ด€๋ฆฌ์ž)๊ฐ€ ๊ฑฐ๊ธฐ์— ์“ด ๊ฒƒ์ฒ˜๋Ÿผ ์ ์ ˆํ•˜๊ฒŒ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค. libbpf).

  4. bpftool์˜ ๋น„๋ฐ€. bpftool ์‚ฌ์šฉ์˜ ์˜ˆ์™€ ๋น„๋ฐ€์„ ๋‹ด์€ Quentin Monnet์˜ ์žฌ๋ฏธ์žˆ๋Š” ํŠธ์œ„ํ„ฐ ์Šค๋ ˆ๋“œ์ž…๋‹ˆ๋‹ค.

  5. BPF ์‚ดํŽด๋ณด๊ธฐ: ์ฝ๊ธฐ ์ž๋ฃŒ ๋ชฉ๋ก. Quentin Monnet์˜ BPF ๋ฌธ์„œ์— ๋Œ€ํ•œ ๋Œ€๊ทœ๋ชจ(๊ทธ๋ฆฌ๊ณ  ์—ฌ์ „ํžˆ ์œ ์ง€ ๊ด€๋ฆฌ๋˜๋Š”) ๋งํฌ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€