<h1>Configuration</h1>
<p>
<code>ovn-northd</code> requires a connection to the Northbound
- and Southbound databases. The default is <code>db.sock</code>
+ and Southbound databases. The defaults are <code>ovnnb_db.sock</code>
+ and <code>ovnsb_db.sock</code> respectively
in the local Open vSwitch's "run" directory. This may be
overridden with the following commands:
</p>
</li>
<li>
<p>
- <code>--ovsnb-db=<var>database</var></code>
+ <code>--ovnsb-db=<var>database</var></code>
</p>
<p>
The database containing the OVN Southbound Database.
<h2>Logical Switch Datapaths</h2>
- <h3>Ingress Table 0: Admission Control and Ingress Port Security</h3>
+ <h3>Ingress Table 0: Admission Control and Ingress Port Security - L2</h3>
<p>
Ingress table 0 contains these logical flows:
be dropped.
</p>
- <h3>Ingress Table 1: <code>from-lport</code> Pre-ACLs</h3>
+ <h3>Ingress Table 1: Ingress Port Security - IP</h3>
<p>
- Ingress table 1 prepares flows for possible stateful ACL processing
- in table 2. It contains a priority-0 flow that simply moves
- traffic to table 2. If stateful ACLs are used in the logical
- datapath, a priority-100 flow is added that sends IP packets to
- the connection tracker before advancing to table 2.
+ Ingress table 1 contains these logical flows:
</p>
- <h3>Ingress table 2: <code>from-lport</code> ACLs</h3>
+ <ul>
+ <li>
+ <p>
+ For each element in the port security set having one or more IPv4 or
+ IPv6 addresses (or both),
+ </p>
+
+ <ul>
+ <li>
+ Priority 90 flow to allow IPv4 traffic if it has IPv4 addresses
+ which match the <code>inport</code>, valid <code>eth.src</code>
+ and valid <code>ip4.src</code> address(es).
+ </li>
+
+ <li>
+ Priority 90 flow to allow IPv4 DHCP discovery traffic if it has a
+ valid <code>eth.src</code>. This is necessary since DHCP discovery
+ messages are sent from the unspecified IPv4 address (0.0.0.0) since
+ the IPv4 address has not yet been assigned.
+ </li>
+
+ <li>
+ Priority 90 flow to allow IPv6 traffic if it has IPv6 addresses
+ which match the <code>inport</code>, valid <code>eth.src</code> and
+ valid <code>ip6.src</code> address(es).
+ </li>
+
+ <li>
+ Priority 90 flow to allow IPv6 DAD (Duplicate Address Detection)
+ traffic if it has a valid <code>eth.src</code>. This is is
+ necessary since DAD include requires joining an multicast group and
+ sending neighbor solicitations for the newly assigned address. Since
+ no address is yet assigned, these are sent from the unspecified
+ IPv6 address (::).
+ </li>
+
+ <li>
+ Priority 80 flow to drop IP (both IPv4 and IPv6) traffic which
+ match the <code>inport</code> and valid <code>eth.src</code>.
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ One priority-0 fallback flow that matches all packets and advances to
+ the next table.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 2: Ingress Port Security - Neighbor discovery</h3>
+
+ <p>
+ Ingress table 2 contains these logical flows:
+ </p>
+
+ <ul>
+ <li>
+ <p>
+ For each element in the port security set,
+ </p>
+
+ <ul>
+ <li>
+ Priority 90 flow to allow ARP traffic which match the
+ <code>inport</code> and valid <code>eth.src</code> and
+ <code>arp.sha</code>. If the element has one or more
+ IPv4 addresses, then it also matches the valid
+ <code>arp.spa</code>.
+ </li>
+
+ <li>
+ Priority 90 flow to allow IPv6 Neighbor Solicitation and
+ Advertisement traffic which match the <code>inport</code>,
+ valid <code>eth.src</code> and
+ <code>nd.sll</code>/<code>nd.tll</code>.
+ If the element has one or more IPv6 addresses, then it also
+ matches the valid <code>nd.target</code> address(es) for Neighbor
+ Advertisement traffic.
+ </li>
+
+ <li>
+ Priority 80 flow to drop ARP and IPv6 Neighbor Solicitation and
+ Advertisement traffic which match the <code>inport</code> and
+ valid <code>eth.src</code>.
+ </li>
+ </ul>
+ </li>
+
+ <li>
+ One priority-0 fallback flow that matches all packets and advances to
+ the next table.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 3: <code>from-lport</code> Pre-ACLs</h3>
+
+ <p>
+ This table prepares flows for possible stateful ACL processing in
+ ingress table <code>ACLs</code>. It contains a priority-0 flow that
+ simply moves traffic to the next table. If stateful ACLs are used in the
+ logical datapath, a priority-100 flow is added that sets a hint
+ (with <code>reg0[0] = 1; next;</code>) for table
+ <code>Pre-stateful</code> to send IP packets to the connection tracker
+ before eventually advancing to ingress table <code>ACLs</code>.
+ </p>
+
+ <h3>Ingress Table 4: Pre-LB</h3>
+
+ <p>
+ This table prepares flows for possible stateful load balancing processing
+ in ingress table <code>LB</code> and <code>Stateful</code>. It contains
+ a priority-0 flow that simply moves traffic to the next table. If load
+ balancing rules with virtual IP addresses (and ports) are configured in
+ <code>OVN_Northbound</code> database for a logical datapath, a
+ priority-100 flow is added for each configured virtual IP address
+ <var>VIP</var> with a match <code>ip && ip4.dst == <var>VIP</var>
+ </code> that sets an action <code>reg0[0] = 1; next;</code> to act as a
+ hint for table <code>Pre-stateful</code> to send IP packets to the
+ connection tracker for packet de-fragmentation before eventually
+ advancing to ingress table <code>LB</code>.
+ </p>
+
+ <h3>Ingress Table 5: Pre-stateful</h3>
+
+ <p>
+ This table prepares flows for all possible stateful processing
+ in next tables. It contains a priority-0 flow that simply moves
+ traffic to the next table. A priority-100 flow sends the packets to
+ connection tracker based on a hint provided by the previous tables
+ (with a match for <code>reg0[0] == 1</code>) by using the
+ <code>ct_next;</code> action.
+ </p>
+
+ <h3>Ingress table 6: <code>from-lport</code> ACLs</h3>
<p>
Logical flows in this table closely reproduce those in the
<code>ACL</code> table in the <code>OVN_Northbound</code> database
- for the <code>from-lport</code> direction. <code>allow</code>
- ACLs translate into logical flows with the <code>next;</code>
- action, <code>allow-related</code> ACLs translate into logical
- flows with the <code>ct_next;</code> action, other ACLs translate
- to <code>drop;</code>. The <code>priority</code> values from the
- <code>ACL</code> table are used directly.
+ for the <code>from-lport</code> direction. The <code>priority</code>
+ values from the <code>ACL</code> table have a limited range and have
+ 1000 added to them to leave room for OVN default flows at both
+ higher and lower priorities.
</p>
+ <ul>
+ <li>
+ <code>allow</code> ACLs translate into logical flows with
+ the <code>next;</code> action. If there are any stateful ACLs
+ on this datapath, then <code>allow</code> ACLs translate to
+ <code>ct_commit; next;</code> (which acts as a hint for the next tables
+ to commit the connection to conntrack),
+ </li>
+ <li>
+ <code>allow-related</code> ACLs translate into logical
+ flows with the <code>ct_commit(ct_label=0/1); next;</code> actions
+ for new connections and <code>reg0[1] = 1; next;</code> for existing
+ connections.
+ </li>
+ <li>
+ Other ACLs translate to <code>drop;</code> for new or untracked
+ connections and <code>ct_commit(ct_label=1/1);</code> for known
+ connections. Setting <code>ct_label</code> marks a connection
+ as one that was previously allowed, but should no longer be
+ allowed due to a policy change.
+ </li>
+ </ul>
<p>
- Ingress table 2 also contains a priority 0 flow with action
+ This table also contains a priority 0 flow with action
<code>next;</code>, so that ACLs allow packets by default. If the
logical datapath has a statetful ACL, the following flows will
also be added:
<ul>
<li>
- A priority-1 flow to commit IP traffic to the connection
- tracker. This is needed for the default allow policy because,
- while the initiater's direction may not have any stateful rules,
- the server's may and then its return traffic would not be known
- and marked as invalid.
+ A priority-1 flow that sets the hint to commit IP traffic to the
+ connection tracker (with action <code>reg0[1] = 1; next;</code>). This
+ is needed for the default allow policy because, while the initiator's
+ direction may not have any stateful rules, the server's may and then
+ its return traffic would not be known and marked as invalid.
</li>
<li>
- A priority-65535 flow that allows any traffic that has been
- committed to the connection tracker (i.e., established flows).
+ A priority-65535 flow that allows any traffic in the reply
+ direction for a connection that has been committed to the
+ connection tracker (i.e., established flows), as long as
+ the committed flow does not have <code>ct_label[0]</code> set.
+ We only handle traffic in the reply direction here because
+ we want all packets going in the request direction to still
+ go through the flows that implement the currently defined
+ policy based on ACLs. If a connection is no longer allowed by
+ policy, <code>ct_label[0]</code> will get set and packets in the
+ reply direction will no longer be allowed, either.
</li>
<li>
A priority-65535 flow that allows any traffic that is considered
related to a committed flow in the connection tracker (e.g., an
- ICMP Port Unreachable from a non-listening UDP port).
+ ICMP Port Unreachable from a non-listening UDP port), as long
+ as the committed flow does not have <code>ct_label[0]</code> set.
</li>
<li>
A priority-65535 flow that drops all traffic marked by the
connection tracker as invalid.
</li>
+
+ <li>
+ A priority-65535 flow that drops all trafic in the reply direction
+ with <code>ct_label[0]</code> set meaning that the connection
+ should no longer be allowed due to a policy change. Packets
+ in the request direction are skipped here to let a newly created
+ ACL re-allow this connection.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 7: LB</h3>
+
+ <p>
+ It contains a priority-0 flow that simply moves traffic to the next
+ table. For established connections a priority 100 flow matches on
+ <code>ct.est && !ct.rel && !ct.new &&
+ !ct.inv</code> and sets an action <code>reg0[2] = 1; next;</code> to act
+ as a hint for table <code>Stateful</code> to send packets through
+ connection tracker to NAT the packets. (The packet will automatically
+ get DNATed to the same IP address as the first packet in that
+ connection.)
+ </p>
+
+ <h3>Ingress Table 8: Stateful</h3>
+
+ <ul>
+ <li>
+ For all the configured load balancing rules in
+ <code>OVN_Northbound</code> database that includes a L4 port
+ <var>PORT</var> of protocol <var>P</var> and IPv4 address
+ <var>VIP</var>, a priority-120 flow that matches on
+ <code>ct.new && ip && ip4.dst == <var>VIP
+ </var>&& <var>P</var> && <var>P</var>.dst == <var>PORT
+ </var></code> with an action of <code>ct_lb(<var>args</var>)</code>,
+ where <var>args</var> contains comma separated IPv4 addresses (and
+ optional port numbers) to load balance to.
+ </li>
+ <li>
+ For all the configured load balancing rules in
+ <code>OVN_Northbound</code> database that includes just an IP address
+ <var>VIP</var> to match on, a priority-110 flow that matches on
+ <code>ct.new && ip && ip4.dst == <var>VIP</var></code>
+ with an action of <code>ct_lb(<var>args</var>)</code>, where
+ <var>args</var> contains comma separated IPv4 addresses.
+ </li>
+ <li>
+ A priority-100 flow commits packets to connection tracker using
+ <code>ct_commit; next;</code> action based on a hint provided by
+ the previous tables (with a match for <code>reg0[1] == 1</code>).
+ </li>
+ <li>
+ A priority-100 flow sends the packets to connection tracker using
+ <code>ct_lb;</code> as the action based on a hint provided by the
+ previous tables (with a match for <code>reg0[2] == 1</code>).
+ </li>
+ <li>
+ A priority-0 flow that simply moves traffic to the next table.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 9: ARP responder</h3>
+
+ <p>
+ This table implements ARP responder for known IPs. It contains these
+ logical flows:
+ </p>
+
+ <ul>
+ <li>
+ Priority-100 flows to skip ARP responder if inport is of type
+ <code>localnet</code>, and advances directly to the next table.
+ </li>
+
+ <li>
+ <p>
+ Priority-50 flows that matches ARP requests to each known IP address
+ <var>A</var> of logical port <var>P</var>, and respond with ARP
+ replies directly with corresponding Ethernet address <var>E</var>:
+ </p>
+
+ <pre>
+eth.dst = eth.src;
+eth.src = <var>E</var>;
+arp.op = 2; /* ARP reply. */
+arp.tha = arp.sha;
+arp.sha = <var>E</var>;
+arp.tpa = arp.spa;
+arp.spa = <var>A</var>;
+outport = <var>P</var>;
+inport = ""; /* Allow sending out inport. */
+output;
+ </pre>
+
+ <p>
+ These flows are omitted for logical ports (other than router ports)
+ that are down.
+ </p>
+ </li>
+
+ <li>
+ One priority-0 fallback flow that matches all packets and advances to
+ the next table.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 10: DHCP option processing</h3>
+
+ <p>
+ This table adds the DHCPv4 options to a DHCPv4 packet from the
+ logical ports configured with IPv4 address(es) and DHCPv4 options.
+ </p>
+
+ <ul>
+ <li>
+ <p>
+ A priority-100 logical flow is added for these logical ports
+ which matches the IPv4 packet with <code>udp.src</code> = 68 and
+ <code>udp.dst</code> = 67 and applies the action
+ <code>put_dhcp_opts</code> and advances the packet to the next table.
+ </p>
+
+ <pre>
+reg0[3] = put_dhcp_opts(offer_ip = <var>O</var>, <i>options</i>...);
+next;
+ </pre>
+
+ <p>
+ For DHCPDISCOVER and DHCPREQUEST, this transforms the packet into a
+ DHCP reply, adds the DHCP offer IP <var>O</var> and options to the
+ packet, and stores 1 into reg0[3]. For other kinds of packets, it
+ just stores 0 into reg0[3]. Either way, it continues to the next
+ table.
+ </p>
+
+ </li>
+
+ <li>
+ A priority-0 flow that matches all packets to advances to table 11.
+ </li>
</ul>
- <h3>Ingress Table 3: Destination Lookup</h3>
+ <h3>Ingress Table 11: DHCP responses</h3>
+
+ <p>
+ This table implements DHCP responder for the DHCP replies generated by
+ the previous table.
+ </p>
+
+ <ul>
+ <li>
+ <p>
+ A priority 100 logical flow is added for the logical ports configured
+ with DHCPv4 options which matches IPv4 packets with <code>udp.src == 68
+ && udp.dst == 67 && reg0[3] == 1</code> and
+ responds back to the <code>inport</code> after applying these
+ actions. If <code>reg0[3]</code> is set to 1, it means that the
+ action <code>put_dhcp_opts</code> was successful.
+ </p>
+
+ <pre>
+eth.dst = eth.src;
+eth.src = <var>E</var>;
+ip4.dst = <var>O</var>;
+ip4.src = <var>S</var>;
+udp.src = 67;
+udp.dst = 68;
+outport = <var>P</var>;
+inport = ""; /* Allow sending out inport. */
+output;
+ </pre>
+
+ <p>
+ where <var>E</var> is the server MAC address and <var>S</var> is the
+ server IPv4 address defined in the DHCPv4 options and <var>O</var> is
+ the IPv4 address defined in the logical port's addresses column.
+ </p>
+
+ <p>
+ (This terminates ingress packet processing; the packet does not go
+ to the next ingress table.)
+ </p>
+ </li>
+
+ <li>
+ A priority-0 flow that matches all packets to advances to table 12.
+ </li>
+ </ul>
+
+ <h3>Ingress Table 12: Destination Lookup</h3>
<p>
This table implements switching behavior. It contains these logical
</li>
</ul>
- <h3>Egress Table 0: <code>to-lport</code> Pre-ACLs</h3>
+ <h3>Egress Table 0: Pre-LB</h3>
+
+ <p>
+ This table is similar to ingress table <code>Pre-LB</code>. It
+ contains a priority-0 flow that simply moves traffic to the next table.
+ If any load balancing rules exist for the datapath, a priority-100 flow
+ is added with a match of <code>ip</code> and action of <code>reg0[0] = 1;
+ next;</code> to act as a hint for table <code>Pre-stateful</code> to
+ send IP packets to the connection tracker for packet de-fragmentation.
+ </p>
+
+ <h3>Egress Table 1: <code>to-lport</code> Pre-ACLs</h3>
+
+ <p>
+ This is similar to ingress table <code>Pre-ACLs</code> except for
+ <code>to-lport</code> traffic.
+ </p>
+
+ <h3>Egress Table 2: Pre-stateful</h3>
+
+ <p>
+ This is similar to ingress table <code>Pre-stateful</code>.
+ </p>
+
+ <h3>Egress Table 3: LB</h3>
+ <p>
+ This is similar to ingress table <code>LB</code>.
+ </p>
+
+ <h3>Egress Table 4: <code>to-lport</code> ACLs</h3>
<p>
- This is similar to ingress table 1 except for <code>to-lport</code>
- traffic.
+ This is similar to ingress table <code>ACLs</code> except for
+ <code>to-lport</code> ACLs.
</p>
- <h3>Egress Table 1: <code>to-lport</code> ACLs</h3>
+ <h3>Egress Table 5: Stateful</h3>
<p>
- This is similar to ingress table 2 except for <code>to-lport</code> ACLs.
+ This is similar to ingress table <code>Stateful</code> except that
+ there are no rules added for load balancing new connections.
</p>
- <h3>Egress Table 2: Egress Port Security</h3>
+ <p>
+ Also a priority 34000 logical flow is added for each logical port which
+ has DHCPv4 options defined to allow the DHCPv4 reply packet from the
+ <code>Ingress Table 11: DHCP responses</code>.
+ </p>
+
+ <h3>Egress Table 6: Egress Port Security - IP</h3>
<p>
- This is similar to the ingress port security logic in ingress table 0,
+ This is similar to the port security logic in table
+ <code>Ingress Port Security - IP</code> except that <code>outport</code>,
+ <code>eth.dst</code>, <code>ip4.dst</code> and <code>ip6.dst</code>
+ are checked instead of <code>inport</code>, <code>eth.src</code>,
+ <code>ip4.src</code> and <code>ip6.src</code>
+ </p>
+
+ <h3>Egress Table 7: Egress Port Security - L2</h3>
+
+ <p>
+ This is similar to the ingress port security logic in ingress table
+ <code>Admission Control and Ingress Port Security - L2</code>,
but with important differences. Most obviously, <code>outport</code> and
<code>eth.dst</code> are checked instead of <code>inport</code> and
<code>eth.src</code>. Second, packets directed to broadcast or multicast
<h2>Logical Router Datapaths</h2>
+ <p>
+ Logical router datapaths will only exist for <ref table="Logical_Router"
+ db="OVN_Northbound"/> rows in the <ref db="OVN_Northbound"/> database
+ that do not have <ref column="enabled" table="Logical_Router"
+ db="OVN_Northbound"/> set to <code>false</code>
+ </p>
+
<h3>Ingress Table 0: L2 Admission Control</h3>
<p>
<li>
<p>
ICMP echo reply. These flows reply to ICMP echo requests received
- for the router's IP address. Let <var>A</var> be an IP address or
- broadcast address owned by a router port. Then, for each
- <var>A</var>, a priority-90 flow matches on <code>ip4.dst ==
- <var>A</var></code> and <code>icmp4.type == 8 && icmp4.code
- == 0</code> (ICMP echo request). These flows use the following
- actions where, if <var>A</var> is unicast, then <var>S</var> is
- <var>A</var>, and if <var>A</var> is broadcast, <var>S</var> is the
- router's IP address in <var>A</var>'s network:
+ for the router's IP address. Let <var>A</var> be an IP address
+ owned by a router port. Then, for each <var>A</var>, a priority-90
+ flow matches on <code>ip4.dst == <var>A</var></code> and <code>
+ icmp4.type == 8 && icmp4.code == 0</code> (ICMP echo
+ request). The port of the router that receives the echo request
+ does not matter. Also, the ip.ttl of the echo request packet is not
+ checked, so it complies with RFC 1812, section 4.2.2.9. These flows
+ use the following actions:
</p>
<pre>
-ip4.dst = ip4.src;
-ip4.src = <var>S</var>;
+ip4.dst <-> ip4.src;
ip.ttl = 255;
icmp4.type = 0;
+inport = ""; /* Allow sending out inport. */
next;
</pre>
+ </li>
+ <li>
<p>
- Similar flows match on <code>ip4.dst == 255.255.255.255</code> and
- each individual <code>inport</code>, and use the same actions in
- which <var>S</var> is a function of <code>inport</code>.
+ Reply to ARP requests.
</p>
<p>
- Not yet implemented.
+ These flows reply to ARP requests for the router's own IP address.
+ For each router port <var>P</var> that owns IP address <var>A</var>
+ and Ethernet address <var>E</var>, a priority-90 flow matches
+ <code>inport == <var>P</var> && arp.op == 1 &&
+ arp.tpa == <var>A</var></code> (ARP request) with the following
+ actions:
</p>
+
+ <pre>
+eth.dst = eth.src;
+eth.src = <var>E</var>;
+arp.op = 2; /* ARP reply. */
+arp.tha = arp.sha;
+arp.sha = <var>E</var>;
+arp.tpa = arp.spa;
+arp.spa = <var>A</var>;
+outport = <var>P</var>;
+inport = ""; /* Allow sending out inport. */
+output;
+ </pre>
</li>
<li>
<p>
- ARP reply. These flows reply to ARP requests for the router's own IP
- address. For each router port <var>P</var> that owns IP address
- <var>A</var> and Ethernet address <var>E</var>, a priority-90 flow
- matches <code>inport == <var>P</var> && arp.tpa ==
- <var>A</var> && arp.op == 1</code> (ARP request) with the
- following actions:
+ These flows reply to ARP requests for the virtual IP addresses
+ configured in the router for DNAT. For a configured DNAT IP address
+ <var>A</var>, for each router port <var>P</var> with Ethernet
+ address <var>E</var>, a priority-90 flow matches
+ <code>inport == <var>P</var> && arp.op == 1 &&
+ arp.tpa == <var>A</var></code> (ARP request)
+ with the following actions:
</p>
<pre>
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
-inport = \"\"; /* Allow sending out inport. */
+inport = ""; /* Allow sending out inport. */
output;
</pre>
</li>
+ <li>
+ ARP reply handling. These flows use ARP replies to populate the
+ logical router's ARP table. A priority-90 flow with match <code>arp.op
+ == 2</code> has actions <code>put_arp(inport, arp.spa,
+ arp.sha);</code>.
+ </li>
+
<li>
<p>
UDP port unreachable. Priority-80 flows generate ICMP port
handled by one of the flows above, which amounts to ICMP (other than
echo requests) and fragments with nonzero offsets. For each IP address
<var>A</var> owned by the router, a priority-60 flow matches
- <code>ip4.dst == <var>A</var></code> and drops the traffic.
+ <code>ip4.dst == <var>A</var></code> and drops the traffic. An
+ exception is made and the above flow is not added if the router
+ port's own IP address is used to SNAT packets passing through that
+ router.
</li>
</ul>
broadcast address. By definition this traffic should not be forwarded.
</li>
- <li>
- Drop IP multicast. A priority-50 flow with match
- <code>ip4.mcast</code> drops IP multicast traffic.
- </li>
-
<li>
<p>
ICMP time exceeded. For each router port <var>P</var>, whose IP
</li>
</ul>
- <h3>Ingress Table 2: IP Routing</h3>
+ <h3>Ingress Table 2: UNSNAT</h3>
+
+ <p>
+ This is for already established connections' reverse traffic.
+ i.e., SNAT has already been done in egress pipeline and now the
+ packet has entered the ingress pipeline as part of a reply. It is
+ unSNATted here.
+ </p>
+
+ <ul>
+ <li>
+ <p>
+ For each configuration in the OVN Northbound database, that asks
+ to change the source IP address of a packet from <var>A</var> to
+ <var>B</var>, a priority-100 flow matches <code>ip &&
+ ip4.dst == <var>B</var></code> with an action
+ <code>ct_snat; next;</code>.
+ </p>
+
+ <p>
+ A priority-0 logical flow with match <code>1</code> has actions
+ <code>next;</code>.
+ </p>
+ </li>
+ </ul>
+
+ <h3>Ingress Table 3: DNAT</h3>
+
+ <p>
+ Packets enter the pipeline with destination IP address that needs to
+ be DNATted from a virtual IP address to a real IP address. Packets
+ in the reverse direction needs to be unDNATed.
+ </p>
+ <ul>
+ <li>
+ <p>
+ For each configuration in the OVN Northbound database, that asks
+ to change the destination IP address of a packet from <var>A</var> to
+ <var>B</var>, a priority-100 flow matches <code>ip &&
+ ip4.dst == <var>A</var></code> with an action <code>inport = "";
+ ct_dnat(<var>B</var>);</code>.
+ </p>
+
+ <p>
+ For all IP packets of a Gateway router, a priority-50 flow with an
+ action <code>inport = ""; ct_dnat;</code>.
+ </p>
+
+ <p>
+ A priority-0 logical flow with match <code>1</code> has actions
+ <code>next;</code>.
+ </p>
+ </li>
+ </ul>
+
+ <h3>Ingress Table 4: IP Routing</h3>
<p>
A packet that arrives at this table is an IP packet that should be routed
to the address in <code>ip4.dst</code>. This table implements IP
routing, setting <code>reg0</code> to the next-hop IP address (leaving
<code>ip4.dst</code>, the packet's final destination, unchanged) and
- advances to the next table for ARP resolution.
+ advances to the next table for ARP resolution. It also sets
+ <code>reg1</code> to the IP address owned by the selected router port
+ (which is used later in table 6 as the IP source address for an ARP
+ request, if needed).
</p>
<p>
<li>
<p>
Routing table. For each route to IPv4 network <var>N</var> with
- netmask <var>M</var>, a logical flow with match <code>ip4.dst ==
+ netmask <var>M</var>, on router port <var>P</var> with IP address
+ <var>A</var> and Ethernet
+ address <var>E</var>, a logical flow with match <code>ip4.dst ==
<var>N</var>/<var>M</var></code>, whose priority is the number of
1-bits in <var>M</var>, has the following actions:
</p>
<pre>
ip.ttl--;
reg0 = <var>G</var>;
+reg1 = <var>A</var>;
+eth.src = <var>E</var>;
+outport = <var>P</var>;
+inport = ""; /* Allow sending out inport. */
next;
</pre>
</p>
<p>
- If the route has a gateway, <var>G</var> is the gateway IP address,
- otherwise it is <code>ip4.dst</code>.
+ If the route has a gateway, <var>G</var> is the gateway IP address.
+ Instead, if the route is from a configured static route, <var>G</var>
+ is the next hop IP address. Else it is <code>ip4.dst</code>.
</p>
</li>
</li>
</ul>
- <h3>Ingress Table 3: ARP Resolution</h3>
+ <h3>Ingress Table 5: ARP Resolution</h3>
<p>
Any packet that reaches this table is an IP packet whose next-hop IP
<ul>
<li>
<p>
- Known MAC bindings. For each IP address <var>A</var> whose host is
- known to have Ethernet address <var>HE</var> and reside on router
- port <var>P</var> with Ethernet address <var>PE</var>, a priority-200
- flow with match <code>reg0 == <var>A</var></code> has the following
- actions:
+ Static MAC bindings. MAC bindings can be known statically based on
+ data in the <code>OVN_Northbound</code> database. For router ports
+ connected to logical switches, MAC bindings can be known statically
+ from the <code>addresses</code> column in the
+ <code>Logical_Switch_Port</code> table. For router ports
+ connected to other logical routers, MAC bindings can be known
+ statically from the <code>mac</code> and <code>networks</code>
+ column in the <code>Logical_Router_Port</code> table.
</p>
- <pre>
-eth.src = <var>PE</var>;
-eth.dst = <var>HE</var>;
-outport = <var>P</var>;
-output;
- </pre>
+ <p>
+ For each IP address <var>A</var> whose host is known to have Ethernet
+ address <var>E</var> on router port <var>P</var>, a priority-100 flow
+ with match <code>outport === <var>P</var> && reg0 ==
+ <var>A</var></code> has actions <code>eth.dst = <var>E</var>;
+ next;</code>.
+ </p>
<p>
- MAC bindings can be known statically based on data in the
- <code>OVN_Northbound</code> database. For router ports connected to
- logical switches, MAC bindings can be known statically from the
- <code>addresses</code> column in the <code>Logical_Port</code> table.
- For router ports connected to other logical routers, MAC bindings can
- be known statically from the <code>mac</code> and
- <code>network</code> column in the <code>Logical_Router_Port</code>
- table.
+ For each logical router port with an IP address <var>A</var> and
+ a mac address of <var>E</var> that is reachable via a different
+ logical router port <var>P</var>, a priority-100 flow with
+ match <code>outport === <var>P</var> && reg0 ==
+ <var>A</var></code> has actions <code>eth.dst = <var>E</var>;
+ next;</code>.
</p>
</li>
<li>
<p>
- Unknown MAC bindings. For each non-gateway route to IPv4 network
- <var>N</var> with netmask <var>M</var> on router port <var>P</var>
- that owns IP address <var>A</var> and Ethernet address <var>E</var>,
- a logical flow with match <code>ip4.dst ==
- <var>N</var>/<var>M</var></code>, whose priority is the number of
- 1-bits in <var>M</var>, has the following actions:
+ Dynamic MAC bindings. This flows resolves MAC-to-IP bindings that
+ have become known dynamically through ARP. (The next table will
+ issue an ARP request for cases where the binding is not yet known.)
+ </p>
+
+ <p>
+ A priority-0 logical flow with match <code>1</code> has actions
+ <code>get_arp(outport, reg0); next;</code>.
+ </p>
+ </li>
+ </ul>
+
+ <h3>Ingress Table 6: ARP Request</h3>
+
+ <p>
+ In the common case where the Ethernet destination has been resolved, this
+ table outputs the packet. Otherwise, it composes and sends an ARP
+ request. It holds the following flows:
+ </p>
+
+ <ul>
+ <li>
+ <p>
+ Unknown MAC address. A priority-100 flow with match <code>eth.dst ==
+ 00:00:00:00:00:00</code> has the following actions:
</p>
<pre>
arp {
eth.dst = ff:ff:ff:ff:ff:ff;
- eth.src = <var>E</var>;
- arp.sha = <var>E</var>;
- arp.tha = 00:00:00:00:00:00;
- arp.spa = <var>A</var>;
- arp.tpa = ip4.dst;
+ arp.spa = reg1;
arp.op = 1; /* ARP request. */
- outport = <var>P</var>;
output;
};
</pre>
<p>
- TBD: How to install MAC bindings when an ARP response comes back.
- (Implement a "learn" action?)
+ (Ingress table 4 initialized <code>reg1</code> with the IP address
+ owned by <code>outport</code>.)
</p>
<p>
- Not yet implemented.
+ The IP packet that triggers the ARP request is dropped.
+ </p>
+ </li>
+
+ <li>
+ Known MAC address. A priority-0 flow with match <code>1</code> has
+ actions <code>output;</code>.
+ </li>
+ </ul>
+
+ <h3>Egress Table 0: SNAT</h3>
+
+ <p>
+ Packets that are configured to be SNATed get their source IP address
+ changed based on the configuration in the OVN Northbound database.
+ </p>
+ <ul>
+ <li>
+ <p>
+ For each configuration in the OVN Northbound database, that asks
+ to change the source IP address of a packet from an IP address of
+ <var>A</var> or to change the source IP address of a packet that
+ belongs to network <var>A</var> to <var>B</var>, a flow matches
+ <code>ip && ip4.src == <var>A</var></code> with an action
+ <code>ct_snat(<var>B</var>);</code>. The priority of the flow
+ is calculated based on the mask of <var>A</var>, with matches
+ having larger masks getting higher priorities.
+ </p>
+ <p>
+ A priority-0 logical flow with match <code>1</code> has actions
+ <code>next;</code>.
</p>
</li>
</ul>
- <h3>Egress Table 0: Delivery</h3>
+ <h3>Egress Table 1: Delivery</h3>
<p>
Packets that reach this table are ready for delivery. It contains