コンテンツにスキップ

アーキテクチャ

この章は NAT、DHCP relay、DHCP server の内部構造を「container → daemon → 設定生成 → packet path」の順に並べます。time / DNS と TWAMP Light は OS / SAI 寄りなので発展トピックに分けました。

docker-nat と NAT orch

NAT は docker-nat という独立 container に閉じています。中で動く daemon は次の通りです。

  • natmgrd: CONFIG_DBSTATIC_NAT / STATIC_NAPT / NAT_POOL / NAT_BINDINGS / NAT_ZONE / NAT_GLOBAL を読み、Linux iptables の nat table と conntrack を設定します。sonic-swss/cfgmgr/natmgrd.cpp 系で実装されています。
  • natsyncd: kernel の conntrack notification を購読し、動的 NAT entry を APP_DB に push します。sonic-swss/natsyncd/natsyncd.cpp 系です。
  • NatOrch: orchagent 側の sub-orch で、APP_DB の NAT entry を SAI NAT API(SAI_OBJECT_TYPE_NAT_ENTRY)にプログラムします。
flowchart LR
  CFG[(CONFIG_DB STATIC_NAT/NAT_*)] --> NM[natmgrd]
  NM --> IPT[iptables nat table]
  CT[kernel conntrack] --> NS[natsyncd]
  NS --> APP[(APP_DB NAT_TABLE)]
  APP --> NO[NatOrch]
  NO --> SAI[SAI NAT entry]
  SAI --> ASIC[(ASIC_DB)]

要点は、static NAT は CONFIG_DB → iptables + SAI の経路、dynamic NAT は kernel が学習した conntrack を natsyncd が拾って SAI にも push する経路、という二段構成です。CPU を抜けるフローと ASIC ハードウェアパスのフローで挙動が分かれるため、counter 確認も別パスで見ます。

docker-dhcp-relay と dhcrelay / dhcpmon / dhcprelayd

docker-dhcp-relay には複数プロセスが supervisord で起動します。

  • dhcrelay(v4): VLAN ごとに 1 プロセス。docker-dhcp-relay/dhcp-relay.programs.j2DHCP_RELAY[vlan_name]['dhcp_servers'] から program:dhcrelay-Vlan<N> が生成されます。
  • dhcrelay -6: 同 container に並走し、dhcpv6_servers を持つ VLAN だけ起動します。DHCPv6 リレー HLD はこの並走構成を定義したものです。
  • dhcpmon: relay と並走して DHCP packet を監視し、per-interface counter を COUNTERS_DB に書きます。マルチスレッド化済みです。
  • dhcp6relay: 独立した DHCPv6 relay daemon(sonic-dhcp-relay リポジトリ)。Option 79(RFC 6939)対応と dual-ToR の loopback アドレス利用が責務です。
  • dhcprelayd: kea ローカルモードのとき dhcrelay 側と協調して動的に config を更新する agent です。
flowchart LR
  C[(CONFIG_DB DHCP_RELAY/VLAN)] --> SUP[supervisord templates]
  SUP --> D4[dhcrelay -4 per VLAN]
  SUP --> D6[dhcrelay -6 per VLAN]
  SUP --> M[dhcpmon per VLAN]
  SUP --> D6R[dhcp6relay]
  SUP --> DR[dhcprelayd]
  D4 -->|stats syslog/SHM| M
  M --> CD[(COUNTERS_DB DHCPV4/V6_COUNTER_TABLE)]
  D6R --> CD

per-interface counter は VLAN / PortChannel 単位だけでなく interface 単位で DHCPV4_COUNTER_TABLE / DHCPV6_COUNTER_TABLE を持つよう拡張されています。詳細は per-interface counter ページを参照してください。

giaddr 固定(secondary subnet 対応)

VLAN_INTERFACE に secondary IPv4 を付けると、デフォルトの dhcrelay は最初に見つけたアドレスを giaddr にしてしまい、server 側 pool 選択がブレます。SONiC は ISC dhcrelay にパッチ(-pg)を当てて、primary subnet の gateway を明示するようテンプレート(dhcpv4-relay.agents.j2)で VLAN_INTERFACE | get_primary_addr を回しています。config interface ip add --secondary で書き込む secondary: "true" フラグが起点です。詳細は giaddr 固定ページを参照してください。

docker-dhcp-server と kea-dhcp4

ポートベース IPv4 DHCP server は kea を使います。

  • dhcpservd: CONFIG_DB の DHCP_SERVER_IPV4 / DHCP_SERVER_IPV4_RANGE / DHCP_SERVER_IPV4_PORT / DHCP_SERVER_IPV4_CUSTOMIZED_OPTIONS を読み、kea-dhcp4.conf を生成して kea を再起動します。
  • kea-dhcp4: 実際の DHCP server プロセス。relay からの giaddr で subnet を選び、port 単位の reservation を Option 82 circuit-id 経由で照合します。
  • lease_update.sh: kea の lease ファイル変更を FDB / ARP と同期する hook。
flowchart LR
  CFG[(CONFIG_DB DHCP_SERVER_IPV4*)] --> DS[dhcpservd]
  DS --> KC[kea-dhcp4.conf]
  KC --> K[kea-dhcp4]
  DR[dhcrelay] -->|giaddr + Option 82| K
  K -->|leases| LU[lease_update.sh]
  LU --> ST[(STATE_DB)]

FEATURE テーブルで docker-dhcp-server を有効化するのが起点で、無効化されている装置では dhcprelayd が外部 server 向けに動作します。詳細は port-based DHCP server ページを参照してください。

DHCP DoS 緩和(portmgrd + Linux tc)

DHCP DoS 緩和は SAI / CoPP ではなく Linux Traffic Control を使う設計です。PORTdhcp_rate_limitportmgrd が読み、tc qdisc add dev <port> ingresstc filter を投入します。ただし master では portmgrd 側の tc 投入ロジックは未取り込みで、CoPP の dhcp_relay trap も従来どおり残っています(ページ参照)。本章では「設計上の置き場所」として CoPP / ACL 章ではなく DHCP 側に置きます。

関連ページ