@@ -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
@@ -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. */
@@ -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
+])
Populate the in_out_port tag for logical switch pipeline flows wherever possible. Signed-off-by: Han Zhou <hzhou@ovn.org> --- northd/ovn-northd.c | 272 ++++++++++++++---------- northd/ovn_northd.dl | 495 +++++++++++++++++++++++++------------------ tests/ovn-northd.at | 21 ++ 3 files changed, 470 insertions(+), 318 deletions(-)