Populate the in_out_port tag for logical switch pipeline flows wherever possible.
Signed-off-by: Han Zhou <[email protected]> --- northd/ovn-northd.c | 272 ++++++++++++++---------- northd/ovn_northd.dl | 495 +++++++++++++++++++++++++------------------ tests/ovn-northd.at | 21 ++ 3 files changed, 470 insertions(+), 318 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index ff81bf540..534bb9f97 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -4213,6 +4213,7 @@ struct ovn_lflow { uint16_t priority; char *match; char *actions; + char *io_port; char *stage_hint; const char *where; }; @@ -4248,7 +4249,7 @@ ovn_lflow_equal(const struct ovn_lflow *a, const struct ovn_datapath *od, static void ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od, enum ovn_stage stage, uint16_t priority, - char *match, char *actions, char *stage_hint, + char *match, char *actions, char *io_port, char *stage_hint, const char *where) { hmapx_init(&lflow->od_group); @@ -4257,6 +4258,7 @@ ovn_lflow_init(struct ovn_lflow *lflow, struct ovn_datapath *od, lflow->priority = priority; lflow->match = match; lflow->actions = actions; + lflow->io_port = io_port; lflow->stage_hint = stage_hint; lflow->where = where; } @@ -4274,7 +4276,7 @@ static struct hashrow_locks lflow_locks; static void do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, uint32_t hash, enum ovn_stage stage, uint16_t priority, - const char *match, const char *actions, + const char *match, const char *actions, const char *io_port, const struct ovsdb_idl_row *stage_hint, const char *where) { @@ -4297,6 +4299,7 @@ do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, * one datapath in a group, so it could be hashed correctly. */ ovn_lflow_init(lflow, NULL, stage, priority, xstrdup(match), xstrdup(actions), + io_port ? xstrdup(io_port) : NULL, ovn_lflow_hint(stage_hint), where); hmapx_add(&lflow->od_group, od); hmap_insert_fast(lflow_map, &lflow->hmap_node, hash); @@ -4306,7 +4309,7 @@ do_ovn_lflow_add(struct hmap *lflow_map, struct ovn_datapath *od, 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 *match, const char *actions, const char *io_port, const struct ovsdb_idl_row *stage_hint, const char *where) { ovs_assert(ovn_stage_to_datapath_type(stage) == ovn_datapath_get_type(od)); @@ -4321,11 +4324,11 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, if (use_logical_dp_groups && use_parallel_build) { lock_hash_row(&lflow_locks, hash); do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, - actions, stage_hint, where); + actions, io_port, stage_hint, where); unlock_hash_row(&lflow_locks, hash); } else { do_ovn_lflow_add(lflow_map, od, hash, stage, priority, match, - actions, stage_hint, where); + actions, io_port, stage_hint, where); } } @@ -4333,11 +4336,27 @@ ovn_lflow_add_at(struct hmap *lflow_map, struct ovn_datapath *od, #define ovn_lflow_add_with_hint(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, \ ACTIONS, STAGE_HINT) \ ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \ - STAGE_HINT, OVS_SOURCE_LOCATOR) + NULL, STAGE_HINT, OVS_SOURCE_LOCATOR) + +/* This macro is similar to ovn_lflow_add_with_hint, except that it requires + * the IN_OUT_PORT argument, which tells the lport name that appears in the + * MATCH, which helps ovn-controller to bypass lflows parsing when the lport is + * not local to the chassis. The critiera of the lport to be added using this + * argument: + * + * - For ingress pipeline, the lport that is used to match "inport". + * - For egress pipeline, the lport that is used to match "outport". + * + * For now, only LS pipelines should use this macro. */ +#define ovn_lflow_add_with_lport_and_hint(LFLOW_MAP, OD, STAGE, PRIORITY, \ + MATCH, ACTIONS, IN_OUT_PORT, \ + STAGE_HINT) \ + ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \ + IN_OUT_PORT, STAGE_HINT, OVS_SOURCE_LOCATOR) #define ovn_lflow_add(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS) \ ovn_lflow_add_at(LFLOW_MAP, OD, STAGE, PRIORITY, MATCH, ACTIONS, \ - NULL, OVS_SOURCE_LOCATOR) + NULL, NULL, OVS_SOURCE_LOCATOR) static struct ovn_lflow * ovn_lflow_find(const struct hmap *lflows, const struct ovn_datapath *od, @@ -4363,6 +4382,7 @@ ovn_lflow_destroy(struct hmap *lflows, struct ovn_lflow *lflow) hmapx_destroy(&lflow->od_group); free(lflow->match); free(lflow->actions); + free(lflow->io_port); free(lflow->stage_hint); free(lflow); } @@ -4532,8 +4552,10 @@ build_port_security_nd(struct ovn_port *op, struct hmap *lflows, ds_chomp(&match, ','); ds_put_cstr(&match, "}"); } - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, - 90, ds_cstr(&match), "next;", stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_PORT_SEC_ND, 90, + ds_cstr(&match), "next;", + op->key, stage_hint); } if (ps->n_ipv6_addrs || no_ip) { @@ -4542,15 +4564,18 @@ 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_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, - 90, ds_cstr(&match), "next;", stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_PORT_SEC_ND, 90, + ds_cstr(&match), "next;", + op->key, stage_hint); } } ds_clear(&match); ds_put_format(&match, "inport == %s && (arp || nd)", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 80, - ds_cstr(&match), "drop;", stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, + 80, ds_cstr(&match), "drop;", op->key, + stage_hint); ds_destroy(&match); } @@ -4602,9 +4627,10 @@ 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_with_hint(lflows, op->od, stage, 90, - ds_cstr(&dhcp_match), "next;", - stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, stage, 90, + ds_cstr(&dhcp_match), + "next;", op->key, + stage_hint); ds_destroy(&dhcp_match); ds_put_format(&match, "inport == %s && eth.src == %s" " && ip4.src == {", op->json_key, @@ -4643,9 +4669,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_with_hint(lflows, op->od, stage, 90, - ds_cstr(&match), "next;", - stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, stage, 90, + ds_cstr(&match), "next;", + op->key, stage_hint); ds_destroy(&match); } @@ -4659,11 +4685,11 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op, " && eth.src == %s" " && ip6.src == ::" " && ip6.dst == ff02::/16" - " && icmp6.type == {131, 135, 143}", op->json_key, - ps->ea_s); - ovn_lflow_add_with_hint(lflows, op->od, stage, 90, - ds_cstr(&dad_match), "next;", - stage_hint); + " && icmp6.type == {131, 135, 143}", + op->json_key, ps->ea_s); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, stage, 90, + ds_cstr(&dad_match), "next;", + op->key, stage_hint); ds_destroy(&dad_match); } ds_put_format(&match, "%s == %s && %s == %s", @@ -4671,9 +4697,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_with_hint(lflows, op->od, stage, 90, - ds_cstr(&match), "next;", - stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, stage, 90, + ds_cstr(&match), "next;", + op->key, stage_hint); ds_destroy(&match); } @@ -4681,8 +4707,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_with_hint(lflows, op->od, stage, 80, match, "drop;", - stage_hint); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, stage, 80, match, + "drop;", op->key, stage_hint); free(match); } @@ -5003,9 +5029,9 @@ build_lswitch_input_port_sec_op( ds_put_format(actions, "set_queue(%s); ", queue_id); } ds_put_cstr(actions, "next;"); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, 50, - ds_cstr(match), ds_cstr(actions), - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, + 50, ds_cstr(match), ds_cstr(actions), + op->key, &op->nbsp->header_); if (op->nbsp->n_port_security) { build_port_security_ip(P_IN, op, lflows, &op->nbsp->header_); @@ -5039,16 +5065,18 @@ build_lswitch_learn_fdb_op( ds_put_format(match, "inport == %s", op->json_key); ds_put_format(actions, REGBIT_LKUP_FDB " = lookup_fdb(inport, eth.src); next;"); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_LOOKUP_FDB, 100, - ds_cstr(match), ds_cstr(actions), - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_LOOKUP_FDB, 100, + ds_cstr(match), ds_cstr(actions), + op->key, &op->nbsp->header_); ds_put_cstr(match, " && "REGBIT_LKUP_FDB" == 0"); ds_clear(actions); ds_put_cstr(actions, "put_fdb(inport, eth.src); next;"); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_PUT_FDB, 100, - ds_cstr(match), ds_cstr(actions), - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, S_SWITCH_IN_PUT_FDB, + 100, ds_cstr(match), + ds_cstr(actions), op->key, + &op->nbsp->header_); } } @@ -5098,13 +5126,15 @@ build_lswitch_output_port_sec_op(struct ovn_port *op, } } ds_put_cstr(actions, "output;"); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, - 50, ds_cstr(match), ds_cstr(actions), - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_OUT_PORT_SEC_L2, 50, + ds_cstr(match), ds_cstr(actions), + op->key, &op->nbsp->header_); } else { - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, - 150, ds_cstr(match), "drop;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_OUT_PORT_SEC_L2, 150, + ds_cstr(match), "drop;", op->key, + &op->nbsp->header_); } if (op->nbsp->n_port_security) { @@ -5146,12 +5176,12 @@ skip_port_from_conntrack(struct ovn_datapath *od, struct ovn_port *op, 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_with_hint(lflows, od, in_stage, priority, - ds_cstr(&match_in), "next;", - &op->nbsp->header_); - ovn_lflow_add_with_hint(lflows, od, out_stage, priority, - ds_cstr(&match_out), "next;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, od, in_stage, priority, + ds_cstr(&match_in), "next;", op->key, + &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, od, out_stage, priority, + ds_cstr(&match_out), "next;", op->key, + &op->nbsp->header_); ds_destroy(&match_in); ds_destroy(&match_out); @@ -5674,7 +5704,8 @@ build_reject_acl_rules(struct ovn_datapath *od, struct hmap *lflows, "outport <-> inport; %s };", next_action); ovn_lflow_add_with_hint(lflows, od, stage, acl->priority + OVN_ACL_PRI_OFFSET, - ds_cstr(&match), ds_cstr(&actions), stage_hint); + ds_cstr(&match), ds_cstr(&actions), + stage_hint); free(next_action); ds_destroy(&match); @@ -6047,9 +6078,10 @@ 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_with_hint( + ovn_lflow_add_with_lport_and_hint( lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match), - dhcp_actions, &od->nbs->ports[i]->dhcpv4_options->header_); + dhcp_actions, od->nbs->ports[i]->name, + &od->nbs->ports[i]->dhcpv4_options->header_); } } @@ -6073,9 +6105,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_with_hint( + ovn_lflow_add_with_lport_and_hint( lflows, od, S_SWITCH_OUT_ACL, 34000, ds_cstr(&match), - dhcp6_actions, + dhcp6_actions, od->nbs->ports[i]->name, &od->nbs->ports[i]->dhcpv6_options->header_); } } @@ -6829,7 +6861,7 @@ build_lswitch_rport_arp_req_flows(struct ovn_port *op, static void build_dhcpv4_options_flows(struct ovn_port *op, struct lport_addresses *lsp_addrs, - const char *json_key, bool is_external, + struct ovn_port *inport, bool is_external, struct hmap *lflows) { struct ds match = DS_EMPTY_INITIALIZER; @@ -6846,18 +6878,17 @@ build_dhcpv4_options_flows(struct ovn_port *op, &match, "inport == %s && eth.src == %s && " "ip4.src == 0.0.0.0 && ip4.dst == 255.255.255.255 && " "udp.src == 68 && udp.dst == 67", - json_key, lsp_addrs->ea_s); + inport->json_key, lsp_addrs->ea_s); if (is_external) { ds_put_format(&match, " && is_chassis_resident(%s)", op->json_key); } - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), - ds_cstr(&options_action), - &op->nbsp->dhcpv4_options->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, ds_cstr(&match), + ds_cstr(&options_action), inport->key, + &op->nbsp->dhcpv4_options->header_); ds_clear(&match); /* Allow ip4.src = OFFER_IP and * ip4.dst = {SERVER_IP, 255.255.255.255} for the below @@ -6870,18 +6901,17 @@ build_dhcpv4_options_flows(struct ovn_port *op, ds_put_format( &match, "inport == %s && eth.src == %s && " "%s && udp.src == 68 && udp.dst == 67", - json_key, lsp_addrs->ea_s, ds_cstr(&ipv4_addr_match)); + inport->json_key, lsp_addrs->ea_s, ds_cstr(&ipv4_addr_match)); if (is_external) { ds_put_format(&match, " && is_chassis_resident(%s)", op->json_key); } - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), - ds_cstr(&options_action), - &op->nbsp->dhcpv4_options->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, ds_cstr(&match), + ds_cstr(&options_action), inport->key, + &op->nbsp->dhcpv4_options->header_); ds_clear(&match); /* If REGBIT_DHCP_OPTS_RESULT is set, it means the @@ -6890,18 +6920,17 @@ build_dhcpv4_options_flows(struct ovn_port *op, &match, "inport == %s && eth.src == %s && " "ip4 && udp.src == 68 && udp.dst == 67" " && "REGBIT_DHCP_OPTS_RESULT, - json_key, lsp_addrs->ea_s); + inport->json_key, lsp_addrs->ea_s); if (is_external) { ds_put_format(&match, " && is_chassis_resident(%s)", op->json_key); } - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_DHCP_RESPONSE, 100, - ds_cstr(&match), - ds_cstr(&response_action), - &op->nbsp->dhcpv4_options->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100, + ds_cstr(&match), ds_cstr(&response_action), inport->key, + &op->nbsp->dhcpv4_options->header_); ds_destroy(&options_action); ds_destroy(&response_action); ds_destroy(&ipv4_addr_match); @@ -6914,7 +6943,7 @@ build_dhcpv4_options_flows(struct ovn_port *op, static void build_dhcpv6_options_flows(struct ovn_port *op, struct lport_addresses *lsp_addrs, - const char *json_key, bool is_external, + struct ovn_port *inport, bool is_external, struct hmap *lflows) { struct ds match = DS_EMPTY_INITIALIZER; @@ -6930,27 +6959,25 @@ build_dhcpv6_options_flows(struct ovn_port *op, &match, "inport == %s && eth.src == %s" " && ip6.dst == ff02::1:2 && udp.src == 546 &&" " udp.dst == 547", - json_key, lsp_addrs->ea_s); + inport->json_key, lsp_addrs->ea_s); if (is_external) { ds_put_format(&match, " && is_chassis_resident(%s)", op->json_key); } - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_DHCP_OPTIONS, 100, - ds_cstr(&match), - ds_cstr(&options_action), - &op->nbsp->dhcpv6_options->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 100, ds_cstr(&match), + ds_cstr(&options_action), inport->key, + &op->nbsp->dhcpv6_options->header_); /* 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_with_hint(lflows, op->od, - S_SWITCH_IN_DHCP_RESPONSE, 100, - ds_cstr(&match), - ds_cstr(&response_action), - &op->nbsp->dhcpv6_options->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 100, + ds_cstr(&match), ds_cstr(&response_action), inport->key, + &op->nbsp->dhcpv6_options->header_); ds_destroy(&options_action); ds_destroy(&response_action); break; @@ -6979,10 +7006,10 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, port->json_key, op->lsp_addrs[i].ea_s, op->json_key, rp->lsp_addrs[k].ipv4_addrs[l].addr_s); - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_EXTERNAL_PORT, - 100, ds_cstr(&match), "drop;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, + ds_cstr(&match), "drop;", port->key, + &op->nbsp->header_); } for (size_t l = 0; l < rp->lsp_addrs[k].n_ipv6_addrs; l++) { ds_clear(&match); @@ -6995,10 +7022,10 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, 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_with_hint(lflows, op->od, - S_SWITCH_IN_EXTERNAL_PORT, 100, - ds_cstr(&match), "drop;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint( + lflows, op->od, S_SWITCH_IN_EXTERNAL_PORT, 100, + ds_cstr(&match), "drop;", port->key, + &op->nbsp->header_); } ds_clear(&match); @@ -7009,10 +7036,11 @@ build_drop_arp_nd_flows_for_unbound_router_ports(struct ovn_port *op, port->json_key, op->lsp_addrs[i].ea_s, rp->lsp_addrs[k].ea_s, op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_EXTERNAL_PORT, - 100, ds_cstr(&match), "drop;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_EXTERNAL_PORT, + 100, ds_cstr(&match), + "drop;", port->key, + &op->nbsp->header_); } } } @@ -7118,9 +7146,10 @@ build_lswitch_arp_nd_responder_skip_local(struct ovn_port *op, (!strcmp(op->nbsp->type, "vtep"))) { ds_clear(match); ds_put_format(match, "inport == %s", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, - 100, ds_cstr(match), "next;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_ARP_ND_RSP, 100, + ds_cstr(match), "next;", op->key, + &op->nbsp->header_); } } } @@ -7177,10 +7206,11 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, "bind_vport(%s, inport); " "next;", op->json_key); - ovn_lflow_add_with_hint(lflows, op->od, - S_SWITCH_IN_ARP_ND_RSP, 100, - ds_cstr(match), ds_cstr(actions), - &vp->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_ARP_ND_RSP, 100, + ds_cstr(match), + ds_cstr(actions), vparent, + &vp->nbsp->header_); } free(tokstr); @@ -7243,10 +7273,11 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, * 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_with_hint(lflows, op->od, - S_SWITCH_IN_ARP_ND_RSP, 100, - ds_cstr(match), "next;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_ARP_ND_RSP, + 100, ds_cstr(match), + "next;", op->key, + &op->nbsp->header_); } /* For ND solicitations, we need to listen for both the @@ -7285,10 +7316,11 @@ build_lswitch_arp_nd_responder_known_ips(struct ovn_port *op, /* 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_with_hint(lflows, op->od, - S_SWITCH_IN_ARP_ND_RSP, 100, - ds_cstr(match), "next;", - &op->nbsp->header_); + ovn_lflow_add_with_lport_and_hint(lflows, op->od, + S_SWITCH_IN_ARP_ND_RSP, + 100, ds_cstr(match), + "next;", op->key, + &op->nbsp->header_); } } } @@ -7428,17 +7460,17 @@ build_lswitch_dhcp_options_and_response(struct ovn_port *op, for (size_t j = 0; j < op->od->n_localnet_ports; j++) { build_dhcpv4_options_flows( op, &op->lsp_addrs[i], - op->od->localnet_ports[j]->json_key, is_external, + op->od->localnet_ports[j], is_external, lflows); build_dhcpv6_options_flows( op, &op->lsp_addrs[i], - op->od->localnet_ports[j]->json_key, is_external, + op->od->localnet_ports[j], is_external, lflows); } } else { - build_dhcpv4_options_flows(op, &op->lsp_addrs[i], op->json_key, + build_dhcpv4_options_flows(op, &op->lsp_addrs[i], op, is_external, lflows); - build_dhcpv6_options_flows(op, &op->lsp_addrs[i], op->json_key, + build_dhcpv6_options_flows(op, &op->lsp_addrs[i], op, is_external, lflows); } } @@ -12849,6 +12881,12 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths, sbrec_logical_flow_set_priority(sbflow, lflow->priority); sbrec_logical_flow_set_match(sbflow, lflow->match); sbrec_logical_flow_set_actions(sbflow, lflow->actions); + if (lflow->io_port) { + struct smap tags = SMAP_INITIALIZER(&tags); + smap_add(&tags, "in_out_port", lflow->io_port); + sbrec_logical_flow_set_tags(sbflow, &tags); + smap_destroy(&tags); + } /* Trim the source locator lflow->where, which looks something like * "ovn/northd/ovn-northd.c:1234", down to just the part following the diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index ceeabe6f3..f4689bf02 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -1635,6 +1635,34 @@ relation Flow( external_ids: Map<string,string> ) +relation FlowWithInOutPort(f: Flow, ioPort: string) + +relation TaggedFlow( + logical_datapath: uuid, + stage: Stage, + priority: integer, + __match: string, + actions: string, + tags: Map<string,string>, + external_ids: Map<string,string> +) +TaggedFlow( + .logical_datapath = f.logical_datapath, + .stage = f.stage, + .priority = f.priority, + .__match = f.__match, + .actions = f.actions, + .tags = map_empty(), + .external_ids = f.external_ids) :- Flow[f]. +TaggedFlow( + .logical_datapath = f.logical_datapath, + .stage = f.stage, + .priority = f.priority, + .__match = f.__match, + .actions = f.actions, + .tags = [ "in_out_port" -> ioPort ], + .external_ids = f.external_ids) :- FlowWithInOutPort(f, ioPort). + /* If this option is 'true' northd will combine logical flows that differ by * logical datapath only by creating a datapath group. */ relation UseLogicalDatapathGroups[bool] @@ -1651,6 +1679,7 @@ relation AggregatedFlow ( priority: integer, __match: string, actions: string, + tags: Map<string,string>, external_ids: Map<string,string> ) AggregatedFlow(.logical_datapaths = g.to_set(), @@ -1658,17 +1687,19 @@ AggregatedFlow(.logical_datapaths = g.to_set(), .priority = priority, .__match = __match, .actions = actions, + .tags = tags, .external_ids = external_ids) :- - Flow(logical_datapath, stage, priority, __match, actions, external_ids), - var g = logical_datapath.group_by((stage, priority, __match, actions, external_ids)), + TaggedFlow(logical_datapath, stage, priority, __match, actions, tags, external_ids), + var g = logical_datapath.group_by((stage, priority, __match, actions, tags, external_ids)), UseLogicalDatapathGroups[true]. AggregatedFlow(.logical_datapaths = set_singleton(logical_datapath), .stage = stage, .priority = priority, .__match = __match, .actions = actions, + .tags = tags, .external_ids = external_ids) :- - Flow(logical_datapath, stage, priority, __match, actions, external_ids), + TaggedFlow(logical_datapath, stage, priority, __match, actions, tags, external_ids), UseLogicalDatapathGroups[false]. for (f in AggregatedFlow()) { @@ -1685,6 +1716,7 @@ for (f in AggregatedFlow()) { .priority = f.priority, .__match = f.__match, .actions = f.actions, + .tags = f.tags, .external_ids = external_ids) } else { var group_uuid = hash128(f.logical_datapaths) in { @@ -1697,6 +1729,7 @@ for (f in AggregatedFlow()) { .priority = f.priority, .__match = f.__match, .actions = f.actions, + .tags = f.tags, .external_ids = external_ids); sb::Out_Logical_DP_Group(._uuid = group_uuid, .datapaths = f.logical_datapaths) } @@ -1893,35 +1926,43 @@ for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "router"}, * as the icmp request went through the logical router * on hostA, not hostB. This would only work with * distributed conntrack state across all chassis. */ - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_IN_PRE_ACL(), - .priority = 110, - .__match = "ip && inport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_OUT_PRE_ACL(), - .priority = 110, - .__match = "ip && outport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_IN_PRE_ACL(), + .priority = 110, + .__match = "ip && inport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name); + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_OUT_PRE_ACL(), + .priority = 110, + .__match = "ip && outport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } for (&SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "localnet"}, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid, .has_stateful_acl = true})) { - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_IN_PRE_ACL(), - .priority = 110, - .__match = "ip && inport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_OUT_PRE_ACL(), - .priority = 110, - .__match = "ip && outport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_IN_PRE_ACL(), + .priority = 110, + .__match = "ip && inport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name); + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_OUT_PRE_ACL(), + .priority = 110, + .__match = "ip && outport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } for (&Switch(._uuid = ls_uuid, .has_stateful_acl = true)) { @@ -2015,18 +2056,22 @@ for (&Switch(._uuid = ls_uuid)) { for (&SwitchPort(.lsp = lsp, .json_name = lsp_name, .sw = &Switch{._uuid = ls_uuid})) if (lsp.__type == "router" or lsp.__type == "localnet") { - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_IN_PRE_LB(), - .priority = 110, - .__match = "ip && inport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)); - Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_OUT_PRE_LB(), - .priority = 110, - .__match = "ip && outport == ${lsp_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_IN_PRE_LB(), + .priority = 110, + .__match = "ip && inport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name); + FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_OUT_PRE_LB(), + .priority = 110, + .__match = "ip && outport == ${lsp_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } relation HasEventElbMeter(has_meter: bool) @@ -2736,15 +2781,17 @@ for (SwitchPortDHCPv4Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, (Some{var server_id}, Some{var server_mac}, Some{var lease_time}) = (options.get("server_id"), options.get("server_mac"), options.get("lease_time")) in var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_ACL(), - .priority = 34000, - .__match = "outport == ${json_string_escape(lsp.name)} " - "&& eth.src == ${server_mac} " - "&& ip4.src == ${server_id} && udp && udp.src == 67 " - "&& udp.dst == 68", - .actions = if (has_stateful) "ct_commit; next;" else "next;", - .external_ids = stage_hint(dhcpv4_options._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_ACL(), + .priority = 34000, + .__match = "outport == ${json_string_escape(lsp.name)} " + "&& eth.src == ${server_mac} " + "&& ip4.src == ${server_id} && udp && udp.src == 67 " + "&& udp.dst == 68", + .actions = if (has_stateful) "ct_commit; next;" else "next;", + .external_ids = stage_hint(dhcpv4_options._uuid)}, + lsp.name) } for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, @@ -2756,15 +2803,17 @@ for (SwitchPortDHCPv6Options(.port = &SwitchPort{.lsp = lsp, .sw = sw}, /* Get the link local IP of the DHCPv6 server from the * server MAC. */ var has_stateful = sw.has_stateful_acl or sw.has_lb_vip in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_ACL(), - .priority = 34000, - .__match = "outport == ${json_string_escape(lsp.name)} " - "&& eth.src == ${server_mac} " - "&& ip6.src == ${server_ip} && udp && udp.src == 547 " - "&& udp.dst == 546", - .actions = if (has_stateful) "ct_commit; next;" else "next;", - .external_ids = stage_hint(dhcpv6_options._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_ACL(), + .priority = 34000, + .__match = "outport == ${json_string_escape(lsp.name)} " + "&& eth.src == ${server_mac} " + "&& ip6.src == ${server_ip} && udp && udp.src == 547 " + "&& udp.dst == 546", + .actions = if (has_stateful) "ct_commit; next;" else "next;", + .external_ids = stage_hint(dhcpv6_options._uuid)}, + lsp.name) } relation QoSAction(qos: uuid, key_action: string, value_action: integer) @@ -3095,12 +3144,14 @@ for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name, .ps_eth_addresses None -> "next;", Some{id} -> "set_queue(${id}); next;" } in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_L2(), - .priority = 50, - .__match = __match, - .actions = actions, - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_L2(), + .priority = 50, + .__match = __match, + .actions = actions, + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } } @@ -3130,12 +3181,14 @@ for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) " && ip4.src == 0.0.0.0" " && ip4.dst == 255.255.255.255" " && udp.src == 68 && udp.dst == 67" in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_IP(), - .priority = 90, - .__match = dhcp_match, - .actions = "next;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_IP(), + .priority = 90, + .__match = dhcp_match, + .actions = "next;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) }; var addrs = { var addrs = vec_empty(); @@ -3153,12 +3206,14 @@ for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) "inport == ${port.json_name} && eth.src == ${ps.ea} && ip4.src == {" ++ addrs.join(", ") ++ "}" in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_IP(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_IP(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } }; if (ps.ipv6_addrs.len() > 0) { @@ -3178,22 +3233,26 @@ for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) var __match = "inport == ${port.json_name} && eth.src == ${ps.ea}" ++ build_port_security_ipv6_flow(Ingress, ps.ea, ps.ipv6_addrs) in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_IP(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_IP(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } }; var __match = "inport == ${port.json_name} && eth.src == ${ps.ea} && ip" in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_IP(), - .priority = 80, - .__match = __match, - .actions = "drop;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_IP(), + .priority = 80, + .__match = __match, + .actions = "drop;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } } @@ -3236,32 +3295,38 @@ for (SwitchPortPSAddresses(.port = port@&SwitchPort{.sw = sw}, .ps_addrs = ps) prefix } } in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_ND(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_ND(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } }; if (not ps.ipv6_addrs.is_empty() or no_ip) { var __match = "inport == ${port.json_name} && eth.src == ${ps.ea}" ++ build_port_security_ipv6_nd_flow(ps.ea, ps.ipv6_addrs) in { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_ND(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_ND(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } }; - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_PORT_SEC_ND(), - .priority = 80, - .__match = "inport == ${port.json_name} && (arp || nd)", - .actions = "drop;", - .external_ids = stage_hint(port.lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_PORT_SEC_ND(), + .priority = 80, + .__match = "inport == ${port.json_name} && (arp || nd)", + .actions = "drop;", + .external_ids = stage_hint(port.lsp._uuid)}, + port.lsp.name) } } @@ -3289,12 +3354,14 @@ for (&SwitchPort(.lsp = lsp, .sw = sw, .json_name = json_name) if lsp.is_enabled() and (lsp.__type == "localnet" or lsp.__type == "vtep")) { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_ARP_ND_RSP(), - .priority = 100, - .__match = "inport == ${json_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_ARP_ND_RSP(), + .priority = 100, + .__match = "inport == ${json_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } function lsp_is_up(lsp: Intern<nb::Logical_Switch_Port>): bool = { @@ -3310,14 +3377,16 @@ function lsp_is_up(lsp: Intern<nb::Logical_Switch_Port>): bool = { * - ARP reply from the virtual ip which belongs to a logical * port of type 'virtual' and bind that port. * */ - Flow(.logical_datapath = sp.sw._uuid, - .stage = s_SWITCH_IN_ARP_ND_RSP(), - .priority = 100, - .__match = "inport == ${vp.json_name} && " - "((arp.op == 1 && arp.spa == ${virtual_ip} && arp.tpa == ${virtual_ip}) || " - "(arp.op == 2 && arp.spa == ${virtual_ip}))", - .actions = "bind_vport(${sp.json_name}, inport); next;", - .external_ids = stage_hint(lsp._uuid)) :- + FlowWithInOutPort( + Flow{.logical_datapath = sp.sw._uuid, + .stage = s_SWITCH_IN_ARP_ND_RSP(), + .priority = 100, + .__match = "inport == ${vp.json_name} && " + "((arp.op == 1 && arp.spa == ${virtual_ip} && arp.tpa == ${virtual_ip}) || " + "(arp.op == 2 && arp.spa == ${virtual_ip}))", + .actions = "bind_vport(${sp.json_name}, inport); next;", + .external_ids = stage_hint(lsp._uuid)}, + vp.lsp.name) :- sp in &SwitchPort(.lsp = lsp@&nb::Logical_Switch_Port{.__type = "virtual"}), Some{var virtual_ip} = lsp.options.get("virtual-ip"), Some{var virtual_parents} = lsp.options.get("virtual-parents"), @@ -3373,12 +3442,14 @@ for (CheckLspIsUp[check_lsp_is_up]) { * detect situations where the network is not working as * configured, so dropping the request would frustrate that * intent.) */ - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_ARP_ND_RSP(), - .priority = 100, - .__match = __match ++ " && inport == ${json_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_ARP_ND_RSP(), + .priority = 100, + .__match = __match ++ " && inport == ${json_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } } } @@ -3451,12 +3522,14 @@ for (SwitchPortIPv6Address(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam /* Do not reply to a solicitation from the port that owns the * address (otherwise DAD detection will fail). */ - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_IN_ARP_ND_RSP(), - .priority = 100, - .__match = __match ++ " && inport == ${json_name}", - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_IN_ARP_ND_RSP(), + .priority = 100, + .__match = __match ++ " && inport == ${json_name}", + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } } @@ -4032,15 +4105,17 @@ for (IgmpSwitchMulticastGroup(.address = address, .switch = sw)) { * chassis, drop ARP requests arriving on localnet ports from X's Ethernet * address, if the ARP request is asking to translate the IP address of a * router port on LS. */ -Flow(.logical_datapath = sp.sw._uuid, - .stage = s_SWITCH_IN_EXTERNAL_PORT(), - .priority = 100, - .__match = ("inport == ${json_string_escape(localnet_port.1)} && " - "eth.src == ${lp_addr.ea} && " - "!is_chassis_resident(${sp.json_name}) && " - "arp.tpa == ${rp_addr.addr} && arp.op == 1"), - .actions = "drop;", - .external_ids = stage_hint(sp.lsp._uuid)) :- +FlowWithInOutPort( + Flow{.logical_datapath = sp.sw._uuid, + .stage = s_SWITCH_IN_EXTERNAL_PORT(), + .priority = 100, + .__match = ("inport == ${json_string_escape(localnet_port.1)} && " + "eth.src == ${lp_addr.ea} && " + "!is_chassis_resident(${sp.json_name}) && " + "arp.tpa == ${rp_addr.addr} && arp.op == 1"), + .actions = "drop;", + .external_ids = stage_hint(sp.lsp._uuid)}, + localnet_port.1) :- sp in &SwitchPort(), sp.lsp.__type == "external", var localnet_port = FlatMap(sp.sw.localnet_ports), @@ -4048,16 +4123,18 @@ Flow(.logical_datapath = sp.sw._uuid, rp in &SwitchPort(.sw = sp.sw), rp.lsp.__type == "router", SwitchPortIPv4Address(.port = rp, .addr = rp_addr). -Flow(.logical_datapath = sp.sw._uuid, - .stage = s_SWITCH_IN_EXTERNAL_PORT(), - .priority = 100, - .__match = ("inport == ${json_string_escape(localnet_port.1)} && " - "eth.src == ${lp_addr.ea} && " - "!is_chassis_resident(${sp.json_name}) && " - "nd_ns && ip6.dst == {${rp_addr.addr}, ${rp_addr.solicited_node()}} && " - "nd.target == ${rp_addr.addr}"), - .actions = "drop;", - .external_ids = stage_hint(sp.lsp._uuid)) :- +FlowWithInOutPort( + Flow{.logical_datapath = sp.sw._uuid, + .stage = s_SWITCH_IN_EXTERNAL_PORT(), + .priority = 100, + .__match = ("inport == ${json_string_escape(localnet_port.1)} && " + "eth.src == ${lp_addr.ea} && " + "!is_chassis_resident(${sp.json_name}) && " + "nd_ns && ip6.dst == {${rp_addr.addr}, ${rp_addr.solicited_node()}} && " + "nd.target == ${rp_addr.addr}"), + .actions = "drop;", + .external_ids = stage_hint(sp.lsp._uuid)}, + localnet_port.1) :- sp in &SwitchPort(), sp.lsp.__type == "external", var localnet_port = FlatMap(sp.sw.localnet_ports), @@ -4065,15 +4142,17 @@ Flow(.logical_datapath = sp.sw._uuid, rp in &SwitchPort(.sw = sp.sw), rp.lsp.__type == "router", SwitchPortIPv6Address(.port = rp, .addr = rp_addr). -Flow(.logical_datapath = sp.sw._uuid, - .stage = s_SWITCH_IN_EXTERNAL_PORT(), - .priority = 100, - .__match = ("inport == ${json_string_escape(localnet_port.1)} && " - "eth.src == ${lp_addr.ea} && " - "eth.dst == ${ea} && " - "!is_chassis_resident(${sp.json_name})"), - .actions = "drop;", - .external_ids = stage_hint(sp.lsp._uuid)) :- +FlowWithInOutPort( + Flow{.logical_datapath = sp.sw._uuid, + .stage = s_SWITCH_IN_EXTERNAL_PORT(), + .priority = 100, + .__match = ("inport == ${json_string_escape(localnet_port.1)} && " + "eth.src == ${lp_addr.ea} && " + "eth.dst == ${ea} && " + "!is_chassis_resident(${sp.json_name})"), + .actions = "drop;", + .external_ids = stage_hint(sp.lsp._uuid)}, + localnet_port.1) :- sp in &SwitchPort(), sp.lsp.__type == "external", var localnet_port = FlatMap(sp.sw.localnet_ports), @@ -4450,18 +4529,22 @@ for (&Switch(._uuid = ls_uuid)) { .external_ids = map_empty()) } -Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_IN_LOOKUP_FDB(), - .priority = 100, - .__match = "inport == ${sp.json_name}", - .actions = "$[rEGBIT_LKUP_FDB()} = lookup_fdb(inport, eth.src); next;", - .external_ids = stage_hint(lsp_uuid)), -Flow(.logical_datapath = ls_uuid, - .stage = s_SWITCH_IN_LOOKUP_FDB(), - .priority = 100, - .__match = "inport == ${sp.json_name} && ${rEGBIT_LKUP_FDB()} == 0", - .actions = "put_fdb(inport, eth.src); next;", - .external_ids = stage_hint(lsp_uuid)) :- +FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_IN_LOOKUP_FDB(), + .priority = 100, + .__match = "inport == ${sp.json_name}", + .actions = "$[rEGBIT_LKUP_FDB()} = lookup_fdb(inport, eth.src); next;", + .external_ids = stage_hint(lsp_uuid)}, + sp.lsp.name), +FlowWithInOutPort( + Flow{.logical_datapath = ls_uuid, + .stage = s_SWITCH_IN_LOOKUP_FDB(), + .priority = 100, + .__match = "inport == ${sp.json_name} && ${rEGBIT_LKUP_FDB()} == 0", + .actions = "put_fdb(inport, eth.src); next;", + .external_ids = stage_hint(lsp_uuid)}, + sp.lsp.name) :- LogicalSwitchPortWithUnknownAddress(ls_uuid, lsp_uuid), sp in &SwitchPort(.lsp = &nb::Logical_Switch_Port{._uuid = lsp_uuid, .__type = ""}, .ps_addresses = vec_empty()). @@ -4489,12 +4572,14 @@ Flow(.logical_datapath = ls_uuid, * * Priority 150 rules drop packets to disabled logical ports, so that they * don't even receive multicast or broadcast packets. */ -Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_PORT_SEC_L2(), - .priority = 50, - .__match = __match, - .actions = queue_action ++ "output;", - .external_ids = stage_hint(lsp._uuid)) :- +FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_PORT_SEC_L2(), + .priority = 50, + .__match = __match, + .actions = queue_action ++ "output;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) :- &SwitchPort(.sw = sw, .lsp = lsp, .json_name = json_name, .ps_eth_addresses = ps_eth_addresses), lsp.is_enabled(), lsp.__type != "external", @@ -4512,12 +4597,14 @@ Flow(.logical_datapath = sw._uuid, for (&SwitchPort(.lsp = lsp, .json_name = json_name, .sw = sw) if not lsp.is_enabled() and lsp.__type != "external") { - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_PORT_SEC_L2(), - .priority = 150, - .__match = "outport == {$json_name}", - .actions = "drop;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_PORT_SEC_L2(), + .priority = 150, + .__match = "outport == {$json_name}", + .actions = "drop;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_name, .sw = sw}, @@ -4544,30 +4631,36 @@ for (SwitchPortPSAddresses(.port = &SwitchPort{.lsp = lsp, .json_name = json_nam var __match = "outport == ${json_name} && eth.dst == ${ps.ea} && ip4.dst == {255.255.255.255, 224.0.0.0/4, " ++ addrs.join(", ") ++ "}" in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_PORT_SEC_IP(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_PORT_SEC_IP(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) }; if (ps.ipv6_addrs.len() > 0) { var __match = "outport == ${json_name} && eth.dst == ${ps.ea}" ++ build_port_security_ipv6_flow(Egress, ps.ea, ps.ipv6_addrs) in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_PORT_SEC_IP(), - .priority = 90, - .__match = __match, - .actions = "next;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_PORT_SEC_IP(), + .priority = 90, + .__match = __match, + .actions = "next;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) }; var __match = "outport == ${json_name} && eth.dst == ${ps.ea} && ip" in - Flow(.logical_datapath = sw._uuid, - .stage = s_SWITCH_OUT_PORT_SEC_IP(), - .priority = 80, - .__match = __match, - .actions = "drop;", - .external_ids = stage_hint(lsp._uuid)) + FlowWithInOutPort( + Flow{.logical_datapath = sw._uuid, + .stage = s_SWITCH_OUT_PORT_SEC_IP(), + .priority = 80, + .__match = __match, + .actions = "drop;", + .external_ids = stage_hint(lsp._uuid)}, + lsp.name) } /* Logical router ingress table ADMISSION: Admission control framework. */ diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 5dc910f13..1496a72e5 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -4654,3 +4654,24 @@ AT_CHECK([grep "lr_out_snat" lr0flows | sort], [0], [dnl AT_CLEANUP ]) + +OVN_FOR_EACH_NORTHD([ +AT_SETUP([ovn -- Add tags to logical flows]) +ovn_start + +check ovn-nbctl \ + -- ls-add sw0 \ + -- lb-add lb0 10.0.0.10:80 10.0.0.4:8080 \ + -- ls-lb-add sw0 lb0 + +check ovn-nbctl lsp-add sw0 lsp0 \ + -- lsp-set-addresses lsp0 "00:00:00:00:ff:01 1.2.3.4" \ + -- lsp-set-port-security lsp0 "00:00:00:00:ff:01 1.2.3.4" + +check ovn-nbctl --wait=sb sync +AT_CHECK([ovn-sbctl --columns=tags list logical_flow | grep lsp0 -c], [0], [dnl +9 +]) + +AT_CLEANUP +]) -- 2.30.2 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
