리눅스 커널 소스 net 디렉터리 아래의 서브디렉터리들 중에 이름에 “filter”가 들어간 건 한동안 netfilter뿐이었다. 그런데 버전 4.18에서 bpfilter라는 친구가 생겼다.

ipchains 시절까지는 잘 모르겠으니 넘어가고, 그걸 개량한 게 iptables이고 이후 여러 프로토콜로 확장됐다. IPv4/IPv6/ARP/브리지마다 규칙 테이블이 따로 있고 match/target도 상당수가 테이블마다 따로 있다. 비효율적이고 불편하다. 그래서 몇 해 전 새로 등장한 게 nftables다. match/target 구분이 없어지고 IPv4/IPv6 공통 테이블도 생기고 기타 여러 가지가 좋아졌다. 이제 xtables가 슬슬 퇴역하면서 nftables가 그 자리를 차지하면 되는 시나리오였다. 그런데 그 예정된 역사에 요동이 생겼다.

사실 nftables도 완벽하진 않다. 새로운 expression(=match+target)을 추가하려면 여전히 커널과 사용자 공간에 모듈을 추가해야 한다. 그리고 그런 모듈 구조는 패킷 처리 성능 측면에서 꽤 불리하다. 대다수 netfilter 모듈에서 하는 동작은 패킷 헤더나 메타 정보의 필드 한두 개를 읽거나 쓰는 것이고, 그래서 그 동작을 하는 함수에 들어갔다가 나오는 데 훨씬 많은 CPU 사이클을 소모할 수 있다. 그렇다고 여러 기능을 합쳐서 큰 덩어리를 만들자니 복잡해지고 유연성이 떨어진다.

변화의 조짐은 xt_bpf match 모듈에서 보였다. (BPF 소개 글 참고.) “IP 헤더 Version 필드 값이 4이고, IP 헤더 Source IP Address 값이 빅엔디언 0x7f000001이 아니고, IP 헤더 Protocol 값이 6이고, TCP 헤더 Destination Port 필드 값이 빅엔디언 80” 같은 조건을 BPF 프로그램 하나로 기술할 수 있다. tcpdump에서 하는데 netfilter에서 못 할 이유가 없다.

그러면 또 생각을 해 볼 수 있다. match 하나만이 아니라 규칙을, 그것도 여러 개를 BPF 프로그램 하나로 구현할 수 있지 않을까? REJECT target처럼 추가 동작이 필요한 건 헬퍼 함수 도움을 받아 가면서 말이다. match/target마다 함수를 들락거릴 필요가 없으니 규칙 복잡도가 일정 수준을 넘으면 기존 넷필터보다 성능이 빠를 테고 JIT 컴파일이 있으니 그 경계는 꽤 낮을 거다.

그리고 또 생각을 해 볼 수 있다. 사용자가 넷필터 규칙 세트를 교체할 때 그 과정에 슬며시 끼어들어서 넷필터 규칙들을 bpfilter 프로그램으로 변환할 수 있지 않을까. 그러면 기존 넷필터의 성능이 향상되는 효과도 있고 bpfilter로 옮겨가는 문턱을 낮추는 효과도 있다. 뭣하면 LED target 같은 게 없을 때만 그럴 수도 있을 거다.

또 BPF 프로그램을 좀 비싼 NIC에서 실행할 수도 있을 거다. 그리고 BPF 프로그램을 SDN 컨트롤러에서 노드들로 배포할 수도 있을 거다.

현재는 최신 버전 커널에 골격만 들어가 있는 상태다. 개념 확인용 코드에는 살이 좀 붙어 있지만 완전한 형태는 아니다. 내년 정도면 제대로 동작하는 뭔가를 볼 수 있을까?