On Tue, Feb 4, 2020 at 3:32 AM Mark Michelson <mmich...@redhat.com> wrote: > > Acked-by: Mark Michelson <mmich...@redhat.com>
Thanks. I applied this patch to master. Numan > > On 1/31/20 6:38 AM, Dumitru Ceara wrote: > > 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 <dce...@redhat.com> > > > > --- > > 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), > > > > _______________________________________________ > dev mailing list > d...@openvswitch.org > https://mail.openvswitch.org/mailman/listinfo/ovs-dev > _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev