ํ์ด์ BPF๋ผ๋ ๊ธฐ์ ์ด ์์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๋
๋ฅผ ๋ฐ๋ผ๋ณด์๋ค
๋๋ต์ ์ผ๋ก ๋งํ๋ฉด BPF๋ฅผ ์ฌ์ฉํ๋ฉด Linux ์ปค๋ ๊ณต๊ฐ์์ ์์์ ์ฌ์ฉ์ ์ ๊ณต ์ฝ๋๋ฅผ ์คํํ ์ ์์ผ๋ฉฐ ์ ์ํคํ ์ฒ๋ ๋งค์ฐ ์ฑ๊ณต์ ์ด์ด์ ๋ชจ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค๋ช ํ๋ ค๋ฉด XNUMX๊ฐ์ ๊ธฐ์ฌ๊ฐ ๋ ํ์ํ ๊ฒ์ ๋๋ค. (์๋ ์ฑ๋ฅ ์ฝ๋์์ ๋ณผ ์ ์๋ฏ์ด ๊ฐ๋ฐ์๋ค์ด ์ ์ผํ๊ฒ ์ ๋ชปํ ๊ฒ์ ๊ด์ฐฎ์ ๋ก๊ณ ๋ฅผ ๋ง๋๋ ๊ฒ์ด์์ต๋๋ค.)
์ด ๊ธฐ์ฌ์์๋ BPF ๊ฐ์ ๋จธ์ ์ ๊ตฌ์กฐ, BPF ์์
์ ์ํ ์ปค๋ ์ธํฐํ์ด์ค, ๊ฐ๋ฐ ๋๊ตฌ ๋ฐ ๊ธฐ์กด ๊ธฐ๋ฅ์ ๋ํ ๊ฐ๋ตํ๊ณ ๊ฐ๋จํ ๊ฐ์๋ฅผ ์ค๋ช
ํฉ๋๋ค. BPF์ ์ค์ ์ ์ฉ์ ๋ํ ๋ ๊น์ ์ฐ๊ตฌ๋ฅผ ์ํด ๋ฏธ๋์ ํ์ํ ๋ชจ๋ ๊ฒ์
๋๋ค.
๊ธฐ์ฌ ์์ฝ
bpf(2)
.
ะะธัะตะผ ะฟัะพะณัะฐะผะผั BPF ั ะฟะพะผะพััั libbpf
.libbpf
. ํ์ ์์ ์์ ์ฌ์ฉํ ๊ธฐ๋ณธ BPF ์ ํ๋ฆฌ์ผ์ด์
๋ผ๋๋ฅผ ๋ง๋ญ๋๋ค.
BPF ์ํคํ ์ฒ ์๊ฐ
BPF ์ํคํ
์ฒ๋ฅผ ๊ณ ๋ คํ๊ธฐ ์ ์ ๋ง์ง๋ง์ผ๋ก (์ค) ๋ค์์ ์ฐธ์กฐํ๊ฒ ์ต๋๋ค.
์๋ก์ด BPF๋ 64๋นํธ ๋จธ์ , ํด๋ผ์ฐ๋ ์๋น์ค์ ํธ์ฌ์ฑ ๋ฐ SDN ์์ฑ์ ์ํ ๋๊ตฌ์ ๋ํ ํ์์ฑ ์ฆ๊ฐ์ ๋ํ ๋์์ผ๋ก ๊ฐ๋ฐ๋์์ต๋๋ค(Software-d์ ๊ตํ n์ํธ์ํน). ๊ธฐ์กด BPF์ ๊ฐ์ ๋ ๋์ฒดํ์ผ๋ก ์ปค๋ ๋คํธ์ํฌ ์์ง๋์ด์ ์ํด ๊ฐ๋ฐ๋ ์๋ก์ด BPF๋ ๋ฌธ์ ๊ทธ๋๋ก XNUMX๊ฐ์ ํ์ Linux ์์คํ ์ ์ถ์ ํ๋ ์ด๋ ค์ด ์์ ์์ ์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฐ๊ฒฌํ์ผ๋ฉฐ ์ด์ ๋ฑ์ฅํ ์ง XNUMX๋ ์ด ์ง๋ฌ์ผ๋ฏ๋ก ๋ค์ ๊ธฐ์ฌ ์ ์ฒด๊ฐ ํ์ํฉ๋๋ค. ๋ค์ํ ์ข ๋ฅ์ ํ๋ก๊ทธ๋จ์ ๋์ดํด ๋ณด์ธ์.
์ฌ๋ฐ๋ ์ฌ์ง
๊ธฐ๋ณธ์ ์ผ๋ก BPF๋ ๋ณด์์ ์์์ํค์ง ์๊ณ ์ปค๋ ๊ณต๊ฐ์์ "์์" ์ฝ๋๋ฅผ ์คํํ ์ ์๊ฒ ํด์ฃผ๋ ์๋๋ฐ์ค ๊ฐ์ ๋จธ์ ์ ๋๋ค. BPF ํ๋ก๊ทธ๋จ์ ์ฌ์ฉ์ ๊ณต๊ฐ์์ ์์ฑ๋๊ณ ์ปค๋์ ๋ก๋๋๋ฉฐ ์ผ๋ถ ์ด๋ฒคํธ ์์ค์ ์ฐ๊ฒฐ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋คํธ์ํฌ ์ธํฐํ์ด์ค๋ก์ ํจํท ์ ๋ฌ, ์ผ๋ถ ์ปค๋ ๊ธฐ๋ฅ ์คํ ๋ฑ์ด ์ด๋ฒคํธ๊ฐ ๋ ์ ์์ต๋๋ค. ํจํค์ง์ ๊ฒฝ์ฐ BPF ํ๋ก๊ทธ๋จ์ ํจํค์ง์ ๋ฐ์ดํฐ ๋ฐ ๋ฉํ๋ฐ์ดํฐ์ ์ก์ธ์คํ ์ ์์ต๋๋ค(ํ๋ก๊ทธ๋จ ์ ํ์ ๋ฐ๋ผ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ๋ฅผ ์ํด). ์ปค๋ ํจ์๋ฅผ ์คํํ๋ ๊ฒฝ์ฐ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ์ ๋ํ ํฌ์ธํฐ ๋ฑ์ ํฌํจํ ํจ์
์ด ๊ณผ์ ์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ฐ์ , ์ด์ ๋ธ๋ฌ๋ก ์์ฑ๋ ํ๋ก๊ทธ๋จ์ธ ํด๋์ BPF์์ ์ฒซ ๋ฒ์งธ ์ฐจ์ด์ ์ ๋ํด ์ด์ผ๊ธฐํด ๋ณด๊ฒ ์ต๋๋ค. ์ ๋ฒ์ ์์๋ ํ๋ก๊ทธ๋จ์ ๊ณ ๊ธ ์ธ์ด(์ฃผ๋ก C)๋ก ์์ฑํ ์ ์๋๋ก ์ํคํ ์ฒ๊ฐ ํ์ฅ๋์์ต๋๋ค. ์ด๋ฅผ ์ํด BPF ์ํคํ ์ฒ์ฉ ๋ฐ์ดํธ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ llvm์ฉ ๋ฐฑ์๋๊ฐ ๊ฐ๋ฐ๋์์ต๋๋ค.
BPF ์ํคํ
์ฒ๋ ๋ถ๋ถ์ ์ผ๋ก ์ต์ ๋จธ์ ์์ ํจ์จ์ ์ผ๋ก ์คํ๋๋๋ก ์ค๊ณ๋์์ต๋๋ค. ์ค์ ๋ก ์ด ์์
์ ์ํํ๊ธฐ ์ํด ์ปค๋์ ๋ก๋๋ BPF ๋ฐ์ดํธ์ฝ๋๋ JIT ์ปดํ์ผ๋ฌ(Just In T์). ๋ค์์ผ๋ก, ํด๋์ BPF์์ ํ๋ก๊ทธ๋จ์ ๋จ์ผ ์์คํ
ํธ์ถ์ ๋งฅ๋ฝ์์ ์ปค๋์ ๋ก๋๋๊ณ ์ด๋ฒคํธ ์์ค์ ์์์ ์ผ๋ก ์ฐ๊ฒฐ๋์์ต๋๋ค. ์๋ก์ด ์ํคํ
์ฒ์์๋ ์ด ์์
์ด ๋ ๋จ๊ณ๋ก ์งํ๋ฉ๋๋ค. ์ฒซ์งธ, ์์คํ
ํธ์ถ์ ์ฌ์ฉํ์ฌ ์ฝ๋๊ฐ ์ปค๋์ ๋ก๋๋ฉ๋๋ค. bpf(2)
๊ทธ๋ฐ ๋ค์ ๋์ค์ ํ๋ก๊ทธ๋จ ์ ํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๋ค๋ฅธ ๋ฉ์ปค๋์ฆ์ ํตํด ํ๋ก๊ทธ๋จ์ด ์ด๋ฒคํธ ์์ค์ ์ฐ๊ฒฐ๋ฉ๋๋ค.
์ฌ๊ธฐ์ ๋ ์๋ ์ง๋ฌธ์ ๊ฐ์ง ์ ์์ต๋๋ค. ๊ฐ๋ฅํ์ต๋๊น? ๊ทธ๋ฌํ ์ฝ๋์ ์คํ ์์ ์ฑ์ ์ด๋ป๊ฒ ๋ณด์ฅ๋ฉ๋๊น? verifier๋ผ๊ณ ํ๋ BPF ํ๋ก๊ทธ๋จ์ ๋ก๋ํ๋ ๋จ๊ณ์์ ์คํ ์์ ์ฑ์ด ๋ณด์ฅ๋ฉ๋๋ค(์์ด์์๋ ์ด ๋จ๊ณ๋ฅผ verifier๋ผ๊ณ ํ๋ฉฐ ๊ณ์ํด์ ์์ด ๋จ์ด๋ฅผ ์ฌ์ฉํ๊ฒ ์ต๋๋ค).
Verifier๋ ํ๋ก๊ทธ๋จ์ด ์ปค๋์ ์ ์์ ์ธ ์๋์ ๋ฐฉํดํ์ง ์๋์ง ํ์ธํ๋ ์ ์ ๋ถ์๊ธฐ์ ๋๋ค. ์ด๋ ํ๋ก๊ทธ๋จ์ด ์์คํ ์๋์ ๋ฐฉํดํ ์ ์๋ค๋ ์๋ฏธ๋ ์๋๋๋ค. BPF ํ๋ก๊ทธ๋จ์ ์ ํ์ ๋ฐ๋ผ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ ์น์ ์ ์ฝ๊ณ ๋ค์ ์ธ ์ ์๊ณ , ํจ์ ๊ฐ์ ๋ฐํํ๊ณ , ๋ค๋ฌ๊ณ , ์ถ๊ฐํ๊ณ , ๋ค์ ์ธ ์ ์์ต๋๋ค. ๋คํธ์ํฌ ํจํท์ ์ ๋ฌํ ์๋ ์์ต๋๋ค. Verifier๋ BPF ํ๋ก๊ทธ๋จ์ ์คํํ๋ฉด ์ปค๋์ด ์ถฉ๋ํ์ง ์์ผ๋ฉฐ ๊ท์น์ ๋ฐ๋ผ ์ฐ๊ธฐ ์ก์ธ์ค ๊ถํ์ด ์๋ ํ๋ก๊ทธ๋จ(์: ๋๊ฐ๋ ํจํท์ ๋ฐ์ดํฐ)์ด ํจํท ์ธ๋ถ์ ์ปค๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฎ์ด์ธ ์ ์์์ ๋ณด์ฅํฉ๋๋ค. BPF์ ๋ค๋ฅธ ๋ชจ๋ ๊ตฌ์ฑ ์์์ ๋ํด ์๊ฒ ๋ ํ ํด๋น ์น์ ์์ ๊ฒ์ฆ์๋ฅผ ์ข ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ผ ์ฐ๋ฆฌ๋ ์ง๊ธ๊น์ง ๋ฌด์์ ๋ฐฐ์ ๋์? ์ฌ์ฉ์๋ C๋ก ํ๋ก๊ทธ๋จ์ ์์ฑํ๊ณ ์์คํ
ํธ์ถ์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ์ปค๋์ ๋ก๋ํฉ๋๋ค. bpf(2)
, ๊ฒ์ฆ์์ ์ํด ํ์ธ๋๊ณ ๊ธฐ๋ณธ ๋ฐ์ดํธ์ฝ๋๋ก ๋ณํ๋ฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋์ผํ๊ฑฐ๋ ๋ค๋ฅธ ์ฌ์ฉ์๊ฐ ํ๋ก๊ทธ๋จ์ ์ด๋ฒคํธ ์์ค์ ์ฐ๊ฒฐํ๊ณ ์คํ์ ์์ํฉ๋๋ค. ์ฌ๋ฌ ๊ฐ์ง ์ด์ ๋ก ๋ถํ
๊ณผ ์ฐ๊ฒฐ์ ๋ถ๋ฆฌํด์ผ ํฉ๋๋ค. ์ฒซ์งธ, ๊ฒ์ฆ ํ๋ก๊ทธ๋จ์ ์คํํ๋ ๊ฒ์ ์๋์ ์ผ๋ก ๋น์ฉ์ด ๋ง์ด ๋ค๊ณ ๋์ผํ ํ๋ก๊ทธ๋จ์ ์ฌ๋ฌ ๋ฒ ๋ค์ด๋ก๋ํจ์ผ๋ก์จ ์ปดํจํฐ ์๊ฐ์ ๋ญ๋นํฉ๋๋ค. ๋์งธ, ํ๋ก๊ทธ๋จ์ด ์ฐ๊ฒฐ๋๋ ์ ํํ ๋ฐฉ์์ ์ ํ์ ๋ฐ๋ผ ๋ค๋ฅด๋ฉฐ, XNUMX๋
์ ์ ๊ฐ๋ฐ๋ ํ๋์ "์ ๋๋ฒ์ค" ์ธํฐํ์ด์ค๋ ์๋ก์ด ์ ํ์ ํ๋ก๊ทธ๋จ์๋ ์ ํฉํ์ง ์์ ์ ์์ต๋๋ค. (์ง๊ธ์ ์ํคํ
์ฒ๊ฐ ์ฑ์ํด์ง๊ณ ์์ง๋ง, ์ด ์ธํฐํ์ด์ค๋ฅผ ๋ ๋ฒจ์์ ํตํฉํ๋ ค๋ ์์ด๋์ด๊ฐ ์์ต๋๋ค. libbpf
.)
์ฃผ์ ๊น์ ๋ ์๋ผ๋ฉด ์ฐ๋ฆฌ๊ฐ ์์ง ๊ทธ๋ฆผ ์์ ์ ๋ง์น์ง ์์๋ค๋ ๊ฒ์ ์์์ฐจ๋ฆด ์๋ ์์ ๊ฒ์ ๋๋ค. ์ค์ ๋ก ์์ ๋ชจ๋ ๋ด์ฉ์ BPF๊ฐ ๊ธฐ๋ณธ BPF์ ๋นํด ๊ทธ๋ฆผ์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ฐ๊พธ๋ ์ด์ ๋ฅผ ์ค๋ช ํ์ง ์์ต๋๋ค. ์ ์ฉ ๋ฒ์๋ฅผ ํฌ๊ฒ ํ์ฅํ๋ ๋ ๊ฐ์ง ํ์ ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ์ปค๋ ๋์ฐ๋ฏธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๋ ๊ธฐ๋ฅ์ ๋๋ค. BPF์์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ ์์ ๋งต(ํน์ API๋ฅผ ์ฌ์ฉํ ๊ณต์ ๋ฐ์ดํฐ ๊ตฌ์กฐ)์ ์ฌ์ฉํ์ฌ ๊ตฌํ๋ฉ๋๋ค. ์๋ง๋ ์ฒ์์ผ๋ก ๋ฑ์ฅํ ์ง๋ ์ ํ์ด ํด์ ํ ์ด๋ธ์ด์๊ธฐ ๋๋ฌธ์ ์ด ์ด๋ฆ์ ๊ฐ๊ฒ ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฐฐ์ด, ๋ก์ปฌ(CPU๋ณ) ํด์ ํ ์ด๋ธ ๋ฐ ๋ก์ปฌ ๋ฐฐ์ด, ๊ฒ์ ํธ๋ฆฌ, BPF ํ๋ก๊ทธ๋จ์ ๋ํ ํฌ์ธํฐ๊ฐ ํฌํจ๋ ๋งต ๋ฑ์ด ๋ํ๋ฌ์ต๋๋ค. ์ด์ ์ฐ๋ฆฌ์๊ฒ ํฅ๋ฏธ๋ก์ด ์ ์ BPF ํ๋ก๊ทธ๋จ์ด ์ด์ ํธ์ถ ๊ฐ์ ์ํ๋ฅผ ์ ์งํ๊ณ ์ด๋ฅผ ๋ค๋ฅธ ํ๋ก๊ทธ๋จ ๋ฐ ์ฌ์ฉ์ ๊ณต๊ฐ๊ณผ ๊ณต์ ํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค.
๋งต์ ์์คํ
ํธ์ถ์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ํ๋ก์ธ์ค์์ ์ก์ธ์ค๋ฉ๋๋ค. bpf(2)
, ๊ทธ๋ฆฌ๊ณ ๋์ฐ๋ฏธ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ปค๋์์ ์คํ๋๋ BPF ํ๋ก๊ทธ๋จ์์. ๋์ฑ์ด, ๋งต ์์
๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ์ปค๋ ๊ธฐ๋ฅ์ ์ก์ธ์คํ๊ธฐ ์ํ ํฌํผ๋ ์กด์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด 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
struct __sk_buff
struct pt_regs
๊ทธ๋์ ์ฐ๋ฆฌ๋ ๋ ์ง์คํฐ ์ธํธ, ์ปค๋ ๋์ฐ๋ฏธ, ์คํ, ์ปจํ ์คํธ ํฌ์ธํฐ ๋ฐ ๋งต ํํ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ๊ฒ ๋์์ต๋๋ค. ์ฌํ์์ ์ด ๋ชจ๋ ๊ฒ์ด ๊ผญ ํ์ํ ๊ฒ์ ์๋์ง๋ง...
๊ณ์ํด์ ์ค๋ช
ํ๊ณ ์ด๋ฌํ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๋ช
๋ น ์์คํ
์ ๋ํด ์ด์ผ๊ธฐํด ๋ณด๊ฒ ์ต๋๋ค. ๋ชจ๋ (
์ฌ๊ธฐ์ Code
- ์ด๊ฒ์ ๋ช
๋ น์ด์ ์ธ์ฝ๋ฉ์
๋๋ค. Dst
/Src
๋ ๊ฐ๊ฐ ์์ ์์ ์์ค์ ์ธ์ฝ๋ฉ์
๋๋ค. Off
- 16๋นํธ ๋ถํธ ์๋ ๋ค์ฌ์ฐ๊ธฐ ๋ฐ Imm
์ผ๋ถ ๋ช
๋ น์ด์ ์ฌ์ฉ๋๋ 32๋นํธ ๋ถํธ ์๋ ์ ์์
๋๋ค(cBPF ์์ K์ ์ ์ฌ). ๋ถํธํ Code
๋ ๊ฐ์ง ์ ํ ์ค ํ๋๊ฐ ์์ต๋๋ค.
๋ช
๋ น์ด ํด๋์ค 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๋ฅผ ๋ถํดํ๋ ์ค
ํ๋ก๊ทธ๋จ์ ์ปดํ์ผํ๋ ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. 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
-๊ฐ์ s
(์์ค)์ด๋ฉด ์์ค ๋ ์ง์คํฐ์์ ๊ฐ์ ๊ฐ์ ธ์ค๊ณ , ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ์ฒ๋ผ ์ค์ ๋์ง ์์ ๊ฒฝ์ฐ ํ๋์์ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค. Imm
. ๋ฐ๋ผ์ ์ฒซ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ์ง์นจ์์๋ ์์
์ ์ํํฉ๋๋ค. r0 = Imm
. ๋ํ JMP ํด๋์ค 1 ์์
์ 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_PROG_LOAD
ะธ BPF_MAP_CREATE
์์คํ
ํธ์ถ bpf(2)
, ๋ค์ ์น์
์์ ์ด๊ฒ์ด ์ด๋ป๊ฒ ๋ฐ์ํ๋์ง ์ ํํ ์ค๋ช
ํ๊ฒ ์ต๋๋ค. ์ด๊ฒ์ ์ปค๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์์ฑํ๊ณ ๊ฐ๊ฐ์ ๋ํด refcount
(์ฐธ์กฐ ํ์)๊ฐ XNUMX๋ก ์ค์ ๋๊ณ ํด๋น ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํค๋ ํ์ผ ์ค๋ช
์๊ฐ ์ฌ์ฉ์์๊ฒ ๋ฐํ๋ฉ๋๋ค. ์์ก์ด๋ฅผ ๋ซ์ ํ refcount
๊ฐ์ฒด๋ XNUMX๋งํผ ๊ฐ์ํ๊ณ , XNUMX์ ๋๋ฌํ๋ฉด ๊ฐ์ฒด๊ฐ ํ๊ดด๋ฉ๋๋ค.
ํ๋ก๊ทธ๋จ์ด ์ง๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ refcount
์ด ์ง๋๋ ํ๋ก๊ทธ๋จ์ ๋ก๋ํ ํ XNUMX์ฉ ์ฆ๊ฐํฉ๋๋ค. ์ฆ, ํด๋น ํ์ผ ์ค๋ช
์๋ ์ฌ์ฉ์ ํ๋ก์ธ์ค์์ ๋ซํ ์ ์์ง๋ง ์ฌ์ ํ refcount
XNUMX์ด ๋์ง ์์ต๋๋ค:
ํ๋ก๊ทธ๋จ์ ์ฑ๊ณต์ ์ผ๋ก ๋ก๋ํ ํ ์ผ๋ฐ์ ์ผ๋ก ์ด๋ฅผ ์ผ์ข
์ ์ด๋ฒคํธ ์์ฑ๊ธฐ์ ์ฐ๊ฒฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ฅผ ๋คํธ์ํฌ ์ธํฐํ์ด์ค์ ๋ฐฐ์นํ์ฌ ๋ค์ด์ค๋ ํจํท์ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ผ๋ถ ์ธํฐํ์ด์ค์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค. tracepoint
ํต์ฌ์. ์ด ์์ ์์ ์ฐธ์กฐ ์นด์ดํฐ๋ XNUMX์ฉ ์ฆ๊ฐํ๊ณ ๋ก๋ ํ๋ก๊ทธ๋จ์์ ํ์ผ ์ค๋ช
์๋ฅผ ๋ซ์ ์ ์์ต๋๋ค.
์ด์ ๋ถํธ๋ก๋๋ฅผ ์ข ๋ฃํ๋ฉด ์ด๋ป๊ฒ ๋๋์? ์ด๋ฒคํธ ์์ฑ๊ธฐ(ํํฌ)์ ์ ํ์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ๋ชจ๋ ๋คํธ์ํฌ ํํฌ๋ ๋ก๋๊ฐ ์๋ฃ๋ ํ์ ์กด์ฌํ๊ฒ ๋๋ฉฐ, ์ด๋ฅผ ๊ธ๋ก๋ฒ ํํฌ๋ผ๊ณ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ถ์ ํ๋ก๊ทธ๋จ์ ์ด๋ฅผ ์์ฑํ ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ ํ์ ํด์ ๋ฉ๋๋ค(๋ฐ๋ผ์ "๋ก์ปฌ์์ ํ๋ก์ธ์ค๋ก"๋ผ๋ ๋ป์ผ๋ก ๋ก์ปฌ์ด๋ผ๊ณ ํจ). ๊ธฐ์ ์ ์ผ๋ก ๋ก์ปฌ ํํฌ๋ ํญ์ ์ฌ์ฉ์ ๊ณต๊ฐ์ ํด๋น ํ์ผ ์ค๋ช ์๋ฅผ ๊ฐ๊ณ ์์ผ๋ฏ๋ก ํ๋ก์ธ์ค๊ฐ ๋ซํ ๋ ๋ซํ์ง๋ง ๊ธ๋ก๋ฒ ํํฌ๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ๋ค์ ๊ทธ๋ฆผ์์๋ ๋นจ๊ฐ์ ์ญ์๊ฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ก์ปฌ ๋ฐ ์ ์ญ ํํฌ์ ๊ฒฝ์ฐ ๋ก๋ ํ๋ก๊ทธ๋จ ์ข ๋ฃ๊ฐ ๊ฐ์ฒด ์๋ช ์ ์ด๋ค ์ํฅ์ ๋ฏธ์น๋์ง ๋ณด์ฌ์ค๋๋ค.
๋ก์ปฌ ํํฌ์ ๊ธ๋ก๋ฒ ํํฌ๊ฐ ๊ตฌ๋ณ๋๋ ์ด์ ๋ ๋ฌด์์ ๋๊น? ์ผ๋ถ ์ ํ์ ๋คํธ์ํฌ ํ๋ก๊ทธ๋จ์ ์คํํ๋ ๊ฒ์ ์ฌ์ฉ์ ๊ณต๊ฐ ์์ด๋ ๊ฐ๋ฅํฉ๋๋ค. ์๋ฅผ ๋ค์ด DDoS ๋ณดํธ๋ฅผ ์์ํด ๋ณด์ธ์. ๋ถํธ๋ก๋๊ฐ ๊ท์น์ ์์ฑํ๊ณ BPF ํ๋ก๊ทธ๋จ์ ๋คํธ์ํฌ ์ธํฐํ์ด์ค์ ์ฐ๊ฒฐํ ํ ๋ถํธ๋ก๋๊ฐ ์ค์ค๋ก ์ข ๋ฃ๋ ์ ์์ต๋๋ค. ๋ฐ๋ฉด์ XNUMX๋ถ ๋ง์ ๋ฌด๋ฆ์ ๊ฟ๊ณ ์์ฑํ ๋๋ฒ๊น ์ถ์ ํ๋ก๊ทธ๋จ์ ์์ํด ๋ณด์ญ์์ค. ์์ ์ด ์๋ฃ๋๋ฉด ์์คํ ์ ์ฐ๋ ๊ธฐ๊ฐ ๋จ์ ์์ง ์๊ธฐ๋ฅผ ์ํ๋ฉฐ ๋ก์ปฌ ํํฌ๊ฐ ์ด๋ฅผ ๋ณด์ฅํฉ๋๋ค.
๋ฐ๋ฉด์ ์ปค๋์ ์ถ์ ์ ์ ์ฐ๊ฒฐํ์ฌ ์๋
์ ๊ฑธ์ณ ํต๊ณ๋ฅผ ์์งํ๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. ์ด ๊ฒฝ์ฐ ์ฌ์ฉ์ ๋ถ๋ถ์ ์๋ฃํ๊ณ ๋๋๋ก ํต๊ณ๋ก ๋์๊ฐ๊ณ ์ถ์ ๊ฒ์
๋๋ค. bpf ํ์ผ ์์คํ
์ ์ด๋ฌํ ๊ธฐํ๋ฅผ ์ ๊ณตํฉ๋๋ค. BPF ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ํ์ผ ์์ฑ์ ํ์ฉํ๋ ๋ฉ๋ชจ๋ฆฌ ๋ด ์ ์ฉ ์์ฌ ํ์ผ ์์คํ
์
๋๋ค. refcount
์ฌ๋ฌผ. ๊ทธ ํ์๋ ๋ก๋๊ฐ ์ข
๋ฃ๋ ์ ์์ผ๋ฉฐ ์์ฑ๋ ๊ฐ์ฒด๋ ๊ณ์ ์ด์ ์์ต๋๋ค.
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
. ์ด ๊ฒฝ์ฐ ์ด์ ๋ฒ์ ํ๋ก๊ทธ๋จ์ ๋ชจ๋ ํ์ฑ ์ธ์คํด์ค๊ฐ ์์
์ ์๋ฃํ๊ณ ์ ํ๋ก๊ทธ๋จ์์ ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์์ฑ๋๋ฉฐ ์ฌ๊ธฐ์ "์์์ฑ"์ ๋จ์ผ ์ด๋ฒคํธ๊ฐ ๋๋ฝ๋์ง ์์์ ์๋ฏธํฉ๋๋ค.
์ด๋ฒคํธ ์์ค์ ํ๋ก๊ทธ๋จ ์ฐ๊ฒฐ
์ด ๊ธฐ์ฌ์์๋ ํ๋ก๊ทธ๋จ์ ์ด๋ฒคํธ ์์ค์ ์ฐ๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋ณ๋๋ก ์ค๋ช
ํ์ง ์์ต๋๋ค. ํน์ ์ ํ์ ํ๋ก๊ทธ๋จ ๋งฅ๋ฝ์์ ์ด๋ฅผ ์ฐ๊ตฌํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ์ผํฐ๋ฏธํฐ.
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_LOAD
BPF ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ , BPF ๋ช
๋ น์ด ์ธํธ๋ฅผ ๊ฐ์ ธ์ ์ปค๋์ ๋ก๋ํฉ๋๋ค. ๋ก๋ฉํ๋ ์๊ฐ ๊ฒ์ฆ์๊ฐ ์คํ๋๊ณ , JIT ์ปดํ์ผ๋ฌ๊ฐ ์คํ๋๊ณ , ์ฑ๊ณต์ ์ผ๋ก ์คํ๋๋ฉด ํ๋ก๊ทธ๋จ ํ์ผ ๋์คํฌ๋ฆฝํฐ๊ฐ ์ฌ์ฉ์์๊ฒ ๋ฐํ๋ฉ๋๋ค. ์ฐ๋ฆฌ๋ ์ด์ ์น์
์์ ๊ทธ์๊ฒ ๋ค์์ ๋ฌด์จ ์ผ์ด ์ผ์ด๋๋์ง ๋ณด์์ต๋๋ค.
์ด์ ๊ฐ๋จํ 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 ์ง์์ผ๋ก ์ปดํ์ผ๋์ด์ผ ํฉ๋๋ค(์ด ์์
์ ์ํํ๋ ๋ฐฉ๋ฒ์ ์น์
์์ ์ค๋ช
ํฉ๋๋ค).
$ 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]
. ๊ทธ๋ฌ๋ ์ปค๋ ์ธ๋ถ์ ์๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์๊ตฌ์ ๋ฐ๋ผ ๋ณ๋์ ์ ์ฅ์๊ฐ ์ ์ง๋ฉ๋๋ค.
์ด๋ฒ ์น์
์์๋ ๋ค์์ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. 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
๋
ผ๋ฆฌ๋ฅผ ๋ ์ฝ๊ฒ ๋ฐ๋ฅด๋๋ก ํ๊ธฐ ์ํด ์ด๋ฌํ ๋ชฉ์ ์ ๋ง๊ฒ ์์ ๋ฅผ ๋ค์ ์์ฑํ๊ฒ ์ต๋๋ค. 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) ์ปค๋๊ณผ ์ํธ์์ฉํ๊ธฐ ์ํ ์ธํฐํ์ด์ค: 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
๋ด๊ฐ ๊ฐ์ ธ์จ ๊ฒ
๋ฐฉ๊ธ ๋ง๋ ํ๋ก๊ทธ๋จ์ ์ค์นํ์ง ์๊ณ ๋์ ์ ํ๋ก๊ทธ๋จ์ ์ถ๊ฐํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. 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๋ฅผ ์คํํ๊ธฐ ์ํด ์ฐ๋ฆฌ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค net
net-next
bpf
bpf-next
*-next
์ปค๋์ ๋์ด๋ ๊ฒ ์ค ๊ฐ์ฅ ๋ถ์์ ํฉ๋๋ค.)
์ปค๋ ๊ตฌ์ฑ ํ์ผ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช
ํ๋ ๊ฒ์ ์ด ๊ธฐ์ฌ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋ฉ๋๋ค. ์ด ์์
์ ์ํํ๋ ๋ฐฉ๋ฒ์ ์ด๋ฏธ ์๊ณ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
์ ์ปค๋ ์ค ํ๋๋ฅผ ๋ค์ด๋ก๋ํ์ญ์์ค.
$ 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 ๋คํธ์ํน ๋ฐ ๋ณด์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์ด ์๋ฆฌ์ฆ์ ์ด์ ๊ธฐ์ฌ
์ฐ๊ฒฐ
-
BPF ๋ฐ XDP ์ฐธ์กฐ ๊ฐ์ด๋ โ cilium์ BPF์ ๋ํ ๋ฌธ์, ๋ ์ ํํ๊ฒ๋ BPF์ ์ฐฝ์์์ด์ ์ ์ง๊ด๋ฆฌ์ ์ค ํ ๋ช ์ธ Daniel Borkman์ ๋ฌธ์์ ๋๋ค. ์ด๊ฒ์ ๋ค๋์์ด ์์ ์ด ์ฐ๊ณ ์๋ ๋ด์ฉ์ ์ ํํ ์๊ณ ๊ฑฐ๊ธฐ์ ์ค์๊ฐ ์๋ค๋ ์ ์์ ๋ค๋ฅธ ์ค๋ช ๊ณผ ๋ค๋ฅธ ์ต์ด์ ์ง์งํ ์ค๋ช ์ค ํ๋์ ๋๋ค. ํนํ ์ด ๋ฌธ์์์๋ ์ ์๋ ค์ง ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ์ฌ XDP ๋ฐ TC ์ ํ์ BPF ํ๋ก๊ทธ๋จ์ผ๋ก ์์ ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.ip
ํจํค์ง์์iproute2
. -
๋ฌธ์/๋คํธ์ํน/filter.txt โ ํด๋์ ๋ฐ ํ์ฅ BPF์ ๋ํ ๋ฌธ์๊ฐ ํฌํจ๋ ์๋ณธ ํ์ผ์ ๋๋ค. ์ด์ ๋ธ๋ฆฌ ์ธ์ด์ ๊ธฐ์ ์ ์ธ ์ํคํ ์ฒ ์ธ๋ถ ์ฌํญ์ ์์ธํ ์์๋ณด๊ณ ์ถ๋ค๋ฉด ์ฝ์ด๋ณด๋ฉด ์ข์ต๋๋ค. -
Facebook์ BPF ๊ด๋ จ ๋ธ๋ก๊ทธ . ๊ฑฐ์ ์ ๋ฐ์ดํธ๋์ง ์์ง๋ง Alexei Starovoitov(eBPF ์์ฑ์)์ Andrii Nakryiko(๊ด๋ฆฌ์)๊ฐ ๊ฑฐ๊ธฐ์ ์ด ๊ฒ์ฒ๋ผ ์ ์ ํ๊ฒ ์ ๋ฐ์ดํธ๋ฉ๋๋ค.libbpf
). -
bpftool์ ๋น๋ฐ . bpftool ์ฌ์ฉ์ ์์ ๋น๋ฐ์ ๋ด์ Quentin Monnet์ ์ฌ๋ฏธ์๋ ํธ์ํฐ ์ค๋ ๋์ ๋๋ค. -
BPF ์ดํด๋ณด๊ธฐ: ์ฝ๊ธฐ ์๋ฃ ๋ชฉ๋ก . Quentin Monnet์ BPF ๋ฌธ์์ ๋ํ ๋๊ท๋ชจ(๊ทธ๋ฆฌ๊ณ ์ฌ์ ํ ์ ์ง ๊ด๋ฆฌ๋๋) ๋งํฌ ๋ชฉ๋ก์ ๋๋ค.
์ถ์ฒ : habr.com