@@ -81,6 +81,12 @@ lflow_init(void)
expr_symtab_add_field(&symtab, "xxreg0", MFF_XXREG0, NULL, false);
expr_symtab_add_field(&symtab, "xxreg1", MFF_XXREG1, NULL, false);
+ /* Flags used in logical to physical transformation. */
+ expr_symtab_add_field(&symtab, "flags", MFF_LOG_FLAGS, NULL, false);
+ char flags_str[16];
+ snprintf(flags_str, sizeof flags_str, "flags[%d]", MLF_ALLOW_LOOPBACK_BIT);
+ expr_symtab_add_subfield(&symtab, "flags.loopback", NULL, flags_str);
+
/* Connection tracking state. */
expr_symtab_add_field(&symtab, "ct_mark", MFF_CT_MARK, NULL, false);
expr_symtab_add_field(&symtab, "ct_label", MFF_CT_LABEL, NULL, false);
@@ -494,7 +500,7 @@ consider_logical_flow(const struct lport_index *lports,
uint8_t ptable = first_ptable + lflow->table_id;
uint8_t output_ptable = (ingress
? OFTABLE_REMOTE_OUTPUT
- : OFTABLE_LOG_TO_PHY);
+ : OFTABLE_SAVE_INPORT);
/* Translate OVN actions into OpenFlow actions.
*
@@ -51,10 +51,11 @@ struct uuid;
#define OFTABLE_LOG_INGRESS_PIPELINE 16 /* First of LOG_PIPELINE_LEN tables. */
#define OFTABLE_REMOTE_OUTPUT 32
#define OFTABLE_LOCAL_OUTPUT 33
-#define OFTABLE_DROP_LOOPBACK 34
+#define OFTABLE_CHECK_LOOPBACK 34
#define OFTABLE_LOG_EGRESS_PIPELINE 48 /* First of LOG_PIPELINE_LEN tables. */
-#define OFTABLE_LOG_TO_PHY 64
-#define OFTABLE_MAC_BINDING 65
+#define OFTABLE_SAVE_INPORT 64
+#define OFTABLE_LOG_TO_PHY 65
+#define OFTABLE_MAC_BINDING 66
/* The number of tables for the ingress and egress pipelines. */
#define LOG_PIPELINE_LEN 16
@@ -375,25 +375,49 @@ consider_port_binding(enum mf_field_id mff_ovn_geneve,
}
/* Resubmit to table 34. */
- put_resubmit(OFTABLE_DROP_LOOPBACK, ofpacts_p);
+ put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p);
ofctrl_add_flow(OFTABLE_LOCAL_OUTPUT, 100,
&match, ofpacts_p, &binding->header_.uuid);
/* Table 34, Priority 100.
* =======================
*
- * Drop packets whose logical inport and outport are the same. */
+ * Drop packets whose logical inport and outport are the same
+ * and the MLF_ALLOW_LOOPBACK flag is not set. */
match_init_catchall(&match);
ofpbuf_clear(ofpacts_p);
match_set_metadata(&match, htonll(dp_key));
+ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0,
+ 0, MLF_ALLOW_LOOPBACK);
match_set_reg(&match, MFF_LOG_INPORT - MFF_REG0, port_key);
match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
- ofctrl_add_flow(OFTABLE_DROP_LOOPBACK, 100,
+ ofctrl_add_flow(OFTABLE_CHECK_LOOPBACK, 100,
&match, ofpacts_p, &binding->header_.uuid);
/* Table 64, Priority 100.
* =======================
*
+ * If the packet is supposed to hair-pin because the "loopback"
+ * flag is set, temporarily set the in_port to zero, resubmit to
+ * table 65 for logical-to-physical translation, then restore
+ * the port number. */
+ match_init_catchall(&match);
+ ofpbuf_clear(ofpacts_p);
+ match_set_metadata(&match, htonll(dp_key));
+ match_set_reg_masked(&match, MFF_LOG_FLAGS - MFF_REG0,
+ MLF_ALLOW_LOOPBACK, MLF_ALLOW_LOOPBACK);
+ match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key);
+
+ put_stack(MFF_IN_PORT, ofpact_put_STACK_PUSH(ofpacts_p));
+ put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p);
+ put_resubmit(OFTABLE_LOG_TO_PHY, ofpacts_p);
+ put_stack(MFF_IN_PORT, ofpact_put_STACK_POP(ofpacts_p));
+ ofctrl_add_flow(OFTABLE_SAVE_INPORT, 100,
+ &match, ofpacts_p, &binding->header_.uuid);
+
+ /* Table 65, Priority 100.
+ * =======================
+ *
* Deliver the packet to the local vif. */
match_init_catchall(&match);
ofpbuf_clear(ofpacts_p);
@@ -523,12 +547,12 @@ consider_mc_group(enum mf_field_id mff_ovn_geneve,
if (!strcmp(port->type, "patch")) {
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32,
remote_ofpacts_p);
- put_resubmit(OFTABLE_DROP_LOOPBACK, remote_ofpacts_p);
+ put_resubmit(OFTABLE_CHECK_LOOPBACK, remote_ofpacts_p);
} else if (simap_contains(&localvif_to_ofport,
(port->parent_port && *port->parent_port)
? port->parent_port : port->logical_port)) {
put_load(port->tunnel_key, MFF_LOG_OUTPORT, 0, 32, ofpacts_p);
- put_resubmit(OFTABLE_DROP_LOOPBACK, ofpacts_p);
+ put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p);
} else if (port->chassis && !get_localnet_port(local_datapaths,
mc->datapath->tunnel_key)) {
/* Add remote chassis only when localnet port not exist,
@@ -888,7 +912,17 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve,
MFF_LOG_REGS;
#undef MFF_LOG_REGS
put_resubmit(OFTABLE_LOG_EGRESS_PIPELINE, &ofpacts);
- ofctrl_add_flow(OFTABLE_DROP_LOOPBACK, 0, &match, &ofpacts, hc_uuid);
+ ofctrl_add_flow(OFTABLE_CHECK_LOOPBACK, 0, &match, &ofpacts, hc_uuid);
+
+ /* Table 64, Priority 0.
+ * =======================
+ *
+ * Resubmit packets that do not have the MLF_ALLOW_LOOPBACK flag set
+ * to table 65 for logical-to-physical translation. */
+ match_init_catchall(&match);
+ ofpbuf_clear(&ofpacts);
+ put_resubmit(OFTABLE_LOG_TO_PHY, &ofpacts);
+ ofctrl_add_flow(OFTABLE_SAVE_INPORT, 0, &match, &ofpacts, hc_uuid);
ofpbuf_uninit(&ofpacts);
@@ -2872,16 +2872,6 @@ parse_assignment(struct lexer *lexer, struct expr_field *dst,
bitwise_put(port, &sf->value,
sf->field->n_bytes, 0, sf->field->n_bits);
bitwise_one(&sf->mask, sf->field->n_bytes, 0, sf->field->n_bits);
-
- /* If the logical input port is being zeroed, clear the OpenFlow
- * ingress port also, to allow a packet to be sent back to its
- * origin. */
- if (!port && sf->field->id == MFF_LOG_INPORT) {
- sf = ofpact_put_SET_FIELD(ofpacts);
- sf->field = mf_from_id(MFF_IN_PORT);
- bitwise_one(&sf->mask,
- sf->field->n_bytes, 0, sf->field->n_bits);
- }
}
exit_destroy_cs:
@@ -18,11 +18,21 @@
#include "openvswitch/meta-flow.h"
+enum {
+ MLF_ALLOW_LOOPBACK_BIT = 0
+};
+
+enum {
+ MLF_ALLOW_LOOPBACK = (1 << MLF_ALLOW_LOOPBACK_BIT) /* Allow outputting
+ back to inport. */
+};
+
/* Logical fields.
*
* These values are documented in ovn-architecture(7), please update the
* documentation if you change any of them. */
#define MFF_LOG_DATAPATH MFF_METADATA /* Logical datapath (64 bits). */
+#define MFF_LOG_FLAGS MFF_REG10 /* One of MLF_* (32 bits). */
#define MFF_LOG_DNAT_ZONE MFF_REG11 /* conntrack dnat zone for gateway router
* (32 bits). */
#define MFF_LOG_SNAT_ZONE MFF_REG12 /* conntrack snat zone for gateway router
@@ -441,7 +441,7 @@ arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = inport;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
output;
</pre>
@@ -467,7 +467,7 @@ nd_na {
nd.target = <var>A</var>;
nd.tll = <var>E</var>;
outport = inport;
- inport = ""; /* Allow sending out inport. */
+ flags.loopback = 1;
output;
};
</pre>
@@ -546,7 +546,7 @@ ip4.src = <var>S</var>;
udp.src = 67;
udp.dst = 68;
outport = <var>P</var>;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
output;
</pre>
@@ -772,7 +772,7 @@ output;
ip4.dst <-> ip4.src;
ip.ttl = 255;
icmp4.type = 0;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
next;
</pre>
@@ -784,7 +784,7 @@ next;
ip6.dst <-> ip6.src;
ip.ttl = 255;
icmp6.type = 129;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
next;
</pre>
</li>
@@ -812,7 +812,7 @@ arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
output;
</pre>
</li>
@@ -837,7 +837,7 @@ arp.sha = <var>E</var>;
arp.tpa = arp.spa;
arp.spa = <var>A</var>;
outport = <var>P</var>;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
output;
</pre>
</li>
@@ -872,7 +872,7 @@ nd_na {
nd.target = <var>A</var>;
nd.tll = <var>E</var>;
outport = inport;
- inport = \"\"; /* Allow sending out inport. */
+ flags.loopback = 1;
output;
};
</pre>
@@ -1032,13 +1032,13 @@ icmp4 {
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>.
+ ip4.dst == <var>A</var></code> with an action
+ <code>flags.loopback = 1; 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>.
+ action <code>flags.loopback = 1; ct_dnat;</code>.
</p>
<p>
@@ -1084,7 +1084,7 @@ reg0 = <var>G</var>;
reg1 = <var>A</var>;
eth.src = <var>E</var>;
outport = <var>P</var>;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
next;
</pre>
@@ -1117,7 +1117,7 @@ xxreg0 = <var>G</var>;
xxreg1 = <var>A</var>;
eth.src = <var>E</var>;
outport = <var>P</var>;
-inport = ""; /* Allow sending out inport. */
+flags.loopback = 1;
next;
</pre>
@@ -1802,8 +1802,8 @@ build_dhcpv4_action(struct ovn_port *op, ovs_be32 offer_ip,
ds_put_format(response_action, "eth.dst = eth.src; eth.src = %s; "
"ip4.dst = "IP_FMT"; ip4.src = %s; udp.src = 67; "
- "udp.dst = 68; outport = inport; inport = \"\";"
- " /* Allow sending out inport. */ output;",
+ "udp.dst = 68; outport = inport; flags.loopback = 1; "
+ "output;",
server_mac, IP_ARGS(offer_ip), server_ip);
smap_destroy(&dhcpv4_options);
@@ -2470,7 +2470,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
"arp.tpa = arp.spa; "
"arp.spa = %s; "
"outport = inport; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"output;",
op->lsp_addrs[i].ea_s, op->lsp_addrs[i].ea_s,
op->lsp_addrs[i].ipv4_addrs[j].addr_s);
@@ -2497,7 +2497,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
"nd.target = %s; "
"nd.tll = %s; "
"outport = inport; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"output; "
"};",
op->lsp_addrs[i].ea_s,
@@ -2793,7 +2793,7 @@ add_route(struct hmap *lflows, const struct ovn_port *op,
"%sreg1 = %s; "
"eth.src = %s; "
"outport = %s; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"next;",
is_ipv4 ? "" : "xx",
lrp_addr_s,
@@ -3074,7 +3074,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"ip4.dst <-> ip4.src; "
"ip.ttl = 255; "
"icmp4.type = 0; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"next; ");
ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
ds_cstr(&match), ds_cstr(&actions));
@@ -3098,7 +3098,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"arp.tpa = arp.spa; "
"arp.spa = %s; "
"outport = %s; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"output;",
op->lrp_networks.ea_s,
op->lrp_networks.ea_s,
@@ -3147,7 +3147,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"arp.tpa = arp.spa; "
"arp.spa = "IP_FMT"; "
"outport = %s; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"output;",
op->lrp_networks.ea_s,
op->lrp_networks.ea_s,
@@ -3216,7 +3216,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"ip6.dst <-> ip6.src; "
"ip.ttl = 255; "
"icmp6.type = 129; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"next; ");
ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
ds_cstr(&match), ds_cstr(&actions));
@@ -3249,7 +3249,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"nd.target = %s; "
"nd.tll = %s; "
"outport = inport; "
- "inport = \"\"; /* Allow sending out inport. */ "
+ "flags.loopback = 1; "
"output; "
"};",
op->lrp_networks.ea_s,
@@ -3345,7 +3345,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_clear(&match);
ds_put_format(&match, "ip && ip4.dst == %s", nat->external_ip);
ds_clear(&actions);
- ds_put_format(&actions,"inport = \"\"; ct_dnat(%s);",
+ ds_put_format(&actions,"flags.loopback = 1; ct_dnat(%s);",
nat->logical_ip);
ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100,
ds_cstr(&match), ds_cstr(&actions));
@@ -3385,7 +3385,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
* back the new destination IP address that is needed for
* routing in the openflow pipeline. */
ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50,
- "ip", "inport = \"\"; ct_dnat;");
+ "ip", "flags.loopback = 1; ct_dnat;");
}
/* Logical router ingress table 4: IP Routing.
@@ -768,6 +768,15 @@
Open vSwitch extension register number 12.
</dd>
+ <dt>logical flow flags</dt>
+ <dd>
+ A field used to store flags to be used when transforming logical
+ <!-- Keep the following in sync with MFF_LOG_FLAGS in
+ ovn/lib/logical-fields.h. -->
+ flows into physical flows. OVN stores this in Open vSwitch
+ extension register number 10.
+ </dd>
+
<dt>VLAN ID</dt>
<dd>
The VLAN ID is used as an interface between OVN and containers nested
@@ -851,10 +860,10 @@
<dd>
<p>
Implemented by storing arguments into OpenFlow fields, then
- resubmitting to table 65, which <code>ovn-controller</code>
+ resubmitting to table 66, which <code>ovn-controller</code>
populates with flows generated from the <code>MAC_Binding</code>
table in the OVN Southbound database. If there is a match in table
- 65, then its actions store the bound MAC in the Ethernet
+ 66, then its actions store the bound MAC in the Ethernet
destination address field.
</p>
@@ -887,8 +896,8 @@
OpenFlow tables 32 through 47 implement the <code>output</code> action
in the logical ingress pipeline. Specifically, table 32 handles
packets to remote hypervisors, table 33 handles packets to the local
- hypervisor, and table 34 discards packets whose logical ingress and
- egress port are the same.
+ hypervisor, and table 34 checks whether packets whose logical ingress
+ and egress port are the same should be discarded.
</p>
<p>
@@ -941,7 +950,8 @@
<p>
Table 34 matches and drops packets for which the logical input and
- output ports are the same. It resubmits other packets to table 48.
+ output ports are the same and the MLF_ALLOW_LOOPBACK flag is not
+ set. It resubmits other packets to table 48.
</p>
</li>
@@ -965,7 +975,19 @@
<li>
<p>
- OpenFlow table 64 performs logical-to-physical translation, the
+ OpenFlow table 64 is responsible for saving the ingress logical
+ port when the MLF_ALLOW_LOOPBACK flag is set. If this is not
+ done, Open vSwitch will not forward the packet when the egress
+ port is the same as the ingress port. A flow is added that
+ matches on the "allow loopback" flag with actions that push the
+ ingress logical port onto the stack, resubmit to table 65 for
+ logical-to-physical transformation, and then pop the logical
+ ingress port back from the stack. If the flag is not set, the
+ flow simply resubmits to table 65.
+ </p>
+
+ <p>
+ OpenFlow table 65 performs logical-to-physical translation, the
opposite of table 0. It matches the packet's logical egress port. Its
actions output the packet to the port attached to the OVN integration
bridge that represents that logical port. If the logical egress port
@@ -974,7 +996,7 @@
</p>
<p>
- If the logical egress port is a logical patch port, then table 64
+ If the logical egress port is a logical patch port, then table 65
outputs to an OVS patch port that represents the logical patch port.
The packet re-enters the OpenFlow flow table from the OVS patch port's
peer in table 0, which identifies the logical datapath and logical
@@ -375,13 +375,13 @@
depends on the current value of the <code>outport</code> field. Suppose
<code>outport</code> designates a logical port. First, OVN compares
<code>inport</code> to <code>outport</code>; if they are equal, it treats
- the <code>output</code> as a no-op. 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. <code>reg0</code> ...
- <code>reg9</code> 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).
+ the <code>output</code> 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. <code>reg0</code> ... <code>reg9</code> 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).
</p>
<p>
@@ -787,6 +787,7 @@
<li><code>reg0</code>...<code>reg9</code></li>
<li><code>xxreg0</code> <code>xxreg1</code></li>
<li><code>inport</code> <code>outport</code></li>
+ <li><code>flags.loopback</code></li>
<li><code>eth.src</code> <code>eth.dst</code> <code>eth.type</code></li>
<li><code>vlan.tci</code> <code>vlan.vid</code> <code>vlan.pcp</code> <code>vlan.present</code></li>
<li><code>ip.proto</code> <code>ip.dscp</code> <code>ip.ecn</code> <code>ip.ttl</code> <code>ip.frag</code></li>
@@ -883,13 +884,13 @@
</p>
<p>
- Output to the input port is implicitly dropped, that is,
- <code>output</code> becomes a no-op if <code>outport</code> ==
- <code>inport</code>. Occasionally it may be useful to override
- this behavior, e.g. to send an ARP reply to an ARP request; to do
- so, use <code>inport = "";</code> to set the logical input port to
- an empty string (which should not be used as the name of any
- logical port).
+ By default, output to the input port is implicitly dropped,
+ that is, <code>output</code> becomes a no-op if
+ <code>outport</code> == <code>inport</code>. Occasionally
+ it may be useful to override this behavior, e.g. to send an
+ ARP reply to an ARP request; to do so, use
+ <code>flags.loopback = 1</code> to allow the packet to
+ "hair-pin" back to the input port.
</p>
</dd>
@@ -568,7 +568,7 @@ tcp.dst=80; => actions=set_field:80->tcp_dst, prereqs=ip.proto == 0x6 && (eth.ty
eth.dst[40] = 1; => actions=set_field:01:00:00:00:00:00/01:00:00:00:00:00->eth_dst, prereqs=1
vlan.pcp = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=vlan.tci[12]
vlan.tci[13..15] = 2; => actions=set_field:0x4000/0xe000->vlan_tci, prereqs=1
-inport = ""; => actions=set_field:0->reg14,set_field:0->in_port, prereqs=1
+inport = ""; => actions=set_field:0->reg14, prereqs=1
ip.ttl = 4; => actions=set_field:4->nw_ttl, prereqs=eth.type == 0x800 || eth.type == 0x86dd
outport="eth0"; next; outport="LOCAL"; next; => actions=set_field:0x5->reg15,resubmit(,27),set_field:0xfffe->reg15,resubmit(,27), prereqs=1
@@ -697,7 +697,7 @@ reg1[0] = put_dhcp_opts(offerip="xyzzy"); => DHCP option offerip requires numeri
reg1[0] = put_dhcp_opts(offerip=1.2.3.4, domain=1.2.3.4); => DHCP option domain requires string value.
# nd_na
-nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; }; => actions=controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.00.19.00.10.00.00.00.02.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00), prereqs=nd_ns
+nd_na { eth.src = 12:34:56:78:9a:bc; nd.tll = 12:34:56:78:9a:bc; outport = inport; inport = ""; /* Allow sending out inport. */ output; }; => actions=controller(userdata=00.00.00.03.00.00.00.00.00.19.00.10.80.00.08.06.12.34.56.78.9a.bc.00.00.00.19.00.10.80.00.42.06.12.34.56.78.9a.bc.00.00.ff.ff.00.18.00.00.23.20.00.06.00.20.00.00.00.00.00.01.1c.04.00.01.1e.04.00.19.00.10.00.01.1c.04.00.00.00.00.00.00.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00), prereqs=nd_ns
# Contradictionary prerequisites (allowed but not useful):
ip4.src = ip6.src[0..31]; => actions=move:NXM_NX_IPV6_SRC[0..31]->NXM_OF_IP_SRC[], prereqs=eth.type == 0x800 && eth.type == 0x86dd
Introduce the "flags.loopback" symbol to allow packets to be sent back on their ingress ports. Previously, one needed to clear "inport" to hair-pin packets, but this made "inport" not available for future matching. This approach should be more intuitive, but it will also be needed in future patches. This patch also removes functionality from the OVN expression library that clears the OpenFlow ingress port when the logical input port is zeroed. Signed-off-by: Justin Pettit <jpettit@ovn.org> --- ovn/controller/lflow.c | 8 +++++++- ovn/controller/lflow.h | 7 ++++--- ovn/controller/physical.c | 46 +++++++++++++++++++++++++++++++++++++++------ ovn/lib/expr.c | 10 ---------- ovn/lib/logical-fields.h | 10 ++++++++++ ovn/northd/ovn-northd.8.xml | 26 ++++++++++++------------- ovn/northd/ovn-northd.c | 24 +++++++++++------------ ovn/ovn-architecture.7.xml | 36 ++++++++++++++++++++++++++++------- ovn/ovn-sb.xml | 29 ++++++++++++++-------------- tests/ovn.at | 4 ++-- 10 files changed, 132 insertions(+), 68 deletions(-)