This database holds logical and physical configuration and state for the
Open Virtual Network (OVN) system to support virtual network abstraction.
For an introduction to OVN, please see ovn-architecture
(7).
The OVN Southbound database sits at the center of the OVN
architecture. It is the one component that speaks both southbound
directly to all the hypervisors and gateways, via
ovn-controller
/ovn-controller-vtep
, and
northbound to the Cloud Management System, via ovn-northd
:
The OVN Southbound database contains classes of data with
different properties, as described in the sections below.
PN tables contain information about the chassis nodes in the system. This
contains all the information necessary to wire the overlay, such as IP
addresses, supported tunnel types, and security keys.
The amount of PN data is small (O(n) in the number of chassis) and it
changes infrequently, so it can be replicated to every chassis.
LN tables contain the topology of logical switches and routers, ACLs,
firewall rules, and everything needed to describe how packets traverse a
logical network, represented as logical datapath flows (see Logical
Datapath Flows, below).
LN data may be large (O(n) in the number of logical ports, ACL rules,
etc.). Thus, to improve scaling, each chassis should receive only data
related to logical networks in which that chassis participates. Past
experience shows that in the presence of large logical networks, even
finer-grained partitioning of data, e.g. designing logical flows so that
only the chassis hosting a logical port needs related flows, pays off
scale-wise. (This is not necessary initially but it is worth bearing in
mind in the design.)
The LN is a slave of the cloud management system running northbound of OVN.
That CMS determines the entire OVN logical configuration and therefore the
LN's content at any given time is a deterministic function of the CMS's
configuration, although that happens indirectly via the
database and ovn-northd
.
LN data is likely to change more quickly than PN data. This is especially
true in a container environment where VMs are created and destroyed (and
therefore added to and deleted from logical switches) quickly.
These tables link logical and physical components. They show the current
placement of logical components (such as VMs and VIFs) onto chassis, and
map logical entities to the values that represent them in tunnel
encapsulations.
These tables change frequently, at least every time a VM powers up or down
or migrates, and especially quickly in a container environment. The
amount of data per VM (or VIF) is small.
Each chassis is authoritative about the VMs and VIFs that it hosts at any
given time and can efficiently flood that state to a central location, so
the consistency needs are minimal.
Each row in this table represents one logical flow.
ovn-northd
populates this table with logical flows
that implement the L2 and L3 topologies specified in the
database. Each hypervisor, via
ovn-controller
, translates the logical flows into
OpenFlow flows specific to its hypervisor and installs them into
Open vSwitch.
Logical flows are expressed in an OVN-specific format, described here. A
logical datapath flow is much like an OpenFlow flow, except that the
flows are written in terms of logical ports and logical datapaths instead
of physical ports and physical datapaths. Translation between logical
and physical flows helps to ensure isolation between logical datapaths.
(The logical flow abstraction also allows the OVN centralized
components to do less work, since they do not have to separately
compute and push out physical flows to each chassis.)
The default action when no flow matches is to drop packets.
Architectural Logical Life Cycle of a Packet
This following description focuses on the life cycle of a packet through
a logical datapath, ignoring physical details of the implementation.
Please refer to Architectural Physical Life Cycle of a Packet in
ovn-architecture
(7) for the physical information.
The description here is written as if OVN itself executes these steps,
but in fact OVN (that is, ovn-controller
) programs Open
vSwitch, via OpenFlow and OVSDB, to execute them on its behalf.
At a high level, OVN passes each packet through the logical datapath's
logical ingress pipeline, which may output the packet to one or more
logical port or logical multicast groups. For each such logical output
port, OVN passes the packet through the datapath's logical egress
pipeline, which may either drop the packet or deliver it to the
destination. Between the two pipelines, outputs to logical multicast
groups are expanded into logical ports, so that the egress pipeline only
processes a single logical output port at a time. Between the two
pipelines is also where, when necessary, OVN encapsulates a packet in a
tunnel (or tunnels) to transmit to remote hypervisors.
In more detail, to start, OVN searches the
table for a row with correct , a of ingress
, a
of 0, and a that is true for the packet. If none
is found, OVN drops the packet. If OVN finds more than one, it chooses
the match with the highest . Then OVN executes
each of the actions specified in the row's column,
in the order specified. Some actions, such as those to modify packet
headers, require no further details. The next
and
output
actions are special.
The next
action causes the above process to be repeated
recursively, except that OVN searches for of 1
instead of 0. Similarly, any next
action in a row found in
that table would cause a further search for a of
2, and so on. When recursive processing completes, flow control returns
to the action following next
.
The output
action also introduces recursion. Its effect
depends on the current value of the outport
field. Suppose
outport
designates a logical port. First, OVN compares
inport
to outport
; if they are equal, it treats
the output
as a no-op by default. In the common
case, where they are different, the packet enters the egress
pipeline. This transition to the egress pipeline discards
register data, e.g. reg0
... reg9
and
connection tracking state, to achieve uniform behavior regardless
of whether the egress pipeline is on a different hypervisor
(because registers aren't preserve across tunnel encapsulation).
To execute the egress pipeline, OVN again searches the table for a row with correct , a of 0, a that is true for the packet, but now looking for a of egress
. If no matching row is found,
the output becomes a no-op. Otherwise, OVN executes the actions for the
matching flow (which is chosen from multiple, if necessary, as already
described).
In the egress
pipeline, the next
action acts as
already described, except that it, of course, searches for
egress
flows. The output
action, however, now
directly outputs the packet to the output port (which is now fixed,
because outport
is read-only within the egress pipeline).
The description earlier assumed that outport
referred to a
logical port. If it instead designates a logical multicast group, then
the description above still applies, with the addition of fan-out from
the logical multicast group to each logical port in the group. For each
member of the group, OVN executes the logical pipeline as described, with
the logical output port replaced by the group member.
Pipeline Stages
ovn-northd
populates the table
with the logical flows described in detail in ovn-northd
(8).
The logical datapath to which the logical flow belongs.
The primary flows used for deciding on a packet's destination are the
ingress
flows. The egress
flows implement
ACLs. See Logical Life Cycle of a Packet, above, for details.
The stage in the logical pipeline, analogous to an OpenFlow table number.
The flow's priority. Flows with numerically higher priority take
precedence over those with lower. If two logical datapath flows with the
same priority both match, then the one actually applied to the packet is
undefined.
A matching expression. OVN provides a superset of OpenFlow matching
capabilities, using a syntax similar to Boolean expressions in a
programming language.
The most important components of match expression are
comparisons between symbols and
constants, e.g. ip4.dst == 192.168.0.1
,
ip.proto == 6
, arp.op == 1
, eth.type ==
0x800
. The logical AND operator &&
and
logical OR operator ||
can combine comparisons into a
larger expression.
Matching expressions also support parentheses for grouping, the logical
NOT prefix operator !
, and literals 0
and
1
to express ``false'' or ``true,'' respectively. The
latter is useful by itself as a catch-all expression that matches every
packet.
Match expressions also support a kind of function syntax. The
following functions are supported:
is_chassis_resident(lport)
-
Evaluates to true on a chassis on which logical port lport
(a quoted string) resides, and to false elsewhere. This function was
introduced in OVN 2.7.
Symbols
Type. Symbols have integer or string
type. Integer symbols have a width in bits.
Kinds. There are three kinds of symbols:
-
Fields. A field symbol represents a packet header or
metadata field. For example, a field
named vlan.tci
might represent the VLAN TCI field in a
packet.
A field symbol can have integer or string type. Integer fields can
be nominal or ordinal (see Level of Measurement,
below).
-
Subfields. A subfield represents a subset of bits from
a larger field. For example, a field vlan.vid
might
be defined as an alias for vlan.tci[0..11]
. Subfields
are provided for syntactic convenience, because it is always
possible to instead refer to a subset of bits from a field
directly.
Only ordinal fields (see Level of Measurement,
below) may have subfields. Subfields are always ordinal.
-
Predicates. A predicate is shorthand for a Boolean
expression. Predicates may be used much like 1-bit fields. For
example, ip4
might expand to eth.type ==
0x800
. Predicates are provided for syntactic convenience,
because it is always possible to instead specify the underlying
expression directly.
A predicate whose expansion refers to any nominal field or
predicate (see Level of Measurement, below) is nominal;
other predicates have Boolean level of measurement.
Level of Measurement. See
http://en.wikipedia.org/wiki/Level_of_measurement for the statistical
concept on which this classification is based. There are three
levels:
-
Ordinal. In statistics, ordinal values can be ordered
on a scale. OVN considers a field (or subfield) to be ordinal if
its bits can be examined individually. This is true for the
OpenFlow fields that OpenFlow or Open vSwitch makes ``maskable.''
Any use of a nominal field may specify a single bit or a range of
bits, e.g. vlan.tci[13..15]
refers to the PCP field
within the VLAN TCI, and eth.dst[40]
refers to the
multicast bit in the Ethernet destination address.
OVN supports all the usual arithmetic relations (==
,
!=
, <
, <=
,
>
, and >=
) on ordinal fields and
their subfields, because OVN can implement these in OpenFlow and
Open vSwitch as collections of bitwise tests.
-
Nominal. In statistics, nominal values cannot be
usefully compared except for equality. This is true of OpenFlow
port numbers, Ethernet types, and IP protocols are examples: all of
these are just identifiers assigned arbitrarily with no deeper
meaning. In OpenFlow and Open vSwitch, bits in these fields
generally aren't individually addressable.
OVN only supports arithmetic tests for equality on nominal fields,
because OpenFlow and Open vSwitch provide no way for a flow to
efficiently implement other comparisons on them. (A test for
inequality can be sort of built out of two flows with different
priorities, but OVN matching expressions always generate flows with
a single priority.)
String fields are always nominal.
-
Boolean. A nominal field that has only two values, 0
and 1, is somewhat exceptional, since it is easy to support both
equality and inequality tests on such a field: either one can be
implemented as a test for 0 or 1.
Only predicates (see above) have a Boolean level of measurement.
This isn't a standard level of measurement.
Prerequisites. Any symbol can have prerequisites, which are
additional condition implied by the use of the symbol. For example,
For example, icmp4.type
symbol might have prerequisite
icmp4
, which would cause an expression icmp4.type ==
0
to be interpreted as icmp4.type == 0 &&
icmp4
, which would in turn expand to icmp4.type == 0
&& eth.type == 0x800 && ip4.proto == 1
(assuming
icmp4
is a predicate defined as suggested under
Types above).
Relational operators
All of the standard relational operators ==
,
!=
, <
, <=
,
>
, and >=
are supported. Nominal
fields support only ==
and !=
, and only in a
positive sense when outer !
are taken into account,
e.g. given string field inport
, inport ==
"eth0"
and !(inport != "eth0")
are acceptable, but
not inport != "eth0"
.
The implementation of ==
(or !=
when it is
negated), is more efficient than that of the other relational
operators.
Constants
Integer constants may be expressed in decimal, hexadecimal prefixed by
0x
, or as dotted-quad IPv4 addresses, IPv6 addresses in
their standard forms, or Ethernet addresses as colon-separated hex
digits. A constant in any of these forms may be followed by a slash
and a second constant (the mask) in the same form, to form a masked
constant. IPv4 and IPv6 masks may be given as integers, to express
CIDR prefixes.
String constants have the same syntax as quoted strings in JSON (thus,
they are Unicode strings).
Some operators support sets of constants written inside curly braces
{
... }
. Commas between elements of a set,
and after the last elements, are optional. With ==
,
``field == { constant1,
constant2,
... }
'' is syntactic sugar
for ``field == constant1 ||
field == constant2 ||
...
.
Similarly, ``field != { constant1,
constant2,
... }
'' is equivalent to
``field != constant1 &&
field != constant2 &&
...
''.
You may refer to a set of IPv4, IPv6, or MAC addresses stored in the
table by its . An with a name
of set1
can be referred to as
$set1
.
Miscellaneous
Comparisons may name the symbol or the constant first,
e.g. tcp.src == 80
and 80 == tcp.src
are both
acceptable.
Tests for a range may be expressed using a syntax like 1024 <=
tcp.src <= 49151
, which is equivalent to 1024 <=
tcp.src && tcp.src <= 49151
.
For a one-bit field or predicate, a mention of its name is equivalent
to symobl == 1
, e.g. vlan.present
is equivalent to vlan.present == 1
. The same is true for
one-bit subfields, e.g. vlan.tci[12]
. There is no
technical limitation to implementing the same for ordinal fields of all
widths, but the implementation is expensive enough that the syntax
parser requires writing an explicit comparison against zero to make
mistakes less likely, e.g. in tcp.src != 0
the comparison
against 0 is required.
Operator precedence is as shown below, from highest to lowest.
There are two exceptions where parentheses are required even though the
table would suggest that they are not: &&
and
||
require parentheses when used together, and
!
requires parentheses when applied to a relational
expression. Thus, in (eth.type == 0x800 || eth.type == 0x86dd)
&& ip.proto == 6
or !(arp.op == 1)
, the
parentheses are mandatory.
()
== != < <= > >=
!
&& ||
Comments may be introduced by //
, which extends
to the next new-line. Comments within a line may be bracketed by
/*
and */
. Multiline comments are not
supported.
Symbols
Most of the symbols below have integer type. Only inport
and outport
have string type. inport
names a
logical port. Thus, its value is a name
from the table. outport
may
name a logical port, as inport
, or a logical multicast
group defined in the table. For both
symbols, only names within the flow's logical datapath may be used.
The reg
X symbols are 32-bit integers.
The xxreg
X symbols are 128-bit integers,
which overlay four of the 32-bit registers: xxreg0
overlays reg0
through reg3
, with
reg0
supplying the most-significant bits of
xxreg0
and reg3
the least-signficant.
xxreg1
similarly overlays reg4
through
reg7
.
reg0
...reg9
xxreg0
xxreg1
inport
outport
flags.loopback
eth.src
eth.dst
eth.type
vlan.tci
vlan.vid
vlan.pcp
vlan.present
ip.proto
ip.dscp
ip.ecn
ip.ttl
ip.frag
ip4.src
ip4.dst
ip6.src
ip6.dst
ip6.label
arp.op
arp.spa
arp.tpa
arp.sha
arp.tha
tcp.src
tcp.dst
tcp.flags
udp.src
udp.dst
sctp.src
sctp.dst
icmp4.type
icmp4.code
icmp6.type
icmp6.code
nd.target
nd.sll
nd.tll
ct_mark
ct_label
-
ct_state
, which has the following Boolean subfields:
ct.new
: True for a new flow
ct.est
: True for an established flow
ct.rel
: True for a related flow
ct.rpl
: True for a reply flow
ct.inv
: True for a connection entry in a bad state
The above subfields of ct_state
are initialized by
the ct_next
action, described later.
-
ct.dnat
: True for a packet whose destination IP
address has been changed.
-
ct.snat
: True for a packet whose source IP
address has been changed.
The above subfields of ct_state
are initialized by
the actions like ct_dnat
, ct_snat
and
ct_lb
described later.
The following predicates are supported:
eth.bcast
expands to eth.dst == ff:ff:ff:ff:ff:ff
eth.mcast
expands to eth.dst[40]
vlan.present
expands to vlan.tci[12]
ip4
expands to eth.type == 0x800
ip4.mcast
expands to ip4.dst[28..31] == 0xe
ip6
expands to eth.type == 0x86dd
ip
expands to ip4 || ip6
icmp4
expands to ip4 && ip.proto == 1
icmp6
expands to ip6 && ip.proto == 58
icmp
expands to icmp4 || icmp6
ip.is_frag
expands to ip.frag[0]
ip.later_frag
expands to ip.frag[1]
ip.first_frag
expands to ip.is_frag && !ip.later_frag
arp
expands to eth.type == 0x806
nd
expands to icmp6.type == {135, 136} && icmp6.code == 0 && ip.ttl == 255
nd_ns
expands to icmp6.type == 135 && icmp6.code == 0 && ip.ttl == 255
nd_na
expands to icmp6.type == 136 && icmp6.code == 0 && ip.ttl == 255
tcp
expands to ip.proto == 6
udp
expands to ip.proto == 17
sctp
expands to ip.proto == 132
Logical datapath actions, to be executed when the logical flow
represented by this row is the highest-priority match.
Actions share lexical syntax with the column. An
empty set of actions (or one that contains just white space or
comments), or a set of actions that consists of just
drop;
, causes the matched packets to be dropped.
Otherwise, the column should contain a sequence of actions, each
terminated by a semicolon.
The following actions are defined:
output;
-
In the ingress pipeline, this action executes the
egress
pipeline as a subroutine. If
outport
names a logical port, the egress pipeline
executes once; if it is a multicast group, the egress pipeline runs
once for each logical port in the group.
In the egress pipeline, this action performs the actual
output to the outport
logical port. (In the egress
pipeline, outport
never names a multicast group.)
By default, output to the input port is implicitly dropped,
that is, output
becomes a no-op if
outport
== inport
. Occasionally
it may be useful to override this behavior, e.g. to send an
ARP reply to an ARP request; to do so, use
flags.loopback = 1
to allow the packet to
"hair-pin" back to the input port.
next;
next(table);
next(pipeline=pipeline, table=table);
-
Executes the given logical datapath table in
pipeline as a subroutine. The default table is
just after the current one. If pipeline is specified, it
may be
ingress
or egress
; the default
pipeline is the one currently executing. Actions in the
ingress pipeline may not use next
to jump into the
egress pipeline (use the output
instead), but
transitions in the opposite direction are allowed.
field = constant;
-
Sets data or metadata field field to constant value
constant, e.g. outport = "vif0";
to set the
logical output port. To set only a subset of bits in a field,
specify a subfield for field or a masked
constant, e.g. one may use vlan.pcp[2] = 1;
or vlan.pcp = 4/4;
to set the most sigificant bit of
the VLAN PCP.
Assigning to a field with prerequisites implicitly adds those
prerequisites to ; thus, for example, a flow
that sets tcp.dst
applies only to TCP flows,
regardless of whether its mentions any TCP
field.
Not all fields are modifiable (e.g. eth.type
and
ip.proto
are read-only), and not all modifiable fields
may be partially modified (e.g. ip.ttl
must assigned
as a whole). The outport
field is modifiable in the
ingress
pipeline but not in the egress
pipeline.
field1 = field2;
-
Sets data or metadata field field1 to the value of data
or metadata field field2, e.g. reg0 =
ip4.src;
copies ip4.src
into reg0
.
To modify only a subset of a field's bits, specify a subfield for
field1 or field2 or both, e.g. vlan.pcp
= reg0[0..2];
copies the least-significant bits of
reg0
into the VLAN PCP.
field1 and field2 must be the same type,
either both string or both integer fields. If they are both
integer fields, they must have the same width.
If field1 or field2 has prerequisites, they
are added implicitly to . It is possible to
write an assignment with contradictory prerequisites, such as
ip4.src = ip6.src[0..31];
, but the contradiction means
that a logical flow with such an assignment will never be matched.
field1 <-> field2;
-
Similar to field1 = field2;
except that the two values are exchanged instead of copied. Both
field1 and field2 must modifiable.
ip.ttl--;
-
Decrements the IPv4 or IPv6 TTL. If this would make the TTL zero
or negative, then processing of the packet halts; no further
actions are processed. (To properly handle such cases, a
higher-priority flow should match on
ip.ttl == {0, 1};
.)
Prerequisite: ip
ct_next;
-
Apply connection tracking to the flow, initializing
ct_state
for matching in later tables.
Automatically moves on to the next table, as if followed by
next
.
As a side effect, IP fragments will be reassembled for matching.
If a fragmented packet is output, then it will be sent with any
overlapping fragments squashed. The connection tracking state is
scoped by the logical port when the action is used in a flow for
a logical switch, so overlapping addresses may be used. To allow
traffic related to the matched flow, execute ct_commit
. Connection tracking state is scoped by the logical
topology when the action is used in a flow for a router.
It is possible to have actions follow ct_next
,
but they will not have access to any of its side-effects and
is not generally useful.
ct_commit;
ct_commit(ct_mark=value[/mask]);
ct_commit(ct_label=value[/mask]);
ct_commit(ct_mark=value[/mask], ct_label=value[/mask]);
-
Commit the flow to the connection tracking entry associated with it
by a previous call to ct_next
. When
ct_mark=value[/mask]
and/or
ct_label=value[/mask]
are supplied,
ct_mark
and/or ct_label
will be set to the
values indicated by value[/mask] on the connection
tracking entry. ct_mark
is a 32-bit field.
ct_label
is a 128-bit field. The value[/mask]
should be specified in hex string if more than 64bits are to be used.
Note that if you want processing to continue in the next table,
you must execute the next
action after
ct_commit
. You may also leave out next
which will commit connection tracking state, and then drop the
packet. This could be useful for setting ct_mark
on a connection tracking entry before dropping a packet,
for example.
ct_dnat;
ct_dnat(IP);
-
ct_dnat
sends the packet through the DNAT zone in
connection tracking table to unDNAT any packet that was DNATed in
the opposite direction. The packet is then automatically sent to
to the next tables as if followed by next;
action.
The next tables will see the changes in the packet caused by
the connection tracker.
ct_dnat(IP)
sends the packet through the
DNAT zone to change the destination IP address of the packet to
the one provided inside the parentheses and commits the connection.
The packet is then automatically sent to the next tables as if
followed by next;
action. The next tables will see
the changes in the packet caused by the connection tracker.
ct_snat;
ct_snat(IP);
-
ct_snat
sends the packet through the SNAT zone to
unSNAT any packet that was SNATed in the opposite direction. If
the packet needs to be sent to the next tables, then it should be
followed by a next;
action. The next tables will not
see the changes in the packet caused by the connection tracker.
ct_snat(IP)
sends the packet through the
SNAT zone to change the source IP address of the packet to
the one provided inside the parenthesis and commits the connection.
The packet is then automatically sent to the next tables as if
followed by next;
action. The next tables will see the
changes in the packet caused by the connection tracker.
ct_clear;
-
Clears connection tracking state.
clone { action;
... };
-
Makes a copy of the packet being processed and executes each
action
on the copy. Actions following the
clone action, if any, apply to the original, unmodified
packet. This can be used as a way to ``save and restore'' the packet
around a set of actions that may modify it and should not persist.
arp { action;
... };
-
Temporarily replaces the IPv4 packet being processed by an ARP
packet and executes each nested action on the ARP
packet. Actions following the arp action, if any, apply
to the original, unmodified packet.
The ARP packet that this action operates on is initialized based on
the IPv4 packet being processed, as follows. These are default
values that the nested actions will probably want to change:
eth.src
unchanged
eth.dst
unchanged
eth.type = 0x0806
arp.op = 1
(ARP request)
arp.sha
copied from eth.src
arp.spa
copied from ip4.src
arp.tha = 00:00:00:00:00:00
arp.tpa
copied from ip4.dst
The ARP packet has the same VLAN header, if any, as the IP packet
it replaces.
Prerequisite: ip4
get_arp(P, A);
-
Parameters: logical port string field P, 32-bit
IP address field A.
Looks up A in P's mac binding table.
If an entry is found, stores its Ethernet address in
eth.dst
, otherwise stores
00:00:00:00:00:00
in eth.dst
.
Example: get_arp(outport, ip4.dst);
-
put_arp(P, A, E);
-
Parameters: logical port string field P, 32-bit
IP address field A, 48-bit Ethernet address field
E.
Adds or updates the entry for IP address A in
logical port P's mac binding table, setting its
Ethernet address to E.
Example: put_arp(inport, arp.spa, arp.sha);
-
nd_na { action;
... };
-
Temporarily replaces the IPv6 neighbor solicitation packet
being processed by an IPv6 neighbor advertisement (NA)
packet and executes each nested action on the NA
packet. Actions following the nd_na
action,
if any, apply to the original, unmodified packet.
The NA packet that this action operates on is initialized based on
the IPv6 packet being processed, as follows. These are default
values that the nested actions will probably want to change:
eth.dst
exchanged with eth.src
eth.type = 0x86dd
ip6.dst
copied from ip6.src
ip6.src
copied from nd.target
icmp6.type = 136
(Neighbor Advertisement)
nd.target
unchanged
nd.sll = 00:00:00:00:00:00
nd.tll
copied from eth.dst
The ND packet has the same VLAN header, if any, as the IPv6 packet
it replaces.
Prerequisite: nd_ns
get_nd(P, A);
-
Parameters: logical port string field P, 128-bit
IPv6 address field A.
Looks up A in P's mac binding table.
If an entry is found, stores its Ethernet address in
eth.dst
, otherwise stores
00:00:00:00:00:00
in eth.dst
.
Example: get_nd(outport, ip6.dst);
-
put_nd(P, A, E);
-
Parameters: logical port string field P,
128-bit IPv6 address field A, 48-bit Ethernet
address field E.
Adds or updates the entry for IPv6 address A in
logical port P's mac binding table, setting its
Ethernet address to E.
Example: put_nd(inport, nd.target, nd.tll);
-
R = put_dhcp_opts(D1 = V1, D2 = V2, ..., Dn = Vn);
-
Parameters: one or more DHCP option/value pairs, which must
include an offerip
option (with code 0).
Result: stored to a 1-bit subfield R.
Valid only in the ingress pipeline.
When this action is applied to a DHCP request packet (DHCPDISCOVER
or DHCPREQUEST), it changes the packet into a DHCP reply (DHCPOFFER
or DHCPACK, respectively), replaces the options by those specified
as parameters, and stores 1 in R.
When this action is applied to a non-DHCP packet or a DHCP packet
that is not DHCPDISCOVER or DHCPREQUEST, it leaves the packet
unchanged and stores 0 in R.
The contents of the table control the
DHCP option names and values that this action supports.
Example:
reg0[0] = put_dhcp_opts(offerip = 10.0.0.2, router = 10.0.0.1,
netmask = 255.255.255.0, dns_server = {8.8.8.8, 7.7.7.7});
-
R = put_dhcpv6_opts(D1 = V1, D2 = V2, ..., Dn = Vn);
-
Parameters: one or more DHCPv6 option/value pairs.
Result: stored to a 1-bit subfield R.
Valid only in the ingress pipeline.
When this action is applied to a DHCPv6 request packet, it changes
the packet into a DHCPv6 reply, replaces the options by those
specified as parameters, and stores 1 in R.
When this action is applied to a non-DHCPv6 packet or an invalid
DHCPv6 request packet , it leaves the packet unchanged and stores
0 in R.
The contents of the table control the
DHCPv6 option names and values that this action supports.
Example:
reg0[3] = put_dhcpv6_opts(ia_addr = aef0::4, server_id = 00:00:00:00:10:02,
dns_server={ae70::1,ae70::2});
-
set_queue(queue_number);
-
Parameters: Queue number queue_number, in the range 0 to 61440.
This is a logical equivalent of the OpenFlow set_queue
action. It affects packets that egress a hypervisor through a
physical interface. For nonzero queue_number, it
configures packet queuing to match the settings configured for the
with
options:qdisc_queue_id
matching
queue_number. When queue_number is zero, it
resets queuing to the default strategy.
Example: set_queue(10);
ct_lb;
ct_lb(
ip[:
port]...);
-
With one or more arguments, ct_lb
commits the packet
to the connection tracking table and DNATs the packet's destination
IP address (and port) to the IP address or addresses (and optional
ports) specified in the string. If multiple comma-separated IP
addresses are specified, each is given equal weight for picking the
DNAT address. Processing automatically moves on to the next table,
as if next;
were specified, and later tables act on
the packet as modified by the connection tracker. Connection
tracking state is scoped by the logical port when the action is
used in a flow for a logical switch, so overlapping
addresses may be used. Connection tracking state is scoped by the
logical topology when the action is used in a flow for a router.
Without arguments, ct_lb
sends the packet to the
connection tracking table to NAT the packets. If the packet is
part of an established connection that was previously committed to
the connection tracker via ct_lb(
...)
, it
will automatically get DNATed to the same IP address as the first
packet in that connection.
The following actions will likely be useful later, but they have not
been thought out carefully.
icmp4 { action;
... };
-
Temporarily replaces the IPv4 packet being processed by an ICMPv4
packet and executes each nested action on the ICMPv4
packet. Actions following the icmp4 action, if any,
apply to the original, unmodified packet.
The ICMPv4 packet that this action operates on is initialized based
on the IPv4 packet being processed, as follows. These are default
values that the nested actions will probably want to change.
Ethernet and IPv4 fields not listed here are not changed:
ip.proto = 1
(ICMPv4)
ip.frag = 0
(not a fragment)
icmp4.type = 3
(destination unreachable)
icmp4.code = 1
(host unreachable)
Details TBD.
Prerequisite: ip4
tcp_reset;
-
This action transforms the current TCP packet according to the
following pseudocode:
if (tcp.ack) {
tcp.seq = tcp.ack;
} else {
tcp.ack = tcp.seq + length(tcp.payload);
tcp.seq = 0;
}
tcp.flags = RST;
Then, the action drops all TCP options and payload data, and
updates the TCP checksum.
Details TBD.
Prerequisite: tcp
Human-readable name for this flow's stage in the pipeline.
Source file and line number of the code that added this flow to the
pipeline.
The overall purpose of these columns is described under Common
Columns
at the beginning of this document.