ovs learn action
2021-04-29 本文已影响0人
分享放大价值
本文主要记录下 learn action的操作,learn action用来动态添加openflow流表,包括匹配域,action和其他属性。
主要还是参考源码和ovs-action,也可参考官网的例子
learn action
Thelearnaction
Syntax:
learn(argument...)
The learn action adds or modifies a flow in an OpenFlow table,
similar to ovs-ofctl --strict mod-flows. The arguments specify
the match fields, actions, and other properties of the flow to be
added or modified.
learn的参数指定了匹配域,动作和其他流的属性。
Match fields for the new flow are specified as follows. At least
one match field should ordinarily be specified:
对于新添加的流表,匹配域按如下格式指定,field 是标准的字段,
可参考 https://man7.org/linux/man-pages/man7/ovs-fields.7.html
field = value, value为任意值
field=value
Specifies that field, in the new flow, must match
the literal value, e.g. dl_type=0x800. Shorthand
match syntax, such as ip in place of dl_type=0x800,
is not supported.
field=src,src为正常处理的报文中的字段
field=src
Specifies that field in the new flow must match src
taken from the packet currently being processed.
For example, udp_dst=udp_src, applied to a UDP
packet with source port 53, creates a flow which
matches udp_dst=53. field and src must have the
same width.
field 上面的格式,如果field和src相等,则可简写为field
field Shorthand for the previous form when field and src
are the same. For example, udp_dst, applied to a
UDP packet with destination port 53, creates a flow
which matches udp_dst=53.
The field and src arguments above should be fields or subfields
in the syntax described under ``Field Specifications’’ above.
Match field specifications must honor prerequisites for both the
flow with the learn and the new flow that it creates. Consider
the following complete flow, in the syntax accepted by ovs-ofctl.
If the flow’s match on udp were omitted, then the flow would not
satisfy the prerequisites for the learn action’s use of udp_src.
If dl_type=0x800 or nw_proto were omitted from learn, then the
new flow would not satisfy the prerequisite for its match on
udp_dst. For more information on prerequisites, please refer to
ovs-fields(7):
udp, actions=learn(dl_type=0x800, nw_proto=17, udp_dst=udp_src)
新流表的action按如下格式添加,至少指定一个action。
learn只支持给新流表添加两种action: load 和 output
Actions for the new flow are specified as follows. At least one
action should ordinarily be specified:
将任意值value加载进dst
load:value->dst
Adds a load action to the new flow that loads the
literal value into dst. The syntax is the same as
the load action explained in the ``Header
Modification’’ section.
将正在处理的报文的field或者子field,加载进dst
load:src->dst
Adds a load action to the new flow that loads src,
a field or subfield from the packet being
processed, into dst.
load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15])
output:field
Adds an output action to the new flow’s actions
that outputs to the OpenFlow port taken from field,
which must be a field as described above.
fin_idle_timeout=seconds
fin_hard_timeout=seconds
Adds a fin_timeout action with the specified
arguments to the new flow. This feature was added in
Open vSwitch 1.5.90.
还有下面额外的参数需要添加到flow
The following additional arguments are optional:
idle_timeout=seconds
hard_timeout=seconds
priority=value
cookie=value
send_flow_rem
These arguments have the same meaning as in the usual
flow syntax documented in ovs-ofctl(8).
table=table
The table in which the new flow should be inserted.
Specify a decimal number between 0 and 254 inclusive
or the name of a table. The default, if table is
unspecified, is table 1 (not 0).
delete_learned
When this flag is specified, deleting the flow that
contains the learn action will also delete the flows
created by learn. Specifically, when the last learn
action with this flag and particular table and cookie
values is removed, the switch deletes all of the
flows in the specified table with the specified
cookie.
This flag was added in Open vSwitch 2.4.
limit=number
If the number of flows in the new flow’s table with
the same cookie exceeds number, the action will not
add a new flow. By default, or with limit=0, there is
no limit.
This flag was added in Open vSwitch 2.8.
result_dst=field[bit]
If learn fails (because the number of flows exceeds
limit), the action sets field[bit] to 0, otherwise it
will be set to 1. field[bit] must be a single bit.
This flag was added in Open vSwitch 2.8.
learn只支持给新流表添加两种action: load 和 output
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 the ``Open vSwitch Advanced Features
Tutorial’’ in the OVS documentation.
• TCP state based firewalling, by learning outgoing
connections based on SYN packets and matching them
up with incoming packets. (This is usually better
implemented using the ct action.)
• At least some of the features described in T. A.
Hoff, ``Extending Open vSwitch to Facilitate
Creation of Stateful SDN Applications’’.
Conformance:
The learn action is an Open vSwitch extension to OpenFlow added
in Open vSwitch 1.3. Some features of learn were added in later
versions, as noted individually above.
命令行解析
#define NX_LEARN_SRC_FIELD (0 << 13) /* Copy from field. */ 表示源值为 field
#define NX_LEARN_SRC_IMMEDIATE (1 << 13) /* Copy from immediate value. */ 表示源值为立即数
#define NX_LEARN_DST_MATCH (0 << 11) /* Add match criterion. */ 表示添加匹配域
#define NX_LEARN_DST_LOAD (1 << 11) /* Add NXAST_REG_LOAD action. */ 表示添加load action
#define NX_LEARN_DST_OUTPUT (2 << 11) /* Add OFPAT_OUTPUT action. */ 表示添加 output action
/* Part of struct ofpact_learn, below. */
struct ofpact_learn_spec {
OFPACT_PADDED_MEMBERS(
struct mf_subfield src; /* NX_LEARN_SRC_FIELD only. */
struct mf_subfield dst; /* NX_LEARN_DST_MATCH,
* NX_LEARN_DST_LOAD only. */
uint16_t src_type; /* One of NX_LEARN_SRC_*. */
uint16_t dst_type; /* One of NX_LEARN_DST_*. */
uint8_t n_bits; /* Number of bits in source and dest. */
);
/* Followed by 'DIV_ROUND_UP(n_bits, 8)' bytes of immediate data for
* match 'dst_type's NX_LEARN_DST_MATCH and NX_LEARN_DST_LOAD when
* NX_LEARN_SRC_IMMEDIATE is set in 'src_type', followed by zeroes to align
* to OFPACT_ALIGNTO. */
};
struct ofpact_learn {
OFPACT_PADDED_MEMBERS(
struct ofpact ofpact;
uint16_t idle_timeout; /* Idle time before discarding (seconds). */
uint16_t hard_timeout; /* Max time before discarding (seconds). */
uint16_t priority; /* Priority level of flow entry. */
uint8_t table_id; /* Table to insert flow entry. */
enum nx_learn_flags flags; /* NX_LEARN_F_*. */
ovs_be64 cookie; /* Cookie for new flow. */
uint16_t fin_idle_timeout; /* Idle timeout after FIN, if nonzero. */
uint16_t fin_hard_timeout; /* Hard timeout after FIN, if nonzero. */
/* If the number of flows on 'table_id' with 'cookie' exceeds this,
* the action will not add a new flow. 0 indicates unlimited. */
uint32_t limit;
/* Used only if 'flags' has NX_LEARN_F_WRITE_RESULT. If the execution
* failed to install a new flow because 'limit' is exceeded,
* result_dst will be set to 0, otherwise to 1. */
struct mf_subfield result_dst;
);
struct ofpact_learn_spec specs[];
};
###命令行解析
static char * OVS_WARN_UNUSED_RESULT
parse_LEARN(char *arg, const struct ofputil_port_map *port_map,
struct ofpbuf *ofpacts,
enum ofputil_protocol *usable_protocols OVS_UNUSED)
{
return learn_parse(arg, port_map, ofpacts);
}
char * OVS_WARN_UNUSED_RESULT
learn_parse(char *arg, const struct ofputil_port_map *port_map,
struct ofpbuf *ofpacts)
{
char *orig = xstrdup(arg);
char *error = learn_parse__(orig, arg, port_map, ofpacts);
free(orig);
return error;
}
static char * OVS_WARN_UNUSED_RESULT
learn_parse__(char *orig, char *arg, const struct ofputil_port_map *port_map,
struct ofpbuf *ofpacts)
struct ofpact_learn *learn;
struct match match;
char *name, *value;
learn = ofpact_put_LEARN(ofpacts);
learn->idle_timeout = OFP_FLOW_PERMANENT;
learn->hard_timeout = OFP_FLOW_PERMANENT;
learn->priority = OFP_DEFAULT_PRIORITY;
learn->table_id = 1;
match_init_catchall(&match);
while (ofputil_parse_key_value(&arg, &name, &value)) {
if (!strcmp(name, "table")) {
learn->table_id = atoi(value);
if (learn->table_id == 255) {
return xasprintf("%s: table id 255 not valid for `learn' "
"action", orig);
}
} else
...
} else {
struct ofpact_learn_spec *spec;
char *error;
spec = ofpbuf_put_zeros(ofpacts, sizeof *spec);
error = learn_parse_spec(orig, name, value, port_map,
spec, ofpacts, &match);
if (error) {
return error;
}
learn = ofpacts->header;
}
}
static char * OVS_WARN_UNUSED_RESULT
learn_parse_spec(const char *orig, char *name, char *value,
const struct ofputil_port_map *port_map,
struct ofpact_learn_spec *spec,
struct ofpbuf *ofpacts, struct match *match)
/* Parse destination and check prerequisites. */
struct mf_subfield dst;
char *error = mf_parse_subfield(&dst, name);
bool parse_error = error != NULL;
free(error);
//只要parse_error为空,说明根据name查找到了field, 说明这是一个匹配域。action只会以 load 或者 output 开始
if (!parse_error) {
//load action
} else if (!strcmp(name, "load")) {
//output action
} else if (!strcmp(name, "output")) {
}
ovs-vswitchd端通过 xlate_learn_action 来生成流表,并添加到指定table中。
参考
https://docs.openvswitch.org/en/latest/tutorials/ovs-advanced/
https://man7.org/linux/man-pages/man7/ovs-actions.7.html
https://man7.org/linux/man-pages/man7/ovs-fields.7.html