内部実装¶
NAT / DHCP / DNS の内部実装は「SONiC は何を ASIC に任せ、何を Linux user space daemon に任せているか」の切り分けを意識すると整理しやすいです。NAT は SAI で hardware offload する path と conntrack で kernel に任せる path があり、DHCP は relay agent / server agent の二種類、DNS は基本 systemd-resolved + /etc/resolv.conf です。
データフロー¶
NAT¶
flowchart LR
CFG[(CONFIG_DB<br/>NAT_POOL/NAT_BINDINGS/STATIC_NAT)] --> NATMGR[natmgrd]
NATMGR --> APPL[(APPL_DB<br/>NAT_TABLE/NAPT_TABLE)]
NATMGR --> KERNEL[iptables / conntrack]
APPL --> NATORCH[NatOrch]
NATORCH --> ASIC[(ASIC_DB<br/>SAI_NAT_ENTRY)]
KERNEL -->|netlink conntrack| NATSYNCD[natsyncd]
NATSYNCD --> APPL
DHCP relay / DHCP server¶
flowchart LR
CFG[(CONFIG_DB<br/>DHCP_RELAY/DHCP_SERVER_IPV4)] --> DHCPRELAY[dhcprelay<br/>isc-dhcp-relay or dhcpmon]
CFG --> DHCPSRV[dhcp_server_ipv4<br/>kea-dhcp4]
DHCPRELAY --> CLIENT[client]
DHCPSRV --> LEASE[(STATE_DB<br/>DHCP_SERVER_IPV4_LEASE)]
主要 daemon の責務¶
NAT¶
| コンポーネント | 主実体 | 責務 |
|---|---|---|
natmgrd (cfgmgr/natmgr.cpp) |
NatMgr::doTask |
STATIC_NAT / STATIC_NAPT / NAT_POOL / NAT_BINDINGS を iptables と APPL_DB に展開 |
NatOrch (orchagent/natorch.cpp) |
NatOrch::doTask、addNatEntry、removeNatEntry |
APPL_DB を読み SAI NAT entry に投入 |
natsyncd (natsyncd/natsync.cpp) |
conntrack netlink listener | kernel conntrack イベントを APPL_DB:NAT_TABLE に sync(ダイナミック NAT の hardware offload) |
iptables rules (NAT/MANGLE) |
natmgrd が生成 | 初回パケットを kernel で NAT してから ASIC に load する |
DHCP¶
| コンポーネント | 主実体 | 責務 |
|---|---|---|
dhcprelay (dockers/docker-dhcp-relay) |
isc-dhcp-relay + dhcpmon |
DHCPv4 / DHCPv6 relay。dhcpmon がカウンタを STATE_DB に書く |
dhcp_server_ipv4 (src/sonic-dhcp-server) |
kea-dhcp4 based |
フル DHCP server。DHCP_SERVER_IPV4* 系テーブルから設定生成、lease を Redis に書く |
dhcp6relay |
isc-dhcp-relay -6 | DHCPv6 relay |
DNS¶
| コンポーネント | 主実体 | 責務 |
|---|---|---|
resolv.conf 管理 |
hostcfgd の DNS task |
CONFIG_DB:DNS_NAMESERVER から /etc/resolv.conf 生成 |
SAI 属性使用一覧¶
NAT 関連:
| object | 属性 |
|---|---|
SAI_OBJECT_TYPE_NAT_ENTRY |
SAI_NAT_ENTRY_ATTR_NAT_TYPE = SOURCE_NAT/DESTINATION_NAT/DOUBLE_NAT、SAI_NAT_ENTRY_ATTR_SRC_IP、SAI_NAT_ENTRY_ATTR_DST_IP、SAI_NAT_ENTRY_ATTR_HIT_BIT、SAI_NAT_ENTRY_ATTR_AGING_TIME |
SAI_OBJECT_TYPE_ROUTER_INTERFACE |
SAI_ROUTER_INTERFACE_ATTR_NAT_ZONE_ID(NAT zone を rif に紐付け) |
SAI_OBJECT_TYPE_SWITCH |
SAI_SWITCH_ATTR_NAT_ENABLE(NAT 機能の全体スイッチ) |
DHCP / DNS には SAI 属性は使われません(kernel で完結)。
Redis テーブル参照関係¶
CONFIG_DB:
NAT_POOL, NAT_BINDINGS, STATIC_NAT, STATIC_NAPT, NAT_GLOBAL,
DHCP_RELAY, DHCP_SERVER_IPV4, DHCP_SERVER_IPV4_*,
DNS_NAMESERVER
APPL_DB:
NAT_TABLE, NAPT_TABLE, NAT_TWICE_TABLE, NAPT_TWICE_TABLE
STATE_DB:
NAT_TABLE, NAPT_TABLE, NAT_RESTORE_TABLE,
DHCP_SERVER_IPV4_LEASE,
DHCPv4_COUNTERS_TABLE, DHCPv6_COUNTERS_TABLE
ASIC_DB:
NAT_ENTRY
ZMQ / Redis pub/sub¶
- NAT: 通常の ProducerStateTable / SubscriberStateTable のみ。
natsyncdはconntrack-toolsの netlink を直接 listen し、Redis に書く片方向経路。conntrack 自体が pub/sub ではない点に注意。- DHCP:
dhcpmonが pcap または syslog をパースする実装で、Redis 経由ではなく直接 counter を STATE_DB に書く。 - DNS: pub/sub 経路はありません。
既知の実装上の制約¶
- NAT の hardware offload は ASIC によって対応・非対応が分かれます。
SAI_SWITCH_ATTR_NAT_ENABLEがサポートされていない ASIC では NAT は kernel のみ動作し、large flow のスループットが極端に落ちます。 natsyncdは conntrack の age を SAI に正確に反映できないことがあり、SAI_NAT_ENTRY_ATTR_HIT_BITを polling して timeout を判断する設計に依存します。これがベンダ SAI で未対応だと NAT entry が枯渇しやすいです。- DHCP server (
kea-dhcp4) はまだ全機能を網羅しておらず、特に option 82 周辺と高可用構成は限定的です。 - DHCP relay の counter は
dhcpmonが pcap-based で kernel iptables NFLOG を見ている実装で、高負荷時にパケットを取りこぼします。「relay packets」を SLA に使うのは避けてください。 - DNS は SONiC で独自設定はなく、
hostcfgdが/etc/resolv.confを上書きする単純な実装。DNS-over-TLS や split-DNS は未対応。 - IPv6 NAT(NAT66 / NPTv6)は SAI で属性は定義されているが、SONiC orchagent の対応が partial で、HLD と実装の discrepancy が出やすい部分です。
DHCP relay の packet path¶
DHCP relay (dhcprelayd および kea-dhcp4/kea-dhcp6 relay モード) は CoPP 経由で trap された DHCP パケットを処理します。
flowchart LR
CLIENT[DHCP client] -->|broadcast / multicast| PORT[ingress port]
PORT -->|CoPP trap| CPU[CPU queue]
CPU --> KERNEL[Linux kernel]
KERNEL --> RELAY[dhcprelayd / kea]
RELAY -->|unicast to server_vip| EGRESS[egress port]
RELAY -->|stats| DHCPMON[dhcpmon NFLOG]
DHCPMON --> STATE[(STATE_DB<br/>DHCP_COUNTER_TABLE)]
CoPP の trap group dhcp / dhcpv6 がデフォルトで設定され、レート制限は COPP_TABLE の cir/cbs で調整されます。dhcpmon の counter は NFLOG ベースで参考値扱いが妥当です。