Until now the 'stage-hint' external-id was set only for logical flows
installed for ACLs. In order to simplify troubleshooting, extend the
approach and apply whenever possible. Set stage-hint for logical flows
generated by the following NB tables too:
- DHCP_Options
- Logical_Switch_Port
- Logical_Router_Port
- Logical_Router_Policy
- Logical_Router_Static_Route
- Load_Balancer
- NAT
- QoS
Also update ovn-detrace such that whenever stage-hints are available,
all the tables mentioned above are queried and if the stage-hint matches
a NB uuid, relevant information is dumped.
Signed-off-by: Dumitru Ceara <[email protected]>
---
v2:
- Address Mark's comments and add ovn-detrace support for DHCP_Options,
QoS, Logical_Router_Policy.
- Rebase.
---
northd/ovn-northd.c | 722 +++++++++++++++++++++++++++++------------------
utilities/ovn-detrace.in | 123 ++++++--
2 files changed, 555 insertions(+), 290 deletions(-)
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 2ce4f5d..cc614f9 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -3798,6 +3798,15 @@ ovn_lflow_hash(const struct ovn_lflow *lflow)
lflow->actions);
}
+static char *
+ovn_lflow_hint(const struct ovsdb_idl_row *row)
+{
+ if (!row) {
+ return NULL;
+ }
+ return xasprintf("%08x", row->uuid.parts[0]);
+}
+
static bool
ovn_lflow_equal(const struct ovn_lflow *a, const struct ovn_lflow *b)
{
@@ -3828,14 +3837,14 @@ static void
ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od,
enum ovn_stage stage, uint16_t priority,
const char *match, const char *actions,
- const char *stage_hint, const char *where)
+ const struct ovsdb_idl_row *stage_hint, const char *where)
{
ovs_assert(ovn_stage_to_datapath_type(stage) ==
ovn_datapath_get_type(od));
struct ovn_lflow *lflow = xmalloc(sizeof *lflow);
ovn_lflow_init(lflow, od, stage, priority,
xstrdup(match), xstrdup(actions),
- nullable_xstrdup(stage_hint), where);
+ ovn_lflow_hint(stage_hint), where);
hmap_insert(lflow_map, &lflow->hmap_node, ovn_lflow_hash(lflow));
}
@@ -3986,7 +3995,8 @@ build_port_security_ipv6_flow(
* - Priority 80 flow to drop ARP and IPv6 ND packets.
*/
static void
-build_port_security_nd(struct ovn_port *op, struct hmap *lflows)
+build_port_security_nd(struct ovn_port *op, struct hmap *lflows,
+ const struct ovsdb_idl_row *stage_hint)
{
struct ds match = DS_EMPTY_INITIALIZER;
@@ -4022,8 +4032,8 @@ build_port_security_nd(struct ovn_port *op, struct hmap *lflows)
ds_chomp(&match, ',');
ds_put_cstr(&match, "}");
}
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 90,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND,
+ 90, ds_cstr(&match), "next;", stage_hint);
}
if (ps->n_ipv6_addrs || no_ip) {
@@ -4032,15 +4042,15 @@ build_port_security_nd(struct ovn_port *op, struct hmap
*lflows)
op->json_key, ps->ea_s);
build_port_security_ipv6_nd_flow(&match, ps->ea, ps->ipv6_addrs,
ps->n_ipv6_addrs);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 90,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND,
+ 90, ds_cstr(&match), "next;", stage_hint);
}
}
ds_clear(&match);
ds_put_format(&match, "inport == %s && (arp || nd)", op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 80,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 80,
+ ds_cstr(&match), "drop;", stage_hint);
ds_destroy(&match);
}
@@ -4061,7 +4071,8 @@ build_port_security_nd(struct ovn_port *op, struct hmap *lflows)
*/
static void
build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op,
- struct hmap *lflows)
+ struct hmap *lflows,
+ const struct ovsdb_idl_row *stage_hint)
{
char *port_direction;
enum ovn_stage stage;
@@ -4091,8 +4102,9 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct
ovn_port *op,
" && ip4.dst == 255.255.255.255"
" && udp.src == 68 && udp.dst == 67",
op->json_key, ps->ea_s);
- ovn_lflow_add(lflows, op->od, stage, 90,
- ds_cstr(&dhcp_match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, stage, 90,
+ ds_cstr(&dhcp_match), "next;",
+ stage_hint);
ds_destroy(&dhcp_match);
ds_put_format(&match, "inport == %s && eth.src == %s"
" && ip4.src == {", op->json_key,
@@ -4131,7 +4143,9 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct
ovn_port *op,
ds_chomp(&match, ' ');
ds_chomp(&match, ',');
ds_put_cstr(&match, "}");
- ovn_lflow_add(lflows, op->od, stage, 90, ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, stage, 90,
+ ds_cstr(&match), "next;",
+ stage_hint);
ds_destroy(&match);
}
@@ -4147,8 +4161,9 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op,
" && ip6.dst == ff02::/16"
" && icmp6.type == {131, 135, 143}",
op->json_key,
ps->ea_s);
- ovn_lflow_add(lflows, op->od, stage, 90,
- ds_cstr(&dad_match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, stage, 90,
+ ds_cstr(&dad_match), "next;",
+ stage_hint);
ds_destroy(&dad_match);
}
ds_put_format(&match, "%s == %s && %s == %s",
@@ -4156,8 +4171,9 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct
ovn_port *op,
pipeline == P_IN ? "eth.src" : "eth.dst", ps->ea_s);
build_port_security_ipv6_flow(pipeline, &match, ps->ea,
ps->ipv6_addrs, ps->n_ipv6_addrs);
- ovn_lflow_add(lflows, op->od, stage, 90,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, stage, 90,
+ ds_cstr(&match), "next;",
+ stage_hint);
ds_destroy(&match);
}
@@ -4165,7 +4181,8 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op,
port_direction, op->json_key,
pipeline == P_IN ? "eth.src" : "eth.dst",
ps->ea_s);
- ovn_lflow_add(lflows, op->od, stage, 80, match, "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od, stage, 80, match, "drop;",
+ stage_hint);
free(match);
}
@@ -4455,12 +4472,13 @@ build_lswitch_input_port_sec(struct hmap *ports, struct hmap *datapaths,
ds_put_format(&actions, "set_queue(%s); ", queue_id);
}
ds_put_cstr(&actions, "next;");
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbsp->header_);
if (op->nbsp->n_port_security) {
- build_port_security_ip(P_IN, op, lflows);
- build_port_security_nd(op, lflows);
+ build_port_security_ip(P_IN, op, lflows, &op->nbsp->header_);
+ build_port_security_nd(op, lflows, &op->nbsp->header_);
}
}
@@ -4520,15 +4538,17 @@ build_lswitch_output_port_sec(struct hmap *ports, struct hmap *datapaths,
}
}
ds_put_cstr(&actions, "output;");
- ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2,
+ 50, ds_cstr(&match), ds_cstr(&actions),
+ &op->nbsp->header_);
} else {
- ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, 150,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2,
+ 150, ds_cstr(&match), "drop;",
+ &op->nbsp->header_);
}
if (op->nbsp->n_port_security) {
- build_port_security_ip(P_OUT, op, lflows);
+ build_port_security_ip(P_OUT, op, lflows, &op->nbsp->header_);
}
}
@@ -4583,10 +4603,12 @@ build_pre_acls(struct ovn_datapath *od, struct hmap *lflows)
ds_put_format(&match_in, "ip && inport == %s", op->json_key);
ds_put_format(&match_out, "ip && outport == %s", op->json_key);
- ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110,
- ds_cstr(&match_in), "next;");
- ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
- ds_cstr(&match_out), "next;");
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_ACL, 110,
+ ds_cstr(&match_in), "next;",
+ &op->nbsp->header_);
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
+ ds_cstr(&match_out), "next;",
+ &op->nbsp->header_);
ds_destroy(&match_in);
ds_destroy(&match_out);
@@ -4599,10 +4621,12 @@ build_pre_acls(struct ovn_datapath *od, struct hmap
*lflows)
od->localnet_port->json_key);
ds_put_format(&match_out, "ip && outport == %s",
od->localnet_port->json_key);
- ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_ACL, 110,
- ds_cstr(&match_in), "next;");
- ovn_lflow_add(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
- ds_cstr(&match_out), "next;");
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_ACL, 110,
+ ds_cstr(&match_in), "next;",
+ &od->localnet_port->nbsp->header_);
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_OUT_PRE_ACL, 110,
+ ds_cstr(&match_out), "next;",
+ &od->localnet_port->nbsp->header_);
ds_destroy(&match_in);
ds_destroy(&match_out);
@@ -4711,7 +4735,8 @@ build_empty_lb_event_flow(struct ovn_datapath *od, struct
hmap *lflows,
event_to_string(OVN_EVENT_EMPTY_LB_BACKENDS),
meter, vip, lb->protocol,
UUID_ARGS(&lb->header_.uuid));
- ovn_lflow_add(lflows, od, pl, 130, ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, od, pl, 130, ds_cstr(&match), action,
+ &lb->header_);
ds_destroy(&match);
if (lb_vip->vip_port) {
free(vip);
@@ -4853,7 +4878,8 @@ build_acl_log(struct ds *actions, const struct nbrec_acl
*acl)
static void
build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows,
enum ovn_stage stage, struct nbrec_acl *acl,
- struct ds *extra_match, struct ds *extra_actions)
+ struct ds *extra_match, struct ds *extra_actions,
+ const struct ovsdb_idl_row *stage_hint)
{
struct ds match = DS_EMPTY_INITIALIZER;
struct ds actions = DS_EMPTY_INITIALIZER;
@@ -4869,8 +4895,9 @@ build_reject_acl_rules(struct ovn_datapath *od, struct
hmap *lflows,
"eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
"tcp_reset { outport <-> inport; %s };",
ingress ? "output;" : "next(pipeline=ingress,table=0);");
- ovn_lflow_add(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET + 10,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET + 10,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
ds_clear(&match);
ds_clear(&actions);
build_acl_log(&actions, acl);
@@ -4882,8 +4909,9 @@ build_reject_acl_rules(struct ovn_datapath *od, struct
hmap *lflows,
"eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
"tcp_reset { outport <-> inport; %s };",
ingress ? "output;" : "next(pipeline=ingress,table=0);");
- ovn_lflow_add(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET + 10,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET + 10,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
/* IP traffic */
ds_clear(&match);
@@ -4900,8 +4928,9 @@ build_reject_acl_rules(struct ovn_datapath *od, struct
hmap *lflows,
"eth.dst <-> eth.src; ip4.dst <-> ip4.src; "
"icmp4 { outport <-> inport; %s };",
ingress ? "output;" : "next(pipeline=ingress,table=0);");
- ovn_lflow_add(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
ds_clear(&match);
ds_clear(&actions);
build_acl_log(&actions, acl);
@@ -4916,8 +4945,9 @@ build_reject_acl_rules(struct ovn_datapath *od, struct
hmap *lflows,
"eth.dst <-> eth.src; ip6.dst <-> ip6.src; "
"outport <-> inport; %s };",
ingress ? "output;" : "next(pipeline=ingress,table=0);");
- ovn_lflow_add(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
ds_destroy(&match);
ds_destroy(&actions);
@@ -4930,7 +4960,6 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
bool ingress = !strcmp(acl->direction, "from-lport") ? true :false;
enum ovn_stage stage = ingress ? S_SWITCH_IN_ACL : S_SWITCH_OUT_ACL;
- char *stage_hint = xasprintf("%08x", acl->header_.uuid.parts[0]);
if (!strcmp(acl->action, "allow")
|| !strcmp(acl->action, "allow-related")) {
/* If there are any stateful flows, we must even commit "allow"
@@ -4945,7 +4974,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
ovn_lflow_add_with_hint(lflows, od, stage,
acl->priority + OVN_ACL_PRI_OFFSET,
acl->match, ds_cstr(&actions),
- stage_hint);
+ &acl->header_);
ds_destroy(&actions);
} else {
struct ds match = DS_EMPTY_INITIALIZER;
@@ -4974,7 +5003,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
acl->priority + OVN_ACL_PRI_OFFSET,
ds_cstr(&match),
ds_cstr(&actions),
- stage_hint);
+ &acl->header_);
/* Match on traffic in the request direction for an established
* connection tracking entry that has not been marked for
@@ -4994,7 +5023,7 @@ consider_acl(struct hmap *lflows, struct ovn_datapath *od,
ovn_lflow_add_with_hint(lflows, od, stage,
acl->priority + OVN_ACL_PRI_OFFSET,
ds_cstr(&match), ds_cstr(&actions),
- stage_hint);
+ &acl->header_);
ds_destroy(&match);
ds_destroy(&actions);
@@ -5016,14 +5045,15 @@ consider_acl(struct hmap *lflows, struct ovn_datapath
*od,
" || (ct.est && ct_label.blocked == 1))");
if (!strcmp(acl->action, "reject")) {
build_reject_acl_rules(od, lflows, stage, acl, &match,
- &actions);
+ &actions, &acl->header_);
} else {
ds_put_format(&match, " && (%s)", acl->match);
build_acl_log(&actions, acl);
ds_put_cstr(&actions, "/* drop */");
- ovn_lflow_add(lflows, od, stage,
- acl->priority + OVN_ACL_PRI_OFFSET,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ ds_cstr(&match), ds_cstr(&actions),
+ &acl->header_);
}
/* For an existing connection without ct_label set, we've
* encountered a policy change. ACLs previously allowed
@@ -5042,14 +5072,15 @@ consider_acl(struct hmap *lflows, struct ovn_datapath
*od,
ds_put_cstr(&actions, "ct_commit(ct_label=1/1); ");
if (!strcmp(acl->action, "reject")) {
build_reject_acl_rules(od, lflows, stage, acl, &match,
- &actions);
+ &actions, &acl->header_);
} else {
ds_put_format(&match, " && (%s)", acl->match);
build_acl_log(&actions, acl);
ds_put_cstr(&actions, "/* drop */");
- ovn_lflow_add(lflows, od, stage,
- acl->priority + OVN_ACL_PRI_OFFSET,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ ds_cstr(&match), ds_cstr(&actions),
+ &acl->header_);
}
} else {
/* There are no stateful ACLs in use on this datapath,
@@ -5057,19 +5088,19 @@ consider_acl(struct hmap *lflows, struct ovn_datapath
*od,
* logical flow action in all cases. */
if (!strcmp(acl->action, "reject")) {
build_reject_acl_rules(od, lflows, stage, acl, &match,
- &actions);
+ &actions, &acl->header_);
} else {
build_acl_log(&actions, acl);
ds_put_cstr(&actions, "/* drop */");
- ovn_lflow_add(lflows, od, stage,
- acl->priority + OVN_ACL_PRI_OFFSET,
- acl->match, ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ acl->priority + OVN_ACL_PRI_OFFSET,
+ acl->match, ds_cstr(&actions),
+ &acl->header_);
}
}
ds_destroy(&match);
ds_destroy(&actions);
}
- free(stage_hint);
}
static struct ovn_port_group *
@@ -5272,9 +5303,9 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
"&& ip4.src == %s && udp && udp.src == 67 "
"&& udp.dst == 68", od->nbs->ports[i]->name,
server_mac, server_id);
- ovn_lflow_add(
+ ovn_lflow_add_with_hint(
lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
- actions);
+ actions, &od->nbs->ports[i]->dhcpv4_options->header_);
ds_destroy(&match);
}
}
@@ -5299,9 +5330,9 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows,
"&& ip6.src == %s && udp && udp.src == 547 "
"&& udp.dst == 546", od->nbs->ports[i]->name,
server_mac, server_ip);
- ovn_lflow_add(
+ ovn_lflow_add_with_hint(
lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match),
- actions);
+ actions, &od->nbs->ports[i]->dhcpv6_options->header_);
ds_destroy(&match);
}
}
@@ -5352,9 +5383,10 @@ build_qos(struct ovn_datapath *od, struct hmap *lflows) {
ds_put_format(&dscp_action, "ip.dscp = %"PRId64"; next;",
qos->value_action[j]);
- ovn_lflow_add(lflows, od, stage,
- qos->priority,
- qos->match, ds_cstr(&dscp_action));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ qos->priority,
+ qos->match, ds_cstr(&dscp_action),
+ &qos->header_);
ds_destroy(&dscp_action);
}
}
@@ -5383,9 +5415,10 @@ build_qos(struct ovn_datapath *od, struct hmap *lflows) {
*
* We limit the bandwidth of this flow by adding a meter table.
*/
- ovn_lflow_add(lflows, od, stage,
- qos->priority,
- qos->match, ds_cstr(&meter_action));
+ ovn_lflow_add_with_hint(lflows, od, stage,
+ qos->priority,
+ qos->match, ds_cstr(&meter_action),
+ &qos->header_);
ds_destroy(&meter_action);
}
}
@@ -5414,8 +5447,8 @@ build_lb(struct ovn_datapath *od, struct hmap *lflows)
static void
build_lb_hairpin_rules(struct ovn_datapath *od, struct hmap *lflows,
- struct lb_vip *lb_vip, const char *ip_match,
- const char *proto)
+ struct ovn_lb *lb, struct lb_vip *lb_vip,
+ const char *ip_match, const char *proto)
{
/* Ingress Pre-Hairpin table.
* - Priority 2: SNAT load balanced traffic that needs to be hairpinned.
@@ -5440,8 +5473,9 @@ build_lb_hairpin_rules(struct ovn_datapath *od, struct
hmap *lflows,
ds_cstr(&proto_match));
ds_put_format(&action, REGBIT_HAIRPIN " = 1; ct_snat(%s);",
lb_vip->vip);
- ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 2, ds_cstr(&match),
- ds_cstr(&action));
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 2,
+ ds_cstr(&match), ds_cstr(&action),
+ &lb->nlb->header_);
/* If the packets are replies for hairpinned traffic, UNSNAT them. */
ds_clear(&proto_match);
@@ -5453,8 +5487,10 @@ build_lb_hairpin_rules(struct ovn_datapath *od, struct
hmap *lflows,
ds_put_format(&match, "%s.src == %s && %s.dst == %s%s",
ip_match, backend->ip, ip_match, lb_vip->vip,
ds_cstr(&proto_match));
- ovn_lflow_add(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 1, ds_cstr(&match),
- REGBIT_HAIRPIN " = 1; ct_snat;");
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_PRE_HAIRPIN, 1,
+ ds_cstr(&match),
+ REGBIT_HAIRPIN " = 1; ct_snat;",
+ &lb->nlb->header_);
ds_destroy(&action);
ds_destroy(&match);
@@ -5492,11 +5528,13 @@ build_lb_rules(struct ovn_datapath *od, struct hmap
*lflows, struct ovn_lb *lb)
ds_put_format(&match, "ct.new && %s.dst == %s", ip_match,
lb_vip->vip);
if (lb_vip->vip_port) {
ds_put_format(&match, " && %s.dst == %d", proto,
lb_vip->vip_port);
- ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 120,
- ds_cstr(&match), ds_cstr(&action));
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 120,
+ ds_cstr(&match), ds_cstr(&action),
+ &lb->nlb->header_);
} else {
- ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 110,
- ds_cstr(&match), ds_cstr(&action));
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_STATEFUL, 110,
+ ds_cstr(&match), ds_cstr(&action),
+ &lb->nlb->header_);
}
ds_destroy(&match);
@@ -5506,7 +5544,7 @@ build_lb_rules(struct ovn_datapath *od, struct hmap
*lflows, struct ovn_lb *lb)
* a load balancer VIP is DNAT-ed to a backend that happens to be
* the source of the traffic).
*/
- build_lb_hairpin_rules(od, lflows, lb_vip, ip_match, proto);
+ build_lb_hairpin_rules(od, lflows, lb, lb_vip, ip_match, proto);
}
}
@@ -5785,7 +5823,8 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips,
struct ovn_port *patch_op,
struct ovn_datapath *od,
uint32_t priority,
- struct hmap *lflows)
+ struct hmap *lflows,
+ const struct ovsdb_idl_row *stage_hint)
{
struct ds match = DS_EMPTY_INITIALIZER;
struct ds actions = DS_EMPTY_INITIALIZER;
@@ -5816,8 +5855,8 @@ build_lswitch_rport_arp_req_flow_for_ip(struct sset *ips,
* in the broadcast domain.
*/
ds_put_format(&actions, "outport = %s; output;", patch_op->json_key);
- ovn_lflow_add(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_SWITCH_IN_L2_LKUP, priority,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
ds_destroy(&match);
ds_destroy(&actions);
@@ -5834,7 +5873,8 @@ static void
build_lswitch_rport_arp_req_flows(struct ovn_port *op,
struct ovn_datapath *sw_od,
struct ovn_port *sw_op,
- struct hmap *lflows)
+ struct hmap *lflows,
+ const struct ovsdb_idl_row *stage_hint)
{
if (!op || !op->nbrp) {
return;
@@ -5888,11 +5928,13 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op,
if (!sset_is_empty(&all_ips_v4)) {
build_lswitch_rport_arp_req_flow_for_ip(&all_ips_v4, AF_INET, sw_op,
- sw_od, 75, lflows);
+ sw_od, 75, lflows,
+ stage_hint);
}
if (!sset_is_empty(&all_ips_v6)) {
build_lswitch_rport_arp_req_flow_for_ip(&all_ips_v6, AF_INET6, sw_op,
- sw_od, 75, lflows);
+ sw_od, 75, lflows,
+ stage_hint);
}
sset_destroy(&all_ips_v4);
@@ -5972,8 +6014,9 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
(!strcmp(op->nbsp->type, "vtep"))) {
ds_clear(&match);
ds_put_format(&match, "inport == %s", op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP,
+ 100, ds_cstr(&match), "next;",
+ &op->nbsp->header_);
}
}
@@ -6026,8 +6069,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
"bind_vport(%s, inport); "
"next;",
op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &vp->nbsp->header_);
}
free(tokstr);
@@ -6066,8 +6111,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
"output;",
op->lsp_addrs[i].ea_s, op->lsp_addrs[i].ea_s,
op->lsp_addrs[i].ipv4_addrs[j].addr_s);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 50,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
/* Do not reply to an ARP request from the port that owns
* the address (otherwise a DHCP client that ARPs to check
@@ -6082,8 +6130,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
* network is not working as configured, so dropping the
* request would frustrate that intent.) */
ds_put_format(&match, " && inport == %s", op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 100,
+ ds_cstr(&match), "next;",
+ &op->nbsp->header_);
}
/* For ND solicitations, we need to listen for both the
@@ -6114,14 +6164,19 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->lsp_addrs[i].ipv6_addrs[j].addr_s,
op->lsp_addrs[i].ipv6_addrs[j].addr_s,
op->lsp_addrs[i].ea_s);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 50,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
/* Do not reply to a solicitation from the port that owns
* the address (otherwise DAD detection will fail). */
ds_put_format(&match, " && inport == %s", op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 100,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 100,
+ ds_cstr(&match), "next;",
+ &op->nbsp->header_);
}
}
}
@@ -6169,9 +6224,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
"output;",
svc_monitor_mac, svc_monitor_mac,
lb->vips[i].backends[j].svc_mon_src_ip);
- ovn_lflow_add(lflows, lb->vips[i].backends[j].op->od,
- S_SWITCH_IN_ARP_ND_RSP, 110,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows,
+ lb->vips[i].backends[j].op->od,
+ S_SWITCH_IN_ARP_ND_RSP, 110,
+ ds_cstr(&match), ds_cstr(&actions),
+ &lb->nlb->header_);
}
}
}
@@ -6205,6 +6262,14 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
}
for (size_t i = 0; i < op->n_lsp_addrs; i++) {
+ struct ovsdb_idl_row *stage_hint;
+
+ if (op->nbsp->dhcpv4_options) {
+ stage_hint = &op->nbsp->dhcpv4_options->header_;
+ } else {
+ stage_hint = NULL;
+ }
+
for (size_t j = 0; j < op->lsp_addrs[i].n_ipv4_addrs; j++) {
struct ds options_action = DS_EMPTY_INITIALIZER;
struct ds response_action = DS_EMPTY_INITIALIZER;
@@ -6226,9 +6291,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->json_key);
}
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS,
- 100, ds_cstr(&match),
- ds_cstr(&options_action));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ stage_hint);
ds_clear(&match);
/* Allow ip4.src = OFFER_IP and
* ip4.dst = {SERVER_IP, 255.255.255.255} for the below
@@ -6250,9 +6317,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->json_key);
}
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS,
- 100, ds_cstr(&match),
- ds_cstr(&options_action));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ stage_hint);
ds_clear(&match);
/* If REGBIT_DHCP_OPTS_RESULT is set, it means the
@@ -6270,9 +6339,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->json_key);
}
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE,
- 100, ds_cstr(&match),
- ds_cstr(&response_action));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_DHCP_RESPONSE, 100,
+ ds_cstr(&match),
+ ds_cstr(&response_action),
+ stage_hint);
ds_destroy(&options_action);
ds_destroy(&response_action);
ds_destroy(&ipv4_addr_match);
@@ -6280,6 +6351,12 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
}
}
+ if (op->nbsp->dhcpv6_options) {
+ stage_hint = &op->nbsp->dhcpv6_options->header_;
+ } else {
+ stage_hint = NULL;
+ }
+
for (size_t j = 0; j < op->lsp_addrs[i].n_ipv6_addrs; j++) {
struct ds options_action = DS_EMPTY_INITIALIZER;
struct ds response_action = DS_EMPTY_INITIALIZER;
@@ -6300,14 +6377,20 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->json_key);
}
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100,
- ds_cstr(&match), ds_cstr(&options_action));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_DHCP_OPTIONS, 100,
+ ds_cstr(&match),
+ ds_cstr(&options_action),
+ stage_hint);
/* If REGBIT_DHCP_OPTS_RESULT is set to 1, it means the
* put_dhcpv6_opts action is successful */
ds_put_cstr(&match, " && "REGBIT_DHCP_OPTS_RESULT);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE,
100,
- ds_cstr(&match), ds_cstr(&response_action));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_DHCP_RESPONSE, 100,
+ ds_cstr(&match),
+ ds_cstr(&response_action),
+ stage_hint);
ds_destroy(&options_action);
ds_destroy(&response_action);
break;
@@ -6392,9 +6475,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
op->od->localnet_port->json_key,
op->lsp_addrs[i].ea_s, op->json_key,
rp->lsp_addrs[k].ipv4_addrs[l].addr_s);
- ovn_lflow_add(lflows, op->od,
- S_SWITCH_IN_EXTERNAL_PORT, 100,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_EXTERNAL_PORT,
+ 100, ds_cstr(&match), "drop;",
+ &op->nbsp->header_);
}
for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv6_addrs;
l++) {
@@ -6409,9 +6493,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
rp->lsp_addrs[k].ipv6_addrs[l].addr_s,
rp->lsp_addrs[k].ipv6_addrs[l].sn_addr_s,
rp->lsp_addrs[k].ipv6_addrs[l].addr_s);
- ovn_lflow_add(lflows, op->od,
- S_SWITCH_IN_EXTERNAL_PORT, 100,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_EXTERNAL_PORT, 100,
+ ds_cstr(&match), "drop;",
+ &op->nbsp->header_);
}
}
}
@@ -6565,7 +6650,8 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
* requests only to the router port that owns the IP address.
*/
if (!strcmp(op->nbsp->type, "router")) {
- build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows);
+ build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows,
+ &op->nbsp->header_);
}
for (size_t i = 0; i < op->nbsp->n_addresses; i++) {
@@ -6581,8 +6667,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "outport = %s; output;",
op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
+ 50, ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
} else if (!strcmp(op->nbsp->addresses[i], "unknown")) {
if (lsp_is_enabled(op->nbsp)) {
ovn_multicast_add(mcgroups, &mc_unknown, op);
@@ -6600,8 +6688,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "outport = %s; output;",
op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
+ 50, ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
} else if (!strcmp(op->nbsp->addresses[i], "router")) {
if (!op->peer || !op->peer->nbrp
|| !ovs_scan(op->peer->nbrp->mac,
@@ -6642,8 +6732,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "outport = %s; output;",
op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_L2_LKUP, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbsp->header_);
/* Add ethernet addresses specified in NAT rules on
* distributed logical routers. */
@@ -6665,9 +6757,11 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "outport = %s; output;",
op->json_key);
- ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP,
- 50, ds_cstr(&match),
- ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_SWITCH_IN_L2_LKUP, 50,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
}
}
}
@@ -6783,7 +6877,8 @@ get_outport_for_routing_policy_nexthop(struct
ovn_datapath *od,
static void
build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od,
struct hmap *ports,
- const struct nbrec_logical_router_policy *rule)
+ const struct nbrec_logical_router_policy *rule,
+ const struct ovsdb_idl_row *stage_hint)
{
struct ds match = DS_EMPTY_INITIALIZER;
struct ds actions = DS_EMPTY_INITIALIZER;
@@ -6823,8 +6918,9 @@ build_routing_policy_flow(struct hmap *lflows, struct
ovn_datapath *od,
ds_put_cstr(&actions, "next;");
}
ds_put_format(&match, "%s", rule->match);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY, rule->priority,
- ds_cstr(&match), ds_cstr(&actions));
+
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_POLICY, rule->priority,
+ ds_cstr(&match), ds_cstr(&actions), stage_hint);
ds_destroy(&match);
ds_destroy(&actions);
}
@@ -6893,8 +6989,9 @@ add_distributed_nat_routes(struct hmap *lflows, const
struct ovn_port *op)
REGBIT_NAT_REDIRECT" = 0; next;",
op->od->l3dgw_port->json_key,
nat->external_mac);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_ROUTING, 400,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, 400,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
ds_clear(&match);
ds_clear(&actions);
@@ -6941,8 +7038,9 @@ add_distributed_nat_routes(struct hmap *lflows, const struct ovn_port *op)
family == AF_INET ? "4" : "6",
family == AF_INET ? "" : "xx",
nat->external_ip);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_ROUTING, 400,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING,
+ 400, ds_cstr(&match), ds_cstr(&actions),
+ &nat2->header_);
ds_clear(&match);
ds_clear(&actions);
}
@@ -7368,7 +7466,8 @@ build_ecmp_route_flow(struct hmap *lflows, struct
ovn_datapath *od,
static void
add_route(struct hmap *lflows, const struct ovn_port *op,
const char *lrp_addr_s, const char *network_s, int plen,
- const char *gateway, bool is_src_route)
+ const char *gateway, bool is_src_route,
+ const struct ovsdb_idl_row *stage_hint)
{
bool is_ipv4 = strchr(network_s, '.') ? true : false;
struct ds match = DS_EMPTY_INITIALIZER;
@@ -7406,8 +7505,9 @@ add_route(struct hmap *lflows, const struct ovn_port *op,
op->lrp_networks.ea_s,
op->json_key);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_ROUTING, priority,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_ROUTING, priority,
+ ds_cstr(&match), ds_cstr(&actions),
+ stage_hint);
ds_destroy(&match);
ds_destroy(&actions);
}
@@ -7431,7 +7531,8 @@ build_static_route_flow(struct hmap *lflows, struct
ovn_datapath *od,
char *prefix_s = build_route_prefix_s(&route_->prefix, route_->plen);
add_route(lflows, out_port, lrp_addr_s, prefix_s, route_->plen,
- route->nexthop, route_->is_src_route);
+ route->nexthop, route_->is_src_route,
+ &route->header_);
free(prefix_s);
}
@@ -7522,22 +7623,24 @@ add_router_lb_flow(struct hmap *lflows, struct
ovn_datapath *od,
if (lb_force_snat_ip) {
char *new_actions = xasprintf("flags.force_snat_for_lb = 1; %s",
ds_cstr(actions));
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority, new_match,
- new_actions);
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
+ new_match, new_actions, &lb->header_);
free(new_actions);
} else {
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority, new_match,
- ds_cstr(actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
+ new_match, ds_cstr(actions), &lb->header_);
}
/* A match and actions for established connections. */
char *est_match = xasprintf("ct.est && %s", ds_cstr(match));
if (lb_force_snat_ip) {
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority, est_match,
- "flags.force_snat_for_lb = 1; ct_dnat;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
+ est_match,
+ "flags.force_snat_for_lb = 1; ct_dnat;",
+ &lb->header_);
} else {
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, priority, est_match,
- "ct_dnat;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, priority,
+ est_match, "ct_dnat;", &lb->header_);
}
free(new_match);
@@ -7582,12 +7685,14 @@ add_router_lb_flow(struct hmap *lflows, struct
ovn_datapath *od,
"is_chassis_resident(%s)", od->l3dgw_port->json_key,
od->l3redirect_port->json_key);
if (lb_force_snat_ip) {
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
- ds_cstr(&undnat_match),
- "flags.force_snat_for_lb = 1; ct_dnat;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
+ ds_cstr(&undnat_match),
+ "flags.force_snat_for_lb = 1; ct_dnat;",
+ &lb->header_);
} else {
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
- ds_cstr(&undnat_match), "ct_dnat;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 120,
+ ds_cstr(&undnat_match), "ct_dnat;",
+ &lb->header_);
}
ds_destroy(&undnat_match);
@@ -7734,8 +7839,8 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&match);
ds_put_format(&match, "eth.mcast && inport == %s", op->json_key);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ADMISSION, 50,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ADMISSION, 50,
+ ds_cstr(&match), "next;", &op->nbrp->header_);
ds_clear(&match);
ds_put_format(&match, "eth.dst == %s && inport == %s",
@@ -7747,8 +7852,8 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&match, " && is_chassis_resident(%s)",
op->od->l3redirect_port->json_key);
}
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ADMISSION, 50,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ADMISSION, 50,
+ ds_cstr(&match), "next;", &op->nbrp->header_);
}
/* Logical router ingress table 1: LOOKUP_NEIGHBOR and
@@ -7833,10 +7938,12 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&match, " && is_chassis_resident(%s)",
op->od->l3redirect_port->json_key);
}
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_LOOKUP_NEIGHBOR, 100,
- ds_cstr(&match),
- REGBIT_LOOKUP_NEIGHBOR_RESULT" = "
- "lookup_arp(inport, arp.spa, arp.sha); next;");
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_ROUTER_IN_LOOKUP_NEIGHBOR, 100,
+ ds_cstr(&match),
+ REGBIT_LOOKUP_NEIGHBOR_RESULT" = "
+ "lookup_arp(inport, arp.spa, arp.sha); "
+ "next;", &op->nbrp->header_);
}
}
@@ -7915,8 +8022,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_cstr(&match, "ip4.src == ");
op_put_v4_networks(&match, op, true);
ds_put_cstr(&match, " && "REGBIT_EGRESS_LOOPBACK" == 0");
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 100,
+ ds_cstr(&match), "drop;",
+ &op->nbrp->header_);
/* ICMP echo reply. These flows reply to ICMP echo requests
* received for the router's IP address. Since packets only
@@ -7935,8 +8043,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp4.type = 0; "
"flags.loopback = 1; "
"next; ");
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
/* ICMP time exceeded */
@@ -7957,8 +8066,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"ip.ttl = 255; "
"next; };",
op->lrp_networks.ipv4_addrs[i].addr_s);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
/* ARP reply. These flows reply to ARP requests for the router's own
@@ -8019,8 +8129,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
op->lrp_networks.ea_s,
op->lrp_networks.ipv4_addrs[i].addr_s,
op->json_key);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
/* A set to hold all load-balancer vips that need ARP responses. */
@@ -8264,8 +8375,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
IP_ARGS(ip),
op->json_key);
}
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
}
if (!smap_get(&op->od->nbr->options, "chassis")
@@ -8283,8 +8396,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp4.type = 3; "
"icmp4.code = 3; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(&match), action,
+ &op->nbrp->header_);
ds_clear(&match);
ds_put_format(&match,
@@ -8294,8 +8408,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"eth.dst <-> eth.src; "
"ip4.dst <-> ip4.src; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(&match), action,
+ &op->nbrp->header_);
ds_clear(&match);
ds_put_format(&match,
@@ -8308,8 +8423,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp4.type = 3; "
"icmp4.code = 2; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 70,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 70, ds_cstr(&match), action,
+ &op->nbrp->header_);
}
}
@@ -8368,8 +8484,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
if (has_drop_ips) {
/* Drop IP traffic to this router. */
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 60,
- ds_cstr(&match), "drop;");
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 60,
+ ds_cstr(&match), "drop;",
+ &op->nbrp->header_);
}
free(snat_ips);
@@ -8402,8 +8519,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp6.type = 129; "
"flags.loopback = 1; "
"next; ");
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
/* ND reply. These flows reply to ND solicitations for the
@@ -8443,8 +8561,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
op->lrp_networks.ipv6_addrs[i].addr_s,
op->lrp_networks.ipv6_addrs[i].addr_s,
op->lrp_networks.ea_s);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
/* UDP/TCP port unreachable */
@@ -8459,8 +8578,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"eth.dst <-> eth.src; "
"ip6.dst <-> ip6.src; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(&match), action,
+ &op->nbrp->header_);
ds_clear(&match);
ds_put_format(&match,
@@ -8473,8 +8593,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp6.type = 1; "
"icmp6.code = 4; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 80,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 80, ds_cstr(&match), action,
+ &op->nbrp->header_);
ds_clear(&match);
ds_put_format(&match,
@@ -8487,8 +8608,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"icmp6.type = 1; "
"icmp6.code = 3; "
"next; };";
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 70,
- ds_cstr(&match), action);
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT,
+ 70, ds_cstr(&match), action,
+ &op->nbrp->header_);
}
}
@@ -8519,8 +8641,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"icmp6.code = 0; /* TTL exceeded in transit */ "
"next; };",
op->lrp_networks.ipv6_addrs[i].addr_s);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_IP_INPUT, 40,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
}
@@ -8659,8 +8782,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_cstr(&actions, "ct_snat;");
}
- ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 90,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT,
+ 90, ds_cstr(&match),
+ ds_cstr(&actions),
+ &nat->header_);
} else {
/* Distributed router. */
@@ -8686,8 +8811,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_cstr(&actions, "ct_snat;");
}
- ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT,
+ 100, ds_cstr(&match),
+ ds_cstr(&actions),
+ &nat->header_);
/* Traffic received on other router ports must be
* redirected to the central instance of the l3dgw_port
@@ -8696,9 +8823,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&match, "ip && ip%s.dst == %s",
is_v6 ? "6" : "4",
nat->external_ip);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_UNSNAT, 50,
- ds_cstr(&match),
- REGBIT_NAT_REDIRECT" = 1; next;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_UNSNAT,
+ 50, ds_cstr(&match),
+ REGBIT_NAT_REDIRECT" = 1; next;",
+ &nat->header_);
}
}
@@ -8734,8 +8862,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
"ct_dnat(%s);", nat->logical_ip);
}
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
} else {
/* Distributed router. */
@@ -8762,8 +8891,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
nat->logical_ip);
}
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
/* Traffic received on other router ports must be
* redirected to the central instance of the l3dgw_port
@@ -8772,9 +8902,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&match, "ip && ip%s.dst == %s",
is_v6 ? "6" : "4",
nat->external_ip);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DNAT, 50,
- ds_cstr(&match),
- REGBIT_NAT_REDIRECT" = 1; next;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DNAT, 50,
+ ds_cstr(&match),
+ REGBIT_NAT_REDIRECT" = 1; next;",
+ &nat->header_);
}
}
@@ -8813,8 +8944,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_format(&actions, "ct_dnat;");
}
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_UNDNAT, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_UNDNAT, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
}
/* Egress SNAT table: Packets enter the egress pipeline with
@@ -8841,9 +8973,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
/* The priority here is calculated such that the
* nat->logical_ip with the longest mask gets a higher
* priority. */
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT,
- count_1bits(ntohl(mask)) + 1,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
+ count_1bits(ntohl(mask)) + 1,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
} else {
uint16_t priority = count_1bits(ntohl(mask)) + 1;
@@ -8878,9 +9011,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
/* The priority here is calculated such that the
* nat->logical_ip with the longest mask gets a higher
* priority. */
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_SNAT,
- priority, ds_cstr(&match),
- ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_SNAT,
+ priority, ds_cstr(&match),
+ ds_cstr(&actions),
+ &nat->header_);
}
}
@@ -8897,8 +9031,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ETH_ADDR_ARGS(mac),
od->l3dgw_port->json_key,
nat->logical_port);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_ADMISSION, 50,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ADMISSION, 50,
+ ds_cstr(&match), "next;",
+ &nat->header_);
}
/* Ingress Gateway Redirect Table: For NAT on a distributed
@@ -8911,8 +9046,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
is_v6 ? "6" : "4",
nat->logical_ip,
od->l3dgw_port->json_key);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 100,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT,
+ 100, ds_cstr(&match), "next;",
+ &nat->header_);
}
/* Egress Loopback table: For NAT on a distributed router.
@@ -8946,16 +9082,21 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"flags = 0; flags.loopback = 1; "
REGBIT_EGRESS_LOOPBACK" = 1; "
"next(pipeline=ingress, table=0); ");
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, 300,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od,
+ S_ROUTER_OUT_EGR_LOOP, 300,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &nat2->header_);
ds_clear(&match);
ds_put_format(&match,
"ip%s.src == %s && ip%s.dst == %s",
is_v6 ? "6" : "4", nat2->external_ip,
is_v6 ? "6" : "4", nat->external_ip);
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, 200,
- ds_cstr(&match), "next;");
+ ovn_lflow_add_with_hint(lflows, od,
+ S_ROUTER_OUT_EGR_LOOP, 200,
+ ds_cstr(&match), "next;",
+ &nat2->header_);
ds_clear(&match);
}
}
@@ -8975,8 +9116,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
}
ds_put_format(&actions, REGBIT_EGRESS_LOOPBACK" = 1; "
"next(pipeline=ingress, table=0); };");
- ovn_lflow_add(lflows, od, S_ROUTER_OUT_EGR_LOOP, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_OUT_EGR_LOOP, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &nat->header_);
}
}
@@ -9109,8 +9251,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_put_format(&match, "ip && ip6.dst == %s",
lb_vip->vip);
}
- ovn_lflow_add(lflows, od, S_ROUTER_IN_DEFRAG,
- 100, ds_cstr(&match), "ct_next;");
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_DEFRAG,
+ 100, ds_cstr(&match), "ct_next;",
+ &nb_lb->header_);
}
/* Higher priority rules are added for load-balancing in DNAT
@@ -9218,8 +9361,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
if (add_rs_response_flow) {
ds_put_cstr(&actions, "); next;");
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od, S_ROUTER_IN_ND_RA_OPTIONS,
+ 50, ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
ds_clear(&actions);
ds_clear(&match);
ds_put_format(&match, "inport == %s && ip6.dst == ff02::2 && "
@@ -9235,8 +9379,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"outport = inport; flags.loopback = 1; "
"output;",
op->lrp_networks.ea_s, ip6_str);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ND_RA_RESPONSE, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_ROUTER_IN_ND_RA_RESPONSE, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
}
@@ -9277,13 +9423,15 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
add_route(lflows, op, op->lrp_networks.ipv4_addrs[i].addr_s,
op->lrp_networks.ipv4_addrs[i].network_s,
- op->lrp_networks.ipv4_addrs[i].plen, NULL, false);
+ op->lrp_networks.ipv4_addrs[i].plen, NULL, false,
+ &op->nbrp->header_);
}
for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
add_route(lflows, op, op->lrp_networks.ipv6_addrs[i].addr_s,
op->lrp_networks.ipv6_addrs[i].network_s,
- op->lrp_networks.ipv6_addrs[i].plen, NULL, false);
+ op->lrp_networks.ipv6_addrs[i].plen, NULL, false,
+ &op->nbrp->header_);
}
}
@@ -9405,7 +9553,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
for (int i = 0; i < od->nbr->n_policies; i++) {
const struct nbrec_logical_router_policy *rule
= od->nbr->policies[i];
- build_routing_policy_flow(lflows, od, ports, rule);
+ build_routing_policy_flow(lflows, od, ports, rule, &rule->header_);
}
}
@@ -9456,8 +9604,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;",
op->lrp_networks.ea_s);
- ovn_lflow_add(lflows, op->peer->od,
S_ROUTER_IN_ARP_RESOLVE,
- 100, ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
if (op->lrp_networks.n_ipv6_addrs) {
@@ -9469,8 +9619,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;",
op->lrp_networks.ea_s);
- ovn_lflow_add(lflows, op->peer->od,
S_ROUTER_IN_ARP_RESOLVE,
- 100, ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, op->peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
}
@@ -9491,8 +9643,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;",
op->lrp_networks.ea_s);
- ovn_lflow_add(lflows, op->od, S_ROUTER_IN_ARP_RESOLVE,
- 50, ds_cstr(&match), ds_cstr(&actions));
+
+ ovn_lflow_add_with_hint(lflows, op->od,
+ S_ROUTER_IN_ARP_RESOLVE, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbrp->header_);
}
}
} else if (op->od->n_router_ports && strcmp(op->nbsp->type, "router")
@@ -9533,9 +9688,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;", ea_s);
- ovn_lflow_add(lflows, peer->od,
- S_ROUTER_IN_ARP_RESOLVE, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
}
}
@@ -9567,9 +9724,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;", ea_s);
- ovn_lflow_add(lflows, peer->od,
- S_ROUTER_IN_ARP_RESOLVE, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
}
}
}
@@ -9617,9 +9776,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions,
"eth.dst = 00:00:00:00:00:00; next;");
- ovn_lflow_add(lflows, peer->od,
- S_ROUTER_IN_ARP_RESOLVE, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
break;
}
}
@@ -9660,9 +9821,11 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;", ea_s);
- ovn_lflow_add(lflows, peer->od,
- S_ROUTER_IN_ARP_RESOLVE, 100,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match),
+ ds_cstr(&actions),
+ &op->nbsp->header_);
found_vip_network = true;
break;
}
@@ -9715,8 +9878,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;",
router_port->lrp_networks.ea_s);
- ovn_lflow_add(lflows, peer->od, S_ROUTER_IN_ARP_RESOLVE,
- 100, ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbsp->header_);
}
if (router_port->lrp_networks.n_ipv6_addrs) {
@@ -9728,8 +9893,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "eth.dst = %s; next;",
router_port->lrp_networks.ea_s);
- ovn_lflow_add(lflows, peer->od, S_ROUTER_IN_ARP_RESOLVE,
- 100, ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, peer->od,
+ S_ROUTER_IN_ARP_RESOLVE, 100,
+ ds_cstr(&match), ds_cstr(&actions),
+ &op->nbsp->header_);
}
}
}
@@ -9790,8 +9957,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&actions,
REGBIT_PKT_LARGER" = check_pkt_larger(%d);"
" next;", gw_mtu);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_CHK_PKT_LEN, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ &od->l3dgw_port->nbrp->header_);
for (size_t i = 0; i < od->nbr->n_ports; i++) {
struct ovn_port *rp = ovn_port_find(ports,
@@ -9822,8 +9990,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
rp->lrp_networks.ea_s,
rp->lrp_networks.ipv4_addrs[0].addr_s,
gw_mtu - 18);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_LARGER_PKTS, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_LARGER_PKTS,
+ 50, ds_cstr(&match), ds_cstr(&actions),
+ &rp->nbrp->header_);
}
}
}
@@ -9840,8 +10009,15 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
continue;
}
if (od->l3dgw_port && od->l3redirect_port) {
- ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 300,
- REGBIT_DISTRIBUTED_NAT" == 1", "next;");
+ const struct ovsdb_idl_row *stage_hint = NULL;
+
+ if (od->l3dgw_port->nbrp) {
+ stage_hint = &od->l3dgw_port->nbrp->header_;
+ }
+
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, 300,
+ REGBIT_DISTRIBUTED_NAT" == 1", "next;",
+ stage_hint);
/* For traffic with outport == l3dgw_port, if the
* packet did not match any higher priority redirect
@@ -9853,8 +10029,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_clear(&actions);
ds_put_format(&actions, "outport = %s; next;",
od->l3redirect_port->json_key);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, 50,
+ ds_cstr(&match), ds_cstr(&actions),
+ stage_hint);
/* If the Ethernet destination has not been resolved,
* redirect to the central instance of the l3dgw_port.
@@ -9863,8 +10040,9 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
* table, before being redirected to the central instance.
*/
ds_put_format(&match, " && eth.dst == 00:00:00:00:00:00");
- ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 150,
- ds_cstr(&match), ds_cstr(&actions));
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_GW_REDIRECT, 150,
+ ds_cstr(&match), ds_cstr(&actions),
+ stage_hint);
}
/* Packets are allowed by default. */
@@ -9913,8 +10091,10 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
"output; "
"};", ETH_ADDR_ARGS(eth_dst), sn_addr_s,
route->nexthop);
- ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
- ds_cstr(&match), ds_cstr(&actions));
+
+ ovn_lflow_add_with_hint(lflows, od, S_ROUTER_IN_ARP_REQUEST, 200,
+ ds_cstr(&match), ds_cstr(&actions),
+ &route->header_);
}
ovn_lflow_add(lflows, od, S_ROUTER_IN_ARP_REQUEST, 100,
@@ -9972,7 +10152,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap
*ports,
ds_put_format(&actions, "eth.src = %s; output;",
op->lrp_networks.ea_s);
ovn_lflow_add(lflows, op->od, S_ROUTER_OUT_DELIVERY, 110,
- ds_cstr(&match), ds_cstr(&actions));
+ ds_cstr(&match), ds_cstr(&actions));
}
ds_clear(&match);
diff --git a/utilities/ovn-detrace.in b/utilities/ovn-detrace.in
index 3bfb720..87a8d57 100755
--- a/utilities/ovn-detrace.in
+++ b/utilities/ovn-detrace.in
@@ -135,9 +135,104 @@ class CookieHandlerByUUUID(CookieHandler):
cookie = cookie.zfill(8)
return self._db.find_rows_by_partial_uuid(self._table, cookie)
+class ACLHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(ACLHintHandler, self).__init__(ovnnb_db, 'ACL')
+
+ def print_record(self, acl):
+ output = 'ACL: %s, priority=%s, ' \
+ 'match=(%s), %s' % (acl.direction,
+ acl.priority,
+ acl.match.strip('"'),
+ acl.action)
+ if acl.log:
+ output += ' (log)'
+ print_h(output)
+
+class DHCPOptionsHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(DHCPOptionsHintHandler, self).__init__(ovnnb_db, 'DHCP_Options')
+
+ def print_record(self, dhcp_opt):
+ print_h('DHCP Options: cidr %s options (%s)' % (
+ dhcp_opt.cidr, dhcp_opt.options))
+
+class LSPHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(LSPHintHandler, self).__init__(ovnnb_db, 'Logical_Switch_Port')
+
+ def print_record(self, lsp):
+ print_h('Logical Switch Port: %s type %s (addresses %s, dynamic
addresses %s, security %s' % (
+ lsp.name, lsp.type, lsp.addresses, lsp.dynamic_addresses,
+ lsp.port_security))
+
+class LRPHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(LRPHintHandler, self).__init__(ovnnb_db, 'Logical_Router_Port')
+
+ def print_record(self, lrp):
+ print_h('Logical Router Port: %s mac %s networks %s ipv6_ra_configs
%s' % (
+ lrp.name, lrp.mac, lrp.networks, lrp.ipv6_ra_configs))
+
+class LRPolicyHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(LRPolicyHandler, self).__init__(ovnnb_db,
'Logical_Router_Policy')
+
+ def print_record(self, policy):
+ print_h('Logical Router Policy: priority %s match %s action %s nexthop
%s' % (
+ policy.priority, policy.match, policy.action,
+ policy.nexthop))
+
+class LoadBalancerHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(LoadBalancerHintHandler, self).__init__(ovnnb_db,
'Load_Balancer')
+
+ def print_record(self, lb):
+ print_h('Load Balancer: %s protocol %s vips %s ip_port_mappings %s' % (
+ lb.name, lb.protocol, lb.vips, lb.ip_port_mappings))
+
+class NATHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(NATHintHandler, self).__init__(ovnnb_db, 'NAT')
+
+ def print_record(self, nat):
+ print_h('NAT: external IP %s external_mac %s logical_ip %s
logical_port %s type %s' % (
+ nat.external_ip, nat.external_mac, nat.logical_ip,
+ nat.logical_port, nat.type))
+
+class StaticRouteHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(StaticRouteHintHandler, self).__init__(ovnnb_db,
+
'Logical_Router_Static_Route')
+
+ def print_record(self, route):
+ print_h('Route: %s via %s (port %s), policy=%s' % (
+ route.ip_prefix, route.nexthop, route.output_port,
+ route.policy))
+
+class QoSHintHandler(CookieHandlerByUUUID):
+ def __init__(self, ovnnb_db):
+ super(QoSHintHandler, self).__init__(ovnnb_db, 'QoS')
+
+ def print_record(self, qos):
+ print_h('QoS: priority %s direction %s match %s action %s bandwidth
%s' % (
+ qos.priority, qos.direction, qos.match, qos.action,
+ qos.bandwidth))
+
class LogicalFlowHandler(CookieHandlerByUUUID):
- def __init__(self, ovnsb_db):
+ def __init__(self, ovnnb_db, ovnsb_db):
super(LogicalFlowHandler, self).__init__(ovnsb_db, 'Logical_Flow')
+ self._hint_handlers = [
+ ACLHintHandler(ovnnb_db),
+ DHCPOptionsHintHandler(ovnnb_db),
+ LSPHintHandler(ovnnb_db),
+ LRPHintHandler(ovnnb_db),
+ LRPolicyHandler(ovnnb_db),
+ LoadBalancerHintHandler(ovnnb_db),
+ NATHintHandler(ovnnb_db),
+ StaticRouteHintHandler(ovnnb_db),
+ QoSHintHandler(ovnnb_db),
+ ]
def print_record(self, lflow):
print_p('Logical datapath: %s [%s]' %
@@ -151,24 +246,14 @@ class LogicalFlowHandler(CookieHandlerByUUUID):
def print_hint(self, lflow, ovnnb_db):
external_ids = lflow.external_ids
- if external_ids.get('stage-name') in ['ls_in_acl',
- 'ls_out_acl']:
- acl_hint = external_ids.get('stage-hint')
- if not acl_hint:
- return
- for i, acl in enumerate(
- ovnnb_db.find_rows_by_partial_uuid('ACL', acl_hint)):
+ hint = external_ids.get('stage-hint')
+ if not hint:
+ return
+ for handler in self._hint_handlers:
+ for i, record in enumerate(handler.get_records(hint)):
if i > 0:
- print_h('[Duplicate uuid ACL hint]')
-
- output = 'ACL: %s, priority=%s, ' \
- 'match=(%s), %s' % (acl.direction,
- acl.priority,
- acl.match.strip('"'),
- acl.action)
- if acl.log:
- output += ' (log)'
- print_h(output)
+ print_h('[Duplicate uuid hint]')
+ handler.print_record(record)
class PortBindingHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
@@ -283,7 +368,7 @@ def main():
ovsdb_ovnnb = OVSDB(ovnnb_db, 'OVN_Northbound')
cookie_handlers = [
- LogicalFlowHandler(ovsdb_ovnsb),
+ LogicalFlowHandler(ovsdb_ovnnb, ovsdb_ovnsb),
PortBindingHandler(ovsdb_ovnsb),
MacBindingHandler(ovsdb_ovnsb),
MulticastGroupHandler(ovsdb_ovnsb),