From 618ecdbd8bf7e541cf3cb0fe25e1b6585c528074 Mon Sep 17 00:00:00 2001 From: Daniel Noland Date: Thu, 5 Dec 2024 20:08:11 -0700 Subject: [PATCH] Dataplane internals Drawing up designs for the internals of the dataplane --- design-docs/src/mdbook/src/SUMMARY.md | 2 +- .../mdbook/src/dataplane/design-session.md | 232 ++++ .../mdbook/src/dataplane/offloading-plan.md | 1044 ++--------------- 3 files changed, 300 insertions(+), 978 deletions(-) diff --git a/design-docs/src/mdbook/src/SUMMARY.md b/design-docs/src/mdbook/src/SUMMARY.md index 3e1d2131..6f81e335 100644 --- a/design-docs/src/mdbook/src/SUMMARY.md +++ b/design-docs/src/mdbook/src/SUMMARY.md @@ -3,7 +3,6 @@ - [Dataplane project: executive summary](./dataplane/executive-summary.md) - [Reflections from last time](./dataplane/reflections-from-last-time.md) - [Hardware selection for dataplane project](./dataplane/hardware.md) -- [Offloading the dataplane](./dataplane/offloading-plan.md) - [DPDK abstraction map](./dataplane/map-of-dpdk.md) - [Build process](./build/index.md) - [Prerequisites](./build/prerequisites.md) @@ -12,6 +11,7 @@ - [Build dataplane](./build/just-cargo-build.md) - [Sterile builds](./build/sterile-build.md) - [Design session](./dataplane/design-session.md) +- [Offloading the dataplane](./dataplane/offloading-plan.md) - [Development Plan](./dataplane/development-plan.md) - [Configuration Persistence Investigation](./dataplane/tasks/configuration-persistence-investigation.md) - [Configuration database schema](./dataplane/tasks/config-db-schema.md) diff --git a/design-docs/src/mdbook/src/dataplane/design-session.md b/design-docs/src/mdbook/src/dataplane/design-session.md index 1cc5a352..bb72e0a0 100644 --- a/design-docs/src/mdbook/src/dataplane/design-session.md +++ b/design-docs/src/mdbook/src/dataplane/design-session.md @@ -394,4 +394,236 @@ The control plane is, for the moment, just [bgpd] and [bfdd]. +## Zoom in on dataplane + +
+ +
+ +```plantuml +@startuml +rectangle state_manager as "state manager" +cloud flow_lib as "flow lib" +collections workers +collections rx_queue +collections tx_queue +rectangle nic +rectangle flow_queue as "flow queue" + +workers <-- rx_queue : poll +workers --> tx_queue : push + +state_manager <--> workers : state\nupdate +state_manager -> flow_lib : calls +flow_lib <---> flow_queue : edit/query\nflows +flow_queue <--> nic : push/pull +tx_queue -- nic : tx +rx_queue -- nic : rx +@enduml +``` + +```plantuml +@startuml +!pragma teoz true +box "worker" #lightblue + participant rx_queue + participant worker + participant tx_queue +end box +participant state_manager +database flow_rules + +worker -> rx_queue ++ : rte_eth_rx_burst +return packets +worker -> state_manager ++ : updates +state_manager -> flow_rules : push updates +return verdicts +worker -> tx_queue : burst + +@enduml +``` + +
+ +> Biscuits + +
+ +
+ +
+ +
+ +#### Component diagram {#component-diagram-centralized-with-local} + +```plantuml +@startuml +rectangle state_manager as "state manager" +cloud flow_lib as "flow lib" +collections workers +collections rx_queue +collections tx_queue +rectangle nic +rectangle flow_queue as "flow queue" + +workers <-- rx_queue : poll +workers --> tx_queue : push + +state_manager <--> workers : state\nupdate +state_manager -> flow_lib : calls +flow_lib <---> flow_queue : edit/query\nflows +flow_queue <--> nic : push/pull +tx_queue -- nic : tx +rx_queue -- nic : rx +@enduml +``` +
+
+ +#### Sequence diagram {#sequence-diagram-centralized-with-local} + +```plantuml +@startuml +!pragma teoz true +box "worker" #lightblue + participant rx_queue + participant worker + database local_state as "local state" + participant tx_queue +end box +participant state_manager +database flow_rules + +worker -> rx_queue ++ : rte_eth_rx_burst +return packets +worker -> local_state ++ : table\nlookups +return verdicts +worker -> state_manager ++ : updates +state_manager -> flow_rules : push updates +return verdicts +worker -> tx_queue : burst + +@enduml +``` +
+
+ +> Biscuits + +
+ +
+ +
+ +```plantuml +@startuml +rectangle state_manager as "state manager" +cloud flow_lib as "flow lib" +collections workers +collections rx_queue +collections tx_queue +rectangle nic +collections flow_queue as "flow queue" + +workers <-- rx_queue : poll +workers --> tx_queue : push + +state_manager <--> workers : state\nupdate +workers <-> flow_lib : calls +flow_lib <--> flow_queue : edit/query\nflows +flow_queue <--> nic : push/pull +tx_queue --> nic : tx +rx_queue <-- nic : rx +@enduml +``` + + +```plantuml +@startuml +!pragma teoz true +box "worker" #lightblue + participant rx_queue + participant worker + database local_state as "local state" + participant tx_queue +end box +participant state_manager +database flow_rules + +worker -> rx_queue ++ : rte_eth_rx_burst +return packets +worker -> local_state ++ : table\nlookups +return verdicts +worker -> flow_rules : push updates +worker -> tx_queue : burst +worker -> state_manager : updates + +@enduml +``` + +
+ +> Double biscuit + +
+ +```plantuml +@startuml +!pragma use toez +skinparam linetype ortho +skinparam hyperlinkUnderline false +hide empty description +hide empty members +hide circle + +entity vpc +entity worker +entity peering +entity interface +entity chunk +entity subnet + +interface ||-o{ subnet +subnet ||-|{ chunk +peering ||--o{ interface +vpc ||-o{ interface +vpc }o--|| worker +chunk }o--|| worker +@enduml +``` + +```plantuml +@startuml +!pragma teoz true +box "worker" #lightblue + participant rx_queue + participant worker + database local_state as "local state" + participant tx_queue +end box +database flow_rules +participant state_manager + +worker -> rx_queue : rte_eth_rx_burst +return packets +worker -> local_state : table\nlookups +return verdict +worker -> flow_rules : push updates +worker -> tx_queue : rte_eth_tx_burst +worker -> local_state : chunk capacity ok? +alt chunk ok +local_state -> worker : chunk capacity ok? +else chunk low +local_state -> worker : get more chunk +worker -> state_manager : more chunk plz +return ok +worker -> local_state : refill chunk +end alt + +@enduml +``` + + {{#include ../links.md}} diff --git a/design-docs/src/mdbook/src/dataplane/offloading-plan.md b/design-docs/src/mdbook/src/dataplane/offloading-plan.md index 38652761..05bb51a7 100644 --- a/design-docs/src/mdbook/src/dataplane/offloading-plan.md +++ b/design-docs/src/mdbook/src/dataplane/offloading-plan.md @@ -1,12 +1,7 @@ # Offloading the dataplane -These are just unordered design ideas for the moment. - - -
- -## Some figure title +
```plantuml @startuml @@ -21,75 +16,77 @@ These are just unordered design ideas for the moment. !$question = $sty.question !$future = $sty.future -group Group 0: Shared Ingress +group Shared Ingress start $action:goto group 1; end group -group Group 1: Decap -switch (parse) -case () - $question:eth / vlan 2 / ipv4 / udp dst == 4789 / vxlan; - $action:set metadata f(vni); - $action:pop vlan + vxlan decap (raw decap); -case () - $question:eth / vlan N != 2; - $action:set metadata f(vlan); - $action:pop vlan; -endswitch -end group -group Group 2: NAT +group lookup interface id switch (parse) -case () -$question:eth/ip/(tcp|udp|icmp); -switch (and ct is) -case () - $question:new; - $future:count (per ingress meta?); - $future:rate limit? (per ingress meta?); - $action:raw encap (vxlan); - note left - We have already - stripped tags at - this point so we - need to re-encap - if we are going - to trap to the - kernel - end note +case (VLAN) + $question:eth / vlan N != 2; + $action:let iface = f(vlan);; + $action:pop vlan; +case (EVPN) + $question: eth / ipv{4,6} / udp dst == 4789 / vxlan; + $action:let iface = f(vni);; + $action:vxlan decap; +case (Cisco ACI) + $question:eth / vlan 2 / ipv{4,6} / udp dst == 4789 / vxlan; + $action:let iface = f(vni);; + $action:pop vlan + vxlan decap; +endswitch +end group + +group Process packet + + switch (ingress interface type?) + case (inner) + group routing + :route lookup; + :set nexthop ip; + :lookup egress interface; + :rewrite src/dst mac; + :dec ttl; + end group + group nat + switch (egress interface type?) + case (inner) + switch (connection state) + case (new) + :pull chunk; + :construct mapping; + :install offload; + case (established|related) + :offloaded; + detach + case (invalid) + :drop; + detach + endswitch + case (outer) + endswitch + end group + case (outer) + group nat + switch (connection state) + case (new|invalid) + :count; + :drop; + detach; + case (established|related) + :offloaded transform; + endswitch + end group + group routing + :route lookup; + :set nexthop ip; + :lookup egress interface; + :rewrite src/dst mac; + :dec ttl; + end group + endswitch - $action:set vni based on meta; - $action:trap to kernel; - detach -case () - $question:established | related; - $future:count (per ingress meta?); - $future:rate limit? (per ingress meta?); - $action:NAT; - note left $sty.attention - HOT PATH - This action is the main - workload of the whole - program. - end note -case () - $question:invalid; - $action:count; - $action:drop; - detach -endswitch -case () -$question:eth/(arp|ipv6/icmpv6 nd); -$future:rate limit!; -note right $sty.attention - This is the most important - thing to rate limit. -end note -$action:raw encap (vxlan); -$action:set vni based on meta; -$action:trap to kernel; -detach -endswitch end group @@ -116,913 +113,6 @@ end group @enduml ``` -```plantuml -@startuml -!pragma teoz true -!$sty = { -"port": { -"vtep": "#lightgreen", -"rep": "#lightpink", -"sriov": "#lightblue", -"physical": "#orange", -"veth": "#c962a9" -} -} - -cloud elsewhere - -rectangle host { -rectangle eswitch { -rectangle "physical port 1" as phys_port1 $sty.port.physical -rectangle "physical port 2" as phys_port2 $sty.port.physical -rectangle "user rep" as user_rep $sty.port.rep -rectangle "kernel rep" as kernel_rep $sty.port.rep -} -rectangle "user sriov" as user_sriov $sty.port.sriov - -rectangle netns { -rectangle "kernel sriov" as kernel_sriov $sty.port.sriov -rectangle bridge0 as bridge { -rectangle "vtep" as vtep $sty.port.vtep -rectangle "veth[0]" as veth_0_br $sty.port.veth -rectangle "veth[1]" as veth_1_br $sty.port.veth -rectangle "veth[2]" as veth_2_br $sty.port.veth -rectangle "veth[3]" as veth_3_br $sty.port.veth -} -} - -rectangle "veth[0]" as veth_0 $sty.port.veth -rectangle "veth[1]" as veth_1 $sty.port.veth -rectangle "veth[2]" as veth_2 $sty.port.veth -rectangle "veth[3]" as veth_3 $sty.port.veth - -} - -user_rep -- user_sriov -kernel_rep --- kernel_sriov -phys_port1 -[#hidden] phys_port2 -phys_port1 -[#hidden]- user_rep -phys_port2 -[#hidden]- kernel_rep - -elsewhere --- phys_port1 -elsewhere --- phys_port2 - -veth_0_br --- veth_0 -veth_1_br --- veth_1 -veth_2_br --- veth_2 -veth_3_br --- veth_3 -@enduml -``` +> How it's done
- - -```plantuml -@startuml -!pragma teoz true -!$sty = { - "port": { - "vtep": "#lightgreen", - "rep": "#lightpink", - "sriov": "#lightblue", - "physical": "#orange", - "veth": "#c962a9" - } -} - -cloud elsewhere - -rectangle host { - rectangle eswitch { - rectangle "physical port 1" as phys_port1 $sty.port.physical - rectangle "physical port 2" as phys_port2 $sty.port.physical - } - - rectangle bridge0 as bridge { - rectangle "vtep" as vtep $sty.port.vtep - rectangle "veth[0]" as veth_0_br $sty.port.veth - rectangle "veth[1]" as veth_1_br $sty.port.veth - rectangle "veth[2]" as veth_2_br $sty.port.veth - rectangle "veth[3]" as veth_3_br $sty.port.veth - rectangle "veth[4]" as veth_4_br $sty.port.veth - rectangle "veth[5]" as veth_5_br $sty.port.veth - rectangle "veth[6]" as veth_6_br $sty.port.veth - } - - note right of bridge - I only draw one here, - but we can have more vteps - and more bridges using - the **external**, and **vnifilter** - flags when you make bridges. - - Recent FRR supports this. - end note - - - rectangle "netns A" { - rectangle "veth[0]" as veth_0 $sty.port.veth - rectangle "veth[1]" as veth_1 $sty.port.veth - rectangle "some process" as some_process - } - rectangle "netns B" { - rectangle "veth[2]" as veth_2 $sty.port.veth - rectangle "veth[3]" as veth_3 $sty.port.veth - rectangle "some other process" as some_other_process - } - - rectangle "netns C" { - rectangle "veth[4]" as veth_4 $sty.port.veth - rectangle "veth[5]" as veth_5 $sty.port.veth - rectangle "veth[6]" as veth_6 $sty.port.veth - rectangle "yet another process" as yet_another_process - } - - rectangle "Kubernetes\n(present?)" as kubernetes - - note right of kubernetes - I need to make sure - I understand exactly what - the plan is regarding - kubernetes. - end note - - rectangle "FRR???\n(future)" as frr - note right of frr - I understand that we don't - need FRR now, but I think we - can all see that one coming. - - Let me know if I'm wrong **¯\_(ツ)_/¯** - end note -} - -phys_port1 -[#hidden] phys_port2 - -elsewhere -- phys_port1 -elsewhere --- phys_port2 - -veth_0_br -- veth_0 -veth_1_br -- veth_1 -veth_2_br -- veth_2 -veth_3_br -- veth_3 -veth_4_br -- veth_4 -veth_5_br -- veth_5 -veth_6_br -- veth_6 - -phys_port1 -[#hidden]- frr -phys_port2 -[#hidden]- frr - -veth_0 -[hidden]- some_process -veth_1 -[hidden]- some_process - -veth_2 -[hidden]- some_other_process -veth_3 -[hidden]- some_other_process - -veth_4 -[hidden]- yet_another_process -veth_5 -[hidden]- yet_another_process -veth_6 -[hidden]- yet_another_process - -@enduml -``` - -```puml -@startuml -!pragma teoz true - -title First pass - -!$sty = { - "question": "#gold", - "action": "#lightblue", - "future": "#lightgreen", - "attention": "#pink" -} -!$action = $sty.action -!$question = $sty.question - -group Group 0: Shared Ingress -start -$action:goto group 1; -end group - -group Group 1: Decap -switch (parse) -case () - $question:eth / vlan 2 / ipv4 / udp dst == 4789 / vxlan; - $action:set metadata f(vni); - $action:pop vlan + vxlan decap (raw decap); -case () - $question:eth / vlan N != 2; - $action:set metadata f(vlan); - $action:pop vlan; -endswitch -end group -group Group 2: NAT -switch (parse) -case () -$question:eth/ip/(tcp|udp|icmp); -switch (and ct is) -case () - $question:new; - $action:send to dpdk queue **N**; - detach -case () - $question:established | related; - $action:NAT; - note left $sty.attention - HOT PATH - This action is the main - workload of the whole - program. - end note -case () - $question:invalid; - $action:count; - $action:drop; - detach -endswitch -case () -$question:eth/(arp|ipv6/icmpv6 nd); -note right $sty.attention - This is the most important - thing to rate limit. -end note -$action:raw encap (vxlan); -$action:set vni based on meta; -$action:send to DPDK queue **N**; -detach -endswitch - -end group - -group Group 3: Re-tag/encap - -switch (metadata lookup) -case () - $question:vlan+vxlan?; - $action:raw encap (vlan + vxlan); - $action:set vni based on meta; -case () - $question:push vlan?; - $action:push vlan; - $action:set vid based on meta; -endswitch -end group - -group Group 4: Egress -stop -end group - -@enduml -``` - -```puml -@startuml -!pragma teoz true - -title First pass - -!$sty = { -"question": "#gold", -"action": "#lightblue", -"future": "#lightgreen", -"attention": "#pink" -} -!$action = $sty.action -!$question = $sty.question - -group Group 0: Shared Ingress -start -$action:goto group 1; -end group - -group Group 1: Decap -switch (parse) -case () -$question:eth / vlan 2 / ipv4 / udp dst == 4789 / vxlan; -$action:set metadata f(vni); -$action:pop vlan + vxlan decap (raw decap); -case () -$question:eth / vlan N != 2; -$action:set metadata f(vlan); -$action:pop vlan; -endswitch -end group -group Group 2: NAT -switch (parse) -case () -$question:eth/ip/(tcp|udp|icmp); -switch (and ct is) -case () -$question:new; -$action:send to dpdk queue **N**; -detach -case () -$question:established | related; -$action:NAT; -note left $sty.attention -HOT PATH -This action is the main -workload of the whole -program. -end note -case () -$question:invalid; -$action:count; -$action:drop; -detach -endswitch -case () -$question:eth/(arp|ipv6/icmpv6 nd); -note right $sty.attention -This is the most important -thing to rate limit. -end note -$action:raw encap (vxlan); -$action:set vni based on meta; -$action:send to DPDK queue **N**; -detach -endswitch - -end group - -group Group 3: Re-tag/encap - -switch (metadata lookup) -case () -$question:vlan+vxlan?; -$action:raw encap (vlan + vxlan); -$action:set vni based on meta; -case () -$question:push vlan?; -$action:push vlan; -$action:set vid based on meta; -endswitch -end group - -group Group 4: Egress -stop -end group - -@enduml -``` - -```puml -@startuml -!pragma teoz true -!$sty = { - "port": { - "vtep": "#lightgreen", - "rep": "#lightpink", - "sriov": "#lightblue", - "physical": "#orange", - "veth": "#c962a9" - } -} - -cloud elsewhere - -rectangle host { - rectangle dpdk_netns { - rectangle eswitch { - rectangle "physical port 1" as phys_port1 $sty.port.physical - rectangle "physical port 2" as phys_port2 $sty.port.physical - } - rectangle veth as veth.dpdk - } - - rectangle veth as veth.kernel - - rectangle bridge as bridge { - rectangle "vtep" as vtep $sty.port.vtep - rectangle "veth[0]" as veth_0_br $sty.port.veth - rectangle "veth[1]" as veth_1_br $sty.port.veth - rectangle "veth[2]" as veth_2_br $sty.port.veth - rectangle "veth[3]" as veth_3_br $sty.port.veth - rectangle "veth[4]" as veth_4_br $sty.port.veth - rectangle "veth[5]" as veth_5_br $sty.port.veth - rectangle "veth[6]" as veth_6_br $sty.port.veth - } - - note right of bridge - I only draw one here, - but we can have more vteps - and more bridges using - the **external**, and **vnifilter** - flags when you make bridges. - - Recent FRR supports this. - end note - - rectangle "netns A" { - rectangle "veth[0]" as veth_0 $sty.port.veth - rectangle "veth[1]" as veth_1 $sty.port.veth - rectangle "some process" as some_process - } - rectangle "netns B" { - rectangle "veth[2]" as veth_2 $sty.port.veth - rectangle "veth[3]" as veth_3 $sty.port.veth - rectangle "some other process" as some_other_process - } - rectangle "netns C" { - rectangle "veth[4]" as veth_4 $sty.port.veth - rectangle "veth[5]" as veth_5 $sty.port.veth - rectangle "veth[6]" as veth_6 $sty.port.veth - rectangle "yet another process" as yet_another_process - } - -} - -phys_port1 -[#hidden] phys_port2 - -elsewhere -- phys_port1 -elsewhere --- phys_port2 - -veth_0_br -- veth_0 -veth_1_br -- veth_1 -veth_2_br -- veth_2 -veth_3_br -- veth_3 -veth_4_br -- veth_4 -veth_5_br -- veth_5 -veth_6_br -- veth_6 - -veth_0 -[hidden]- some_process -veth_1 -[hidden]- some_process - -veth_2 -[hidden]- some_other_process -veth_3 -[hidden]- some_other_process - -veth_4 -[hidden]- yet_another_process -veth_5 -[hidden]- yet_another_process -veth_6 -[hidden]- yet_another_process - -veth.dpdk -- veth.kernel -veth.kernel -[hidden]- bridge - -@enduml -``` - -```plantuml -@startuml -!pragma teoz true -!$sty = { - "question": "#gold", - "action": "#lightblue", - "future": "#lightgreen", - "attention": "#pink" -} -!$action = $sty.action -!$question = $sty.question -!$future = $sty.future - -group Group 0: Shared Ingress -start -$action:goto group 1; -end group - -group Group 1: Decap -switch (parse) -case () - $question:eth / vlan 2 / ipv4 / udp dst == 4789 / vxlan; - $action:set metadata f(vni); - $action:pop vlan + vxlan decap (raw decap); -case () - $question:eth / vlan N != 2; - $action:set metadata f(vlan); - $action:pop vlan; -endswitch -end group -group Group 2: NAT -switch (parse) -case () -$question:eth/ip/(tcp|udp|icmp); -switch (and ct is) -case () - $question:new; - $future:count (per ingress meta?); - $future:rate limit? (per ingress meta?); - $action:raw encap (vxlan); - note left - We have already - stripped tags at - this point so we - need to re-encap - if we are going - to trap to the - kernel - end note - - $action:set vni based on meta; - $action:trap to kernel; - detach -case () - $question:established | related; - $future:count (per ingress meta?); - $future:rate limit? (per ingress meta?); - $action:NAT; - note left $sty.attention - HOT PATH - This action is the main - workload of the whole - program. - end note -case () - $question:invalid; - $action:count; - $action:drop; - detach -endswitch -case () -$question:eth/(arp|ipv6/icmpv6 nd); -$future:rate limit!; -note right $sty.attention - This is the most important - thing to rate limit. -end note -$action:raw encap (vxlan); -$action:set vni based on meta; -$action:trap to kernel; -detach -endswitch - -end group - -group Group 3: Re-tag/encap - -switch (metadata lookup) -case () - $question:vlan+vxlan?; - $action:raw encap (vlan + vxlan); - $action:set vni based on meta; - $future:count; -case () - $question:push vlan?; - $action:push vlan; - $action:set vid based on meta; - $future:count; -endswitch -end group - -group Group 4: Egress -stop -end group - -@enduml -``` - -```plantuml -@startuml -!pragma teoz true -!$sty = { - "port": { - "vtep": "#lightgreen", - "rep": "#lightpink", - "sriov": "#lightblue", - "physical": "#orange", - "veth": "#c962a9" - } -} - -cloud elsewhere - -rectangle host { - rectangle eswitch { - rectangle "physical port 1" as phys_port1 $sty.port.physical - rectangle "physical port 2" as phys_port2 $sty.port.physical - rectangle "user rep" as user_rep $sty.port.rep - rectangle "kernel rep" as kernel_rep $sty.port.rep - } - rectangle "user sriov" as user_sriov $sty.port.sriov - - rectangle netns { - rectangle "kernel sriov" as kernel_sriov $sty.port.sriov - rectangle bridge0 as bridge { - rectangle "vtep" as vtep $sty.port.vtep - rectangle "veth[0]" as veth_0_br $sty.port.veth - rectangle "veth[1]" as veth_1_br $sty.port.veth - rectangle "veth[2]" as veth_2_br $sty.port.veth - rectangle "veth[3]" as veth_3_br $sty.port.veth - } - } - - rectangle "veth[0]" as veth_0 $sty.port.veth - rectangle "veth[1]" as veth_1 $sty.port.veth - rectangle "veth[2]" as veth_2 $sty.port.veth - rectangle "veth[3]" as veth_3 $sty.port.veth - -} - -user_rep -- user_sriov -kernel_rep --- kernel_sriov -phys_port1 -[#hidden] phys_port2 -phys_port1 -[#hidden]- user_rep -phys_port2 -[#hidden]- kernel_rep - -elsewhere --- phys_port1 -elsewhere --- phys_port2 - -veth_0_br --- veth_0 -veth_1_br --- veth_1 -veth_2_br --- veth_2 -veth_3_br --- veth_3 -@enduml -``` - - - -```plantuml -@startuml -!pragma teoz true -!$sty = { - "port": { - "vtep": "#lightgreen", - "rep": "#lightpink", - "sriov": "#lightblue", - "physical": "#orange", - "veth": "#c962a9" - } -} - -cloud elsewhere - -rectangle host { - rectangle eswitch { - rectangle "physical port 1" as phys_port1 $sty.port.physical - rectangle "physical port 2" as phys_port2 $sty.port.physical - } - - rectangle bridge0 as bridge { - rectangle "vtep" as vtep $sty.port.vtep - rectangle "veth[0]" as veth_0_br $sty.port.veth - rectangle "veth[1]" as veth_1_br $sty.port.veth - rectangle "veth[2]" as veth_2_br $sty.port.veth - rectangle "veth[3]" as veth_3_br $sty.port.veth - rectangle "veth[4]" as veth_4_br $sty.port.veth - rectangle "veth[5]" as veth_5_br $sty.port.veth - rectangle "veth[6]" as veth_6_br $sty.port.veth - } - - note right of bridge - I only draw one here, - but we can have more vteps - and more bridges using - the **external**, and **vnifilter** - flags when you make bridges. - - Recent FRR supports this. - end note - - - rectangle "netns A" { - rectangle "veth[0]" as veth_0 $sty.port.veth - rectangle "veth[1]" as veth_1 $sty.port.veth - rectangle "some process" as some_process - } - rectangle "netns B" { - rectangle "veth[2]" as veth_2 $sty.port.veth - rectangle "veth[3]" as veth_3 $sty.port.veth - rectangle "some other process" as some_other_process - } - - rectangle "netns C" { - rectangle "veth[4]" as veth_4 $sty.port.veth - rectangle "veth[5]" as veth_5 $sty.port.veth - rectangle "veth[6]" as veth_6 $sty.port.veth - rectangle "yet another process" as yet_another_process - } - - rectangle "Kubernetes\n(present?)" as kubernetes - - note right of kubernetes - I need to make sure - I understand exactly what - the plan is regarding - kubernetes. - end note - - rectangle "FRR???\n(future)" as frr - note right of frr - I understand that we don't - need FRR now, but I think we - can all see that one coming. - - Let me know if I'm wrong **¯\_(ツ)_/¯** - end note -} - -phys_port1 -[#hidden] phys_port2 - -elsewhere -- phys_port1 -elsewhere --- phys_port2 - -veth_0_br -- veth_0 -veth_1_br -- veth_1 -veth_2_br -- veth_2 -veth_3_br -- veth_3 -veth_4_br -- veth_4 -veth_5_br -- veth_5 -veth_6_br -- veth_6 - -phys_port1 -[#hidden]- frr -phys_port2 -[#hidden]- frr - -veth_0 -[hidden]- some_process -veth_1 -[hidden]- some_process - -veth_2 -[hidden]- some_other_process -veth_3 -[hidden]- some_other_process - -veth_4 -[hidden]- yet_another_process -veth_5 -[hidden]- yet_another_process -veth_6 -[hidden]- yet_another_process - -@enduml -``` - -```plantuml -@startuml -!pragma teoz true - -title First pass - -!$sty = { - "question": "#gold", - "action": "#lightblue", - "future": "#lightgreen", - "attention": "#pink" -} -!$action = $sty.action -!$question = $sty.question - -group Group 0: Shared Ingress -start -$action:goto group 1; -end group - -group Group 1: Decap -switch (parse) -case () - $question:eth / vlan 2 / ipv4 / udp dst == 4789 / vxlan; - $action:set metadata f(vni); - $action:pop vlan + vxlan decap (raw decap); -case () - $question:eth / vlan N != 2; - $action:set metadata f(vlan); - $action:pop vlan; -endswitch -end group -group Group 2: NAT -switch (parse) -case () -$question:eth/ip/(tcp|udp|icmp); -switch (and ct is) -case () - $question:new; - $action:send to dpdk queue **N**; - detach -case () - $question:established | related; - $action:NAT; - note left $sty.attention - HOT PATH - This action is the main - workload of the whole - program. - end note -case () - $question:invalid; - $action:count; - $action:drop; - detach -endswitch -case () -$question:eth/(arp|ipv6/icmpv6 nd); -note right $sty.attention - This is the most important - thing to rate limit. -end note -$action:raw encap (vxlan); -$action:set vni based on meta; -$action:send to DPDK queue **N**; -detach -endswitch - -end group - -group Group 3: Re-tag/encap - -switch (metadata lookup) -case () - $question:vlan+vxlan?; - $action:raw encap (vlan + vxlan); - $action:set vni based on meta; -case () - $question:push vlan?; - $action:push vlan; - $action:set vid based on meta; -endswitch -end group - -group Group 4: Egress -stop -end group - -@enduml -``` - - -```plantuml -@startuml -!pragma teoz true -!$sty = { - "port": { - "vtep": "#lightgreen", - "rep": "#lightpink", - "sriov": "#lightblue", - "physical": "#orange", - "veth": "#c962a9" - } -} - -cloud elsewhere - -rectangle host { - rectangle dpdk_netns { - rectangle eswitch { - rectangle "physical port 1" as phys_port1 $sty.port.physical - rectangle "physical port 2" as phys_port2 $sty.port.physical - } - rectangle veth as veth.dpdk - } - - rectangle veth as veth.kernel - - rectangle bridge as bridge { - rectangle "vtep" as vtep $sty.port.vtep - rectangle "veth[0]" as veth_0_br $sty.port.veth - rectangle "veth[1]" as veth_1_br $sty.port.veth - rectangle "veth[2]" as veth_2_br $sty.port.veth - rectangle "veth[3]" as veth_3_br $sty.port.veth - rectangle "veth[4]" as veth_4_br $sty.port.veth - rectangle "veth[5]" as veth_5_br $sty.port.veth - rectangle "veth[6]" as veth_6_br $sty.port.veth - } - - note right of bridge - I only draw one here, - but we can have more vteps - and more bridges using - the **external**, and **vnifilter** - flags when you make bridges. - - Recent FRR supports this. - end note - - rectangle "netns A" { - rectangle "veth[0]" as veth_0 $sty.port.veth - rectangle "veth[1]" as veth_1 $sty.port.veth - rectangle "some process" as some_process - } - rectangle "netns B" { - rectangle "veth[2]" as veth_2 $sty.port.veth - rectangle "veth[3]" as veth_3 $sty.port.veth - rectangle "some other process" as some_other_process - } - rectangle "netns C" { - rectangle "veth[4]" as veth_4 $sty.port.veth - rectangle "veth[5]" as veth_5 $sty.port.veth - rectangle "veth[6]" as veth_6 $sty.port.veth - rectangle "yet another process" as yet_another_process - } - -} - -phys_port1 -[#hidden] phys_port2 - -elsewhere -- phys_port1 -elsewhere --- phys_port2 - -veth_0_br -- veth_0 -veth_1_br -- veth_1 -veth_2_br -- veth_2 -veth_3_br -- veth_3 -veth_4_br -- veth_4 -veth_5_br -- veth_5 -veth_6_br -- veth_6 - -veth_0 -[hidden]- some_process -veth_1 -[hidden]- some_process - -veth_2 -[hidden]- some_other_process -veth_3 -[hidden]- some_other_process - -veth_4 -[hidden]- yet_another_process -veth_5 -[hidden]- yet_another_process -veth_6 -[hidden]- yet_another_process - -veth.dpdk -- veth.kernel -veth.kernel -[hidden]- bridge - -@enduml -```