2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

ovs-actions: New document describing OVS actions in detail.

Acked-by: Mark Michelson <mmichels@redhat.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Ben Pfaff
2018-11-08 21:39:55 -08:00
parent a31c38ad0b
commit be51cd4173
11 changed files with 3058 additions and 1121 deletions

View File

@@ -196,7 +196,7 @@ Q: Open vSwitch does not seem to obey my packet filter rules.
For simple filtering rules, it might be possible to achieve similar results
by installing appropriate OpenFlow flows instead. The OVS conntrack
feature (see the "ct" action in ovs-ofctl(8)) can implement a stateful
feature (see the "ct" action in ovs-actions(7)) can implement a stateful
firewall.
If the use of a particular packet filter setup is essential, Open vSwitch

View File

@@ -516,44 +516,6 @@ but the packets are getting dropped instead. Why?
See also the preceding question.
Q: The "learn" action can't learn the action I want, can you improve it?
A: By itself, the "learn" action can only put two kinds of actions into the
flows that it creates: "load" and "output" actions. If "learn" is used in
isolation, these are severe limits.
However, "learn" is not meant to be used in isolation. It is a primitive
meant to be used together with other Open vSwitch features to accomplish a
task. Its existing features are enough to accomplish most tasks.
Here is an outline of a typical pipeline structure that allows for
versatile behavior using "learn":
- Flows in table A contain a "learn" action, that populates flows in table
L, that use a "load" action to populate register R with information about
what was learned.
- Flows in table B contain two sequential resubmit actions: one to table L
and another one to table B+1.
- Flows in table B+1 match on register R and act differently depending on
what the flows in table L loaded into it.
This approach can be used to implement many "learn"-based features. For
example:
- Resubmit to a table selected based on learned information, e.g. see:
https://mail.openvswitch.org/pipermail/ovs-discuss/2016-June/021694.html
- MAC learning in the middle of a pipeline, as described in
:doc:`/tutorials/ovs-advanced`
- TCP state based firewalling, by learning outgoing connections based on
SYN packets and matching them up with incoming packets.
- At least some of the features described in T. A. Hoff, "Extending Open
vSwitch to Facilitate Creation of Stateful SDN Applications".
Q: When using the "ct" action with FTP connections, it doesn't seem to matter
if I set the "alg=ftp" parameter in the action. Is this required?

View File

@@ -50,6 +50,10 @@ The remainder are still in roff format can be found below:
.. list-table::
* - ovs-actions(7)
- `(pdf) <http://www.openvswitch.org/support/dist-docs/ovs-actions.7.pdf>`__
- `(html) <http://www.openvswitch.org/support/dist-docs/ovs-actions.7.html>`__
- `(plain text) <http://www.openvswitch.org/support/dist-docs/ovs-actions.7.txt>`__
* - ovn-architecture(7)
- `(pdf) <http://www.openvswitch.org/support/dist-docs/ovn-architecture.7.pdf>`__
- `(html) <http://www.openvswitch.org/support/dist-docs/ovn-architecture.7.html>`__

View File

@@ -1,8 +1,11 @@
#! /usr/bin/python
import getopt
import sys
import os.path
import re
import xml.dom.minidom
import build.nroff
OFP_ACTION_ALIGN = 8
@@ -69,14 +72,21 @@ def usage():
argv0 = os.path.basename(sys.argv[0])
print('''\
%(argv0)s, for extracting OpenFlow action data
usage: %(argv0)s OFP_ACTIONS.C [--prototypes | --definitions]
usage: %(argv0)s [prototypes | definitions] OFP-ACTIONS.c
usage: %(argv0)s ovs-actions OVS-ACTIONS.XML
This program reads ofp-actions.c to obtain information about OpenFlow
actions. With --prototypes, it outputs on stdout a set of prototypes to
#include early in ofp-actions.c. With --definitions, it outputs on stdout
a set of definitions to #include late in ofp-actions.c
Commands:
OFP_ACTIONS.C should point to lib/ofp-actions.c.\
prototypes OFP-ACTIONS.C
Reads ofp-actions.c and prints a set of prototypes to #include early in
ofp-actions.c.
definitions OFP-ACTIONS.C
Reads ofp-actions.c and prints a set of definitions to #include late in
ofp-actions.c.
ovs-actions OVS-ACTIONS.XML
Reads ovs-actions.xml and prints documentation in troff format.\
''' % {"argv0": argv0})
sys.exit(0)
@@ -377,19 +387,176 @@ static enum ofperr ofpact_decode(const struct ofp_action_header *,
uint64_t arg, const struct vl_mff_map *vl_mff_map,
uint64_t *tlv_bitmap, struct ofpbuf *out);
""")
## ------------------------ ##
## Documentation Generation ##
## ------------------------ ##
def action_to_xml(action_node, body):
syntax = 0
for node in action_node.childNodes:
if node.nodeType == node.ELEMENT_NODE and node.tagName == 'syntax':
if body[-1].strip() == '.PP':
del body[-1]
if syntax:
body += ['.IQ\n']
else:
body += ['.IP "\\fBSyntax:\\fR"\n']
body += [build.nroff.inline_xml_to_nroff(x, r'\fR')
for x in node.childNodes] + ['\n']
syntax += 1
elif (node.nodeType == node.ELEMENT_NODE
and node.tagName == 'conformance'):
body += ['.IP "\\fBConformance:\\fR"\n']
body += [build.nroff.block_xml_to_nroff(node.childNodes)]
else:
body += [build.nroff.block_xml_to_nroff([node])]
def group_xml_to_nroff(group_node):
title = group_node.attributes['title'].nodeValue
body = []
for node in group_node.childNodes:
if node.nodeType == node.ELEMENT_NODE and node.tagName == 'action':
action_to_xml(node, body)
else:
body += [build.nroff.block_xml_to_nroff([node])]
content = [
'.bp\n',
'.SH \"%s\"\n' % build.nroff.text_to_nroff(title.upper())]
content += body
return ''.join(content)
def make_ovs_actions(ovs_actions_xml):
document = xml.dom.minidom.parse(ovs_actions_xml)
doc = document.documentElement
global version
if version == None:
version = "UNKNOWN"
print('''\
'\\" tp
.\\" -*- mode: troff; coding: utf-8 -*-
.TH "ovs\-actions" 7 "%s" "Open vSwitch" "Open vSwitch Manual"
.fp 5 L CR \\" Make fixed-width font available as \\fL.
.de ST
. PP
. RS -0.15in
. I "\\\\$1"
. RE
..
.de SU
. PP
. I "\\\\$1"
..
.de IQ
. br
. ns
. IP "\\\\$1"
..
.de TQ
. br
. ns
. TP "\\\\$1"
..
.de URL
\\\\$2 \\(laURL: \\\\$1 \\(ra\\\\$3
..
.if \\n[.g] .mso www.tmac
.SH NAME
ovs\-actions \- OpenFlow actions and instructions with Open vSwitch extensions
.
.PP
''' % version)
s = ''
for node in doc.childNodes:
if node.nodeType == node.ELEMENT_NODE and node.tagName == "group":
s += group_xml_to_nroff(node)
elif node.nodeType == node.TEXT_NODE:
assert node.data.isspace()
elif node.nodeType == node.COMMENT_NODE:
pass
else:
s += build.nroff.block_xml_to_nroff([node])
if n_errors:
sys.exit(1)
output = []
for oline in s.split("\n"):
oline = oline.strip()
# Life is easier with nroff if we don't try to feed it Unicode.
# Fortunately, we only use a few characters outside the ASCII range.
oline = oline.replace(u'\u2208', r'\[mo]')
oline = oline.replace(u'\u2260', r'\[!=]')
oline = oline.replace(u'\u2264', r'\[<=]')
oline = oline.replace(u'\u2265', r'\[>=]')
oline = oline.replace(u'\u00d7', r'\[mu]')
if len(oline):
output += [oline]
# nroff tends to ignore .bp requests if they come after .PP requests,
# so remove .PPs that precede .bp.
for i in range(len(output)):
if output[i] == '.bp':
j = i - 1
while j >= 0 and output[j] == '.PP':
output[j] = None
j -= 1
for i in range(len(output)):
if output[i] is not None:
print(output[i])
## ------------ ##
## Main Program ##
## ------------ ##
if __name__ == '__main__':
if '--help' in sys.argv:
usage()
elif len(sys.argv) != 3:
sys.stderr.write("exactly two arguments required; "
"use --help for help\n")
sys.exit(1)
elif sys.argv[2] == '--prototypes':
extract_ofp_actions(sys.argv[1], False)
elif sys.argv[2] == '--definitions':
extract_ofp_actions(sys.argv[1], True)
else:
sys.stderr.write("invalid arguments; use --help for help\n")
argv0 = sys.argv[0]
try:
options, args = getopt.gnu_getopt(sys.argv[1:], 'h',
['help', 'ovs-version='])
except getopt.GetoptError as geo:
sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
sys.exit(1)
global version
version = None
for key, value in options:
if key in ['-h', '--help']:
usage()
elif key == '--ovs-version':
version = value
else:
sys.exit(0)
if not args:
sys.stderr.write("%s: missing command argument "
"(use --help for help)\n" % argv0)
sys.exit(1)
commands = {"prototypes": (lambda fn: extract_ofp_actions(fn, False), 1),
"definitions": (lambda fn: extract_ofp_actions(fn, True), 1),
"ovs-actions": (make_ovs_actions, 1)}
if not args[0] in commands:
sys.stderr.write("%s: unknown command \"%s\" "
"(use --help for help)\n" % (argv0, args[0]))
sys.exit(1)
func, n_args = commands[args[0]]
if len(args) - 1 != n_args:
sys.stderr.write("%s: \"%s\" requires %d arguments but %d "
"provided\n"
% (argv0, args[0], n_args, len(args) - 1))
sys.exit(1)
func(*args[1:])

View File

@@ -557,9 +557,9 @@ CLEANFILES += lib/meta-flow.inc lib/nx-match.inc
EXTRA_DIST += build-aux/extract-ofp-fields
lib/ofp-actions.inc1: $(srcdir)/build-aux/extract-ofp-actions lib/ofp-actions.c
$(AM_V_GEN)$(run_python) $^ --prototypes > $@.tmp && mv $@.tmp $@
$(AM_V_GEN)$(run_python) $< prototypes $(srcdir)/lib/ofp-actions.c > $@.tmp && mv $@.tmp $@
lib/ofp-actions.inc2: $(srcdir)/build-aux/extract-ofp-actions lib/ofp-actions.c
$(AM_V_GEN)$(run_python) $^ --definitions > $@.tmp && mv $@.tmp $@
$(AM_V_GEN)$(run_python) $< definitions $(srcdir)/lib/ofp-actions.c > $@.tmp && mv $@.tmp $@
lib/ofp-actions.lo: lib/ofp-actions.inc1 lib/ofp-actions.inc2
CLEANFILES += lib/ofp-actions.inc1 lib/ofp-actions.inc2
EXTRA_DIST += build-aux/extract-ofp-actions
@@ -601,3 +601,12 @@ lib/ovs-fields.7: $(srcdir)/build-aux/extract-ofp-fields include/openvswitch/met
$(srcdir)/lib/meta-flow.xml > $@.tmp
$(AM_V_at)mv $@.tmp $@
EXTRA_DIST += lib/meta-flow.xml
man_MANS += lib/ovs-actions.7
CLEANFILES += lib/ovs-actions.7
lib/ovs-actions.7: $(srcdir)/build-aux/extract-ofp-actions lib/ovs-actions.xml
$(AM_V_GEN)PYTHONIOENCODING=utf8 $(run_python) $< \
--ovs-version=$(VERSION) ovs-actions \
$(srcdir)/lib/ovs-actions.xml > $@.tmp
$(AM_V_at)mv $@.tmp $@
EXTRA_DIST += lib/ovs-actions.xml

View File

@@ -461,7 +461,7 @@ learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map,
}
/* Parses 'arg' as a set of arguments to the "learn" action and appends a
* matching OFPACT_LEARN action to 'ofpacts'. ovs-ofctl(8) describes the
* matching OFPACT_LEARN action to 'ofpacts'. ovs-actions(7) describes the
* format parsed.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
@@ -483,7 +483,7 @@ learn_parse(char *arg, const struct ofputil_port_map *port_map,
return error;
}
/* Appends a description of 'learn' to 's', in the format that ovs-ofctl(8)
/* Appends a description of 'learn' to 's', in the format that ovs-actions(7)
* describes. */
void
learn_format(const struct ofpact_learn *learn,

View File

@@ -136,7 +136,7 @@ multipath_algorithm(uint32_t hash, enum nx_mp_algorithm algorithm,
}
/* Parses 's_' as a set of arguments to the "multipath" action and initializes
* 'mp' accordingly. ovs-ofctl(8) describes the format parsed.
* 'mp' accordingly. ovs-actions(7) describes the format parsed.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string.*/
@@ -214,7 +214,7 @@ multipath_parse__(struct ofpact_multipath *mp, const char *s_, char *s)
}
/* Parses 's_' as a set of arguments to the "multipath" action and initializes
* 'mp' accordingly. ovs-ofctl(8) describes the format parsed.
* 'mp' accordingly. ovs-actions(7) describes the format parsed.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string. */
@@ -227,7 +227,7 @@ multipath_parse(struct ofpact_multipath *mp, const char *s_)
return error;
}
/* Appends a description of 'mp' to 's', in the format that ovs-ofctl(8)
/* Appends a description of 'mp' to 's', in the format that ovs-actions(7)
* describes. */
void
multipath_format(const struct ofpact_multipath *mp, struct ds *s)

View File

@@ -1745,7 +1745,7 @@ oxm_match_from_string(const char *s, struct ofpbuf *b)
return match_len;
}
/* Parses 's' as a "move" action, in the form described in ovs-ofctl(8), into
/* Parses 's' as a "move" action, in the form described in ovs-actions(7), into
* '*move'.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
@@ -1825,7 +1825,7 @@ nxm_reg_load(const struct mf_subfield *dst, uint64_t src_data,
/* nxm_parse_stack_action, works for both push() and pop(). */
/* Parses 's' as a "push" or "pop" action, in the form described in
* ovs-ofctl(8), into '*stack_action'.
* ovs-actions(7), into '*stack_action'.
*
* Returns NULL if successful, otherwise a malloc()'d string describing the
* error. The caller is responsible for freeing the returned string. */

2843
lib/ovs-actions.xml Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5526,7 +5526,7 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
<p>
With <em>flow-based sampling</em>, <code>sample</code> actions in the
OpenFlow flow table drive IPFIX sampling. See
<code>ovs-ofctl</code>(8) for a description of the
<code>ovs-actions</code>(7) for a description of the
<code>sample</code> action.
</p>