digraph G {
	graph [layout=dot fontname="Cantarell,sans-serif"];
	node [shape=Mrecord fontname="Cantarell,sans-serif"];
	edge [fontname="Cantarell,sans-serif"];

	subgraph cluster_kernel {
		label = <<font point-size="20">Linux (kernel mode)</font>>;
		color = "brown";
		nft_filter_prerouting [label="NFTables 規則 (filter, prerouting)"];
		nfqueue               [label="Netfilter user space queue"];
		nft_nat_prerouting    [label="NFTables 規則 (nat, prerouting)"];
	}

	subgraph cluster_fastalg_nfqueue {
		label = <<font point-size="20">fastalg-nfqueue (user mode)</font>>;
		color = "blue";
		netlink_socket [label="Netlink socket"];
		udp_inspect [label="UDP 封包分析程式"];
	}

	subgraph cluster_fastalg_protocol {
		label = <<font point-size="20">fastalg-protocol (user mode library)</font>>;
		color = "green3";
		dns_parser [label="DNS 分析函式"];
		hostname_matcher [label="Hostname 配對函式"];
	}

	pkt_in  [label="DNS request 封包輸入"];
	pkt_out [label="DNS request 封包輸出"];

	pkt_in                 -> nft_filter_prerouting  [label=<<font color="red"><b>1</b></font>>];
	nft_filter_prerouting  -> nfqueue                [label=<<font color="red"><b>2</b></font> Enqueue>];
	nfqueue                -> netlink_socket         [label=<<font color="red"><b>3</b></font> Dequeue>];
	netlink_socket         -> udp_inspect            [label=<<font color="blue"><b>4</b></font>>];
	udp_inspect            -> dns_parser             [label=<<font color="blue"><b>5</b></font> packet list>];
	dns_parser             -> udp_inspect;
	udp_inspect            -> hostname_matcher       [label=<<font color="blue"><b>6</b></font> hostname>];
	hostname_matcher       -> udp_inspect;
	udp_inspect            -> nft_filter_prerouting  [label=<<font color="blue"><b>7</b></font> Set packet mark + Verdict>];

	nft_filter_prerouting  -> nft_nat_prerouting     [label=<<font color="green4"><b>8</b></font>>];
	nft_nat_prerouting     -> pkt_out                [label=<<font color="green4"><b>9</b></font>>];
}