|
|
5f9769 |
From 137b049777cfc301eadba8a2c3b55764bde6f451 Mon Sep 17 00:00:00 2001
|
|
|
5f9769 |
Message-Id: <137b049777cfc301eadba8a2c3b55764bde6f451.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
In-Reply-To: <f21c1b7a467a691847b5552d4570af706fcc5bb0.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
References: <f21c1b7a467a691847b5552d4570af706fcc5bb0.1610458802.git.lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
From: Anton Ivanov <anton.ivanov@cambridgegreys.com>
|
|
|
5f9769 |
Date: Tue, 5 Jan 2021 17:49:34 +0000
|
|
|
5f9769 |
Subject: [PATCH 07/16] ovn-northd: Move destination handling into functions.
|
|
|
5f9769 |
|
|
|
5f9769 |
1. Move igmp/mld destination handling into a function.
|
|
|
5f9769 |
2. Move unicast destination handling into a function.
|
|
|
5f9769 |
|
|
|
5f9769 |
Signed-off-by: Anton Ivanov <anton.ivanov@cambridgegreys.com>
|
|
|
5f9769 |
Signed-off-by: Numan Siddique <numans@ovn.org>
|
|
|
5f9769 |
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
|
|
|
5f9769 |
---
|
|
|
5f9769 |
northd/ovn-northd.c | 433 +++++++++++++++++++++++---------------------
|
|
|
5f9769 |
1 file changed, 223 insertions(+), 210 deletions(-)
|
|
|
5f9769 |
|
|
|
5f9769 |
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
|
|
|
5f9769 |
index f4e248f55..27a788095 100644
|
|
|
5f9769 |
--- a/northd/ovn-northd.c
|
|
|
5f9769 |
+++ b/northd/ovn-northd.c
|
|
|
5f9769 |
@@ -6769,8 +6769,7 @@ is_vlan_transparent(const struct ovn_datapath *od)
|
|
|
5f9769 |
|
|
|
5f9769 |
static void
|
|
|
5f9769 |
build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
5f9769 |
- struct hmap *lflows, struct hmap *mcgroups,
|
|
|
5f9769 |
- struct hmap *igmp_groups)
|
|
|
5f9769 |
+ struct hmap *lflows)
|
|
|
5f9769 |
{
|
|
|
5f9769 |
/* This flow table structure is documented in ovn-northd(8), so please
|
|
|
5f9769 |
* update ovn-northd.8.xml if you change anything. */
|
|
|
5f9769 |
@@ -6778,212 +6777,6 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
5f9769 |
struct ds match = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
struct ds actions = DS_EMPTY_INITIALIZER;
|
|
|
5f9769 |
struct ovn_datapath *od;
|
|
|
5f9769 |
- struct ovn_port *op;
|
|
|
5f9769 |
-
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- /* Ingress table 19: Add IP multicast flows learnt from IGMP/MLD
|
|
|
5f9769 |
- * (priority 90). */
|
|
|
5f9769 |
- struct ovn_igmp_group *igmp_group;
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) {
|
|
|
5f9769 |
- if (!igmp_group->datapath) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&match);
|
|
|
5f9769 |
- ds_clear(&actions);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- struct mcast_switch_info *mcast_sw_info =
|
|
|
5f9769 |
- &igmp_group->datapath->mcast_info.sw;
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- if (IN6_IS_ADDR_V4MAPPED(&igmp_group->address)) {
|
|
|
5f9769 |
- /* RFC 4541, section 2.1.2, item 2: Skip groups in the 224.0.0.X
|
|
|
5f9769 |
- * range.
|
|
|
5f9769 |
- */
|
|
|
5f9769 |
- ovs_be32 group_address =
|
|
|
5f9769 |
- in6_addr_get_mapped_ipv4(&igmp_group->address);
|
|
|
5f9769 |
- if (ip_is_local_multicast(group_address)) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- if (mcast_sw_info->active_v4_flows >= mcast_sw_info->table_size) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- mcast_sw_info->active_v4_flows++;
|
|
|
5f9769 |
- ds_put_format(&match, "eth.mcast && ip4 && ip4.dst == %s ",
|
|
|
5f9769 |
- igmp_group->mcgroup.name);
|
|
|
5f9769 |
- } else {
|
|
|
5f9769 |
- /* RFC 4291, section 2.7.1: Skip groups that correspond to all
|
|
|
5f9769 |
- * hosts.
|
|
|
5f9769 |
- */
|
|
|
5f9769 |
- if (ipv6_is_all_hosts(&igmp_group->address)) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- if (mcast_sw_info->active_v6_flows >= mcast_sw_info->table_size) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- mcast_sw_info->active_v6_flows++;
|
|
|
5f9769 |
- ds_put_format(&match, "eth.mcast && ip6 && ip6.dst == %s ",
|
|
|
5f9769 |
- igmp_group->mcgroup.name);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- /* Also flood traffic to all multicast routers with relay enabled. */
|
|
|
5f9769 |
- if (mcast_sw_info->flood_relay) {
|
|
|
5f9769 |
- ds_put_cstr(&actions,
|
|
|
5f9769 |
- "clone { "
|
|
|
5f9769 |
- "outport = \""MC_MROUTER_FLOOD "\"; "
|
|
|
5f9769 |
- "output; "
|
|
|
5f9769 |
- "};");
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- if (mcast_sw_info->flood_static) {
|
|
|
5f9769 |
- ds_put_cstr(&actions,
|
|
|
5f9769 |
- "clone { "
|
|
|
5f9769 |
- "outport =\""MC_STATIC"\"; "
|
|
|
5f9769 |
- "output; "
|
|
|
5f9769 |
- "};");
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- ds_put_format(&actions, "outport = \"%s\"; output; ",
|
|
|
5f9769 |
- igmp_group->mcgroup.name);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ovn_lflow_add_unique(lflows, igmp_group->datapath, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
- 90, ds_cstr(&match), ds_cstr(&actions));
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- /* Ingress table 19: Destination lookup, unicast handling (priority 50), */
|
|
|
5f9769 |
- HMAP_FOR_EACH (op, key_node, ports) {
|
|
|
5f9769 |
- if (!op->nbsp || lsp_is_external(op->nbsp)) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- /* For ports connected to logical routers add flows to bypass the
|
|
|
5f9769 |
- * broadcast flooding of ARP/ND requests in table 19. We direct the
|
|
|
5f9769 |
- * requests only to the router port that owns the IP address.
|
|
|
5f9769 |
- */
|
|
|
5f9769 |
- if (lsp_is_router(op->nbsp)) {
|
|
|
5f9769 |
- build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows,
|
|
|
5f9769 |
- &op->nbsp->header_);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- for (size_t i = 0; i < op->nbsp->n_addresses; i++) {
|
|
|
5f9769 |
- /* Addresses are owned by the logical port.
|
|
|
5f9769 |
- * Ethernet address followed by zero or more IPv4
|
|
|
5f9769 |
- * or IPv6 addresses (or both). */
|
|
|
5f9769 |
- struct eth_addr mac;
|
|
|
5f9769 |
- if (ovs_scan(op->nbsp->addresses[i],
|
|
|
5f9769 |
- ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
- ds_clear(&match);
|
|
|
5f9769 |
- ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
- ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&actions);
|
|
|
5f9769 |
- ds_put_format(&actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
- ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
- 50, ds_cstr(&match),
|
|
|
5f9769 |
- ds_cstr(&actions),
|
|
|
5f9769 |
- &op->nbsp->header_);
|
|
|
5f9769 |
- } else if (!strcmp(op->nbsp->addresses[i], "unknown")) {
|
|
|
5f9769 |
- if (lsp_is_enabled(op->nbsp)) {
|
|
|
5f9769 |
- ovn_multicast_add(mcgroups, &mc_unknown, op);
|
|
|
5f9769 |
- op->od->has_unknown = true;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- } else if (is_dynamic_lsp_address(op->nbsp->addresses[i])) {
|
|
|
5f9769 |
- if (!op->nbsp->dynamic_addresses
|
|
|
5f9769 |
- || !ovs_scan(op->nbsp->dynamic_addresses,
|
|
|
5f9769 |
- ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- ds_clear(&match);
|
|
|
5f9769 |
- ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
- ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&actions);
|
|
|
5f9769 |
- ds_put_format(&actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
- ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
- 50, ds_cstr(&match),
|
|
|
5f9769 |
- ds_cstr(&actions),
|
|
|
5f9769 |
- &op->nbsp->header_);
|
|
|
5f9769 |
- } else if (!strcmp(op->nbsp->addresses[i], "router")) {
|
|
|
5f9769 |
- if (!op->peer || !op->peer->nbrp
|
|
|
5f9769 |
- || !ovs_scan(op->peer->nbrp->mac,
|
|
|
5f9769 |
- ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
- continue;
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- ds_clear(&match);
|
|
|
5f9769 |
- ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
- ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
- if (op->peer->od->l3dgw_port
|
|
|
5f9769 |
- && op->peer->od->l3redirect_port
|
|
|
5f9769 |
- && op->od->n_localnet_ports) {
|
|
|
5f9769 |
- bool add_chassis_resident_check = false;
|
|
|
5f9769 |
- if (op->peer == op->peer->od->l3dgw_port) {
|
|
|
5f9769 |
- /* The peer of this port represents a distributed
|
|
|
5f9769 |
- * gateway port. The destination lookup flow for the
|
|
|
5f9769 |
- * router's distributed gateway port MAC address should
|
|
|
5f9769 |
- * only be programmed on the gateway chassis. */
|
|
|
5f9769 |
- add_chassis_resident_check = true;
|
|
|
5f9769 |
- } else {
|
|
|
5f9769 |
- /* Check if the option 'reside-on-redirect-chassis'
|
|
|
5f9769 |
- * is set to true on the peer port. If set to true
|
|
|
5f9769 |
- * and if the logical switch has a localnet port, it
|
|
|
5f9769 |
- * means the router pipeline for the packets from
|
|
|
5f9769 |
- * this logical switch should be run on the chassis
|
|
|
5f9769 |
- * hosting the gateway port.
|
|
|
5f9769 |
- */
|
|
|
5f9769 |
- add_chassis_resident_check = smap_get_bool(
|
|
|
5f9769 |
- &op->peer->nbrp->options,
|
|
|
5f9769 |
- "reside-on-redirect-chassis", false);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- if (add_chassis_resident_check) {
|
|
|
5f9769 |
- ds_put_format(&match, " && is_chassis_resident(%s)",
|
|
|
5f9769 |
- op->peer->od->l3redirect_port->json_key);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&actions);
|
|
|
5f9769 |
- ds_put_format(&actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
- ovn_lflow_add_with_hint(lflows, op->od,
|
|
|
5f9769 |
- S_SWITCH_IN_L2_LKUP, 50,
|
|
|
5f9769 |
- ds_cstr(&match), ds_cstr(&actions),
|
|
|
5f9769 |
- &op->nbsp->header_);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- /* Add ethernet addresses specified in NAT rules on
|
|
|
5f9769 |
- * distributed logical routers. */
|
|
|
5f9769 |
- if (op->peer->od->l3dgw_port
|
|
|
5f9769 |
- && op->peer == op->peer->od->l3dgw_port) {
|
|
|
5f9769 |
- for (int j = 0; j < op->peer->od->nbr->n_nat; j++) {
|
|
|
5f9769 |
- const struct nbrec_nat *nat
|
|
|
5f9769 |
- = op->peer->od->nbr->nat[j];
|
|
|
5f9769 |
- if (!strcmp(nat->type, "dnat_and_snat")
|
|
|
5f9769 |
- && nat->logical_port && nat->external_mac
|
|
|
5f9769 |
- && eth_addr_from_string(nat->external_mac, &mac)) {
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&match);
|
|
|
5f9769 |
- ds_put_format(&match, "eth.dst == "ETH_ADDR_FMT
|
|
|
5f9769 |
- " && is_chassis_resident(\"%s\")",
|
|
|
5f9769 |
- ETH_ADDR_ARGS(mac),
|
|
|
5f9769 |
- nat->logical_port);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- ds_clear(&actions);
|
|
|
5f9769 |
- ds_put_format(&actions, "outport = %s; output;",
|
|
|
5f9769 |
- op->json_key);
|
|
|
5f9769 |
- ovn_lflow_add_with_hint(lflows, op->od,
|
|
|
5f9769 |
- S_SWITCH_IN_L2_LKUP, 50,
|
|
|
5f9769 |
- ds_cstr(&match),
|
|
|
5f9769 |
- ds_cstr(&actions),
|
|
|
5f9769 |
- &op->nbsp->header_);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- } else {
|
|
|
5f9769 |
- static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
|
|
|
5f9769 |
-
|
|
|
5f9769 |
- VLOG_INFO_RL(&rl,
|
|
|
5f9769 |
- "%s: invalid syntax '%s' in addresses column",
|
|
|
5f9769 |
- op->nbsp->name, op->nbsp->addresses[i]);
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
- }
|
|
|
5f9769 |
|
|
|
5f9769 |
/* Ingress table 19: Destination lookup for unknown MACs (priority 0). */
|
|
|
5f9769 |
HMAP_FOR_EACH (od, key_node, datapaths) {
|
|
|
5f9769 |
@@ -7492,6 +7285,218 @@ build_lswitch_destination_lookup_bmcast(struct ovn_datapath *od,
|
|
|
5f9769 |
}
|
|
|
5f9769 |
}
|
|
|
5f9769 |
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+/* Ingress table 19: Add IP multicast flows learnt from IGMP/MLD
|
|
|
5f9769 |
+ * (priority 90). */
|
|
|
5f9769 |
+static void
|
|
|
5f9769 |
+build_lswitch_ip_mcast_igmp_mld(struct ovn_igmp_group *igmp_group,
|
|
|
5f9769 |
+ struct hmap *lflows,
|
|
|
5f9769 |
+ struct ds *actions,
|
|
|
5f9769 |
+ struct ds *match)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ if (igmp_group->datapath) {
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(match);
|
|
|
5f9769 |
+ ds_clear(actions);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ struct mcast_switch_info *mcast_sw_info =
|
|
|
5f9769 |
+ &igmp_group->datapath->mcast_info.sw;
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (IN6_IS_ADDR_V4MAPPED(&igmp_group->address)) {
|
|
|
5f9769 |
+ /* RFC 4541, section 2.1.2, item 2: Skip groups in the 224.0.0.X
|
|
|
5f9769 |
+ * range.
|
|
|
5f9769 |
+ */
|
|
|
5f9769 |
+ ovs_be32 group_address =
|
|
|
5f9769 |
+ in6_addr_get_mapped_ipv4(&igmp_group->address);
|
|
|
5f9769 |
+ if (ip_is_local_multicast(group_address)) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (mcast_sw_info->active_v4_flows >= mcast_sw_info->table_size) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ mcast_sw_info->active_v4_flows++;
|
|
|
5f9769 |
+ ds_put_format(match, "eth.mcast && ip4 && ip4.dst == %s ",
|
|
|
5f9769 |
+ igmp_group->mcgroup.name);
|
|
|
5f9769 |
+ } else {
|
|
|
5f9769 |
+ /* RFC 4291, section 2.7.1: Skip groups that correspond to all
|
|
|
5f9769 |
+ * hosts.
|
|
|
5f9769 |
+ */
|
|
|
5f9769 |
+ if (ipv6_is_all_hosts(&igmp_group->address)) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (mcast_sw_info->active_v6_flows >= mcast_sw_info->table_size) {
|
|
|
5f9769 |
+ return;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ mcast_sw_info->active_v6_flows++;
|
|
|
5f9769 |
+ ds_put_format(match, "eth.mcast && ip6 && ip6.dst == %s ",
|
|
|
5f9769 |
+ igmp_group->mcgroup.name);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ /* Also flood traffic to all multicast routers with relay enabled. */
|
|
|
5f9769 |
+ if (mcast_sw_info->flood_relay) {
|
|
|
5f9769 |
+ ds_put_cstr(actions,
|
|
|
5f9769 |
+ "clone { "
|
|
|
5f9769 |
+ "outport = \""MC_MROUTER_FLOOD "\"; "
|
|
|
5f9769 |
+ "output; "
|
|
|
5f9769 |
+ "};");
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ if (mcast_sw_info->flood_static) {
|
|
|
5f9769 |
+ ds_put_cstr(actions,
|
|
|
5f9769 |
+ "clone { "
|
|
|
5f9769 |
+ "outport =\""MC_STATIC"\"; "
|
|
|
5f9769 |
+ "output; "
|
|
|
5f9769 |
+ "};");
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ ds_put_format(actions, "outport = \"%s\"; output; ",
|
|
|
5f9769 |
+ igmp_group->mcgroup.name);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ovn_lflow_add_unique(lflows, igmp_group->datapath, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
+ 90, ds_cstr(match), ds_cstr(actions));
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+/* Ingress table 19: Destination lookup, unicast handling (priority 50), */
|
|
|
5f9769 |
+static void
|
|
|
5f9769 |
+build_lswitch_ip_unicast_lookup(struct ovn_port *op,
|
|
|
5f9769 |
+ struct hmap *lflows,
|
|
|
5f9769 |
+ struct hmap *mcgroups,
|
|
|
5f9769 |
+ struct ds *actions,
|
|
|
5f9769 |
+ struct ds *match)
|
|
|
5f9769 |
+{
|
|
|
5f9769 |
+ if (op->nbsp && (!lsp_is_external(op->nbsp))) {
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ /* For ports connected to logical routers add flows to bypass the
|
|
|
5f9769 |
+ * broadcast flooding of ARP/ND requests in table 19. We direct the
|
|
|
5f9769 |
+ * requests only to the router port that owns the IP address.
|
|
|
5f9769 |
+ */
|
|
|
5f9769 |
+ if (lsp_is_router(op->nbsp)) {
|
|
|
5f9769 |
+ build_lswitch_rport_arp_req_flows(op->peer, op->od, op, lflows,
|
|
|
5f9769 |
+ &op->nbsp->header_);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ for (size_t i = 0; i < op->nbsp->n_addresses; i++) {
|
|
|
5f9769 |
+ /* Addresses are owned by the logical port.
|
|
|
5f9769 |
+ * Ethernet address followed by zero or more IPv4
|
|
|
5f9769 |
+ * or IPv6 addresses (or both). */
|
|
|
5f9769 |
+ struct eth_addr mac;
|
|
|
5f9769 |
+ if (ovs_scan(op->nbsp->addresses[i],
|
|
|
5f9769 |
+ ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
+ ds_clear(match);
|
|
|
5f9769 |
+ ds_put_format(match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
+ ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(actions);
|
|
|
5f9769 |
+ ds_put_format(actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
+ 50, ds_cstr(match),
|
|
|
5f9769 |
+ ds_cstr(actions),
|
|
|
5f9769 |
+ &op->nbsp->header_);
|
|
|
5f9769 |
+ } else if (!strcmp(op->nbsp->addresses[i], "unknown")) {
|
|
|
5f9769 |
+ if (lsp_is_enabled(op->nbsp)) {
|
|
|
5f9769 |
+ ovn_multicast_add(mcgroups, &mc_unknown, op);
|
|
|
5f9769 |
+ op->od->has_unknown = true;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ } else if (is_dynamic_lsp_address(op->nbsp->addresses[i])) {
|
|
|
5f9769 |
+ if (!op->nbsp->dynamic_addresses
|
|
|
5f9769 |
+ || !ovs_scan(op->nbsp->dynamic_addresses,
|
|
|
5f9769 |
+ ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
+ continue;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ ds_clear(match);
|
|
|
5f9769 |
+ ds_put_format(match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
+ ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(actions);
|
|
|
5f9769 |
+ ds_put_format(actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od, S_SWITCH_IN_L2_LKUP,
|
|
|
5f9769 |
+ 50, ds_cstr(match),
|
|
|
5f9769 |
+ ds_cstr(actions),
|
|
|
5f9769 |
+ &op->nbsp->header_);
|
|
|
5f9769 |
+ } else if (!strcmp(op->nbsp->addresses[i], "router")) {
|
|
|
5f9769 |
+ if (!op->peer || !op->peer->nbrp
|
|
|
5f9769 |
+ || !ovs_scan(op->peer->nbrp->mac,
|
|
|
5f9769 |
+ ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(mac))) {
|
|
|
5f9769 |
+ continue;
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ ds_clear(match);
|
|
|
5f9769 |
+ ds_put_format(match, "eth.dst == "ETH_ADDR_FMT,
|
|
|
5f9769 |
+ ETH_ADDR_ARGS(mac));
|
|
|
5f9769 |
+ if (op->peer->od->l3dgw_port
|
|
|
5f9769 |
+ && op->peer->od->l3redirect_port
|
|
|
5f9769 |
+ && op->od->n_localnet_ports) {
|
|
|
5f9769 |
+ bool add_chassis_resident_check = false;
|
|
|
5f9769 |
+ if (op->peer == op->peer->od->l3dgw_port) {
|
|
|
5f9769 |
+ /* The peer of this port represents a distributed
|
|
|
5f9769 |
+ * gateway port. The destination lookup flow for the
|
|
|
5f9769 |
+ * router's distributed gateway port MAC address should
|
|
|
5f9769 |
+ * only be programmed on the gateway chassis. */
|
|
|
5f9769 |
+ add_chassis_resident_check = true;
|
|
|
5f9769 |
+ } else {
|
|
|
5f9769 |
+ /* Check if the option 'reside-on-redirect-chassis'
|
|
|
5f9769 |
+ * is set to true on the peer port. If set to true
|
|
|
5f9769 |
+ * and if the logical switch has a localnet port, it
|
|
|
5f9769 |
+ * means the router pipeline for the packets from
|
|
|
5f9769 |
+ * this logical switch should be run on the chassis
|
|
|
5f9769 |
+ * hosting the gateway port.
|
|
|
5f9769 |
+ */
|
|
|
5f9769 |
+ add_chassis_resident_check = smap_get_bool(
|
|
|
5f9769 |
+ &op->peer->nbrp->options,
|
|
|
5f9769 |
+ "reside-on-redirect-chassis", false);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ if (add_chassis_resident_check) {
|
|
|
5f9769 |
+ ds_put_format(match, " && is_chassis_resident(%s)",
|
|
|
5f9769 |
+ op->peer->od->l3redirect_port->json_key);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(actions);
|
|
|
5f9769 |
+ ds_put_format(actions, "outport = %s; output;", op->json_key);
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od,
|
|
|
5f9769 |
+ S_SWITCH_IN_L2_LKUP, 50,
|
|
|
5f9769 |
+ ds_cstr(match), ds_cstr(actions),
|
|
|
5f9769 |
+ &op->nbsp->header_);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ /* Add ethernet addresses specified in NAT rules on
|
|
|
5f9769 |
+ * distributed logical routers. */
|
|
|
5f9769 |
+ if (op->peer->od->l3dgw_port
|
|
|
5f9769 |
+ && op->peer == op->peer->od->l3dgw_port) {
|
|
|
5f9769 |
+ for (int j = 0; j < op->peer->od->nbr->n_nat; j++) {
|
|
|
5f9769 |
+ const struct nbrec_nat *nat
|
|
|
5f9769 |
+ = op->peer->od->nbr->nat[j];
|
|
|
5f9769 |
+ if (!strcmp(nat->type, "dnat_and_snat")
|
|
|
5f9769 |
+ && nat->logical_port && nat->external_mac
|
|
|
5f9769 |
+ && eth_addr_from_string(nat->external_mac, &mac)) {
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(match);
|
|
|
5f9769 |
+ ds_put_format(match, "eth.dst == "ETH_ADDR_FMT
|
|
|
5f9769 |
+ " && is_chassis_resident(\"%s\")",
|
|
|
5f9769 |
+ ETH_ADDR_ARGS(mac),
|
|
|
5f9769 |
+ nat->logical_port);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ ds_clear(actions);
|
|
|
5f9769 |
+ ds_put_format(actions, "outport = %s; output;",
|
|
|
5f9769 |
+ op->json_key);
|
|
|
5f9769 |
+ ovn_lflow_add_with_hint(lflows, op->od,
|
|
|
5f9769 |
+ S_SWITCH_IN_L2_LKUP, 50,
|
|
|
5f9769 |
+ ds_cstr(match),
|
|
|
5f9769 |
+ ds_cstr(actions),
|
|
|
5f9769 |
+ &op->nbsp->header_);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ } else {
|
|
|
5f9769 |
+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
|
|
|
5f9769 |
+
|
|
|
5f9769 |
+ VLOG_INFO_RL(&rl,
|
|
|
5f9769 |
+ "%s: invalid syntax '%s' in addresses column",
|
|
|
5f9769 |
+ op->nbsp->name, op->nbsp->addresses[i]);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
+}
|
|
|
5f9769 |
+
|
|
|
5f9769 |
/* Returns a string of the IP address of the router port 'op' that
|
|
|
5f9769 |
* overlaps with 'ip_s". If one is not found, returns NULL.
|
|
|
5f9769 |
*
|
|
|
5f9769 |
@@ -11384,6 +11389,8 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
|
|
|
5f9769 |
&lsi->match);
|
|
|
5f9769 |
build_lswitch_dhcp_options_and_response(op,lsi->lflows);
|
|
|
5f9769 |
build_lswitch_external_port(op, lsi->lflows);
|
|
|
5f9769 |
+ build_lswitch_ip_unicast_lookup(op, lsi->lflows, lsi->mcgroups,
|
|
|
5f9769 |
+ &lsi->actions, &lsi->match);
|
|
|
5f9769 |
|
|
|
5f9769 |
/* Build Logical Router Flows. */
|
|
|
5f9769 |
build_adm_ctrl_flows_for_lrouter_port(op, lsi->lflows, &lsi->match,
|
|
|
5f9769 |
@@ -11412,6 +11419,7 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
5f9769 |
struct ovn_datapath *od;
|
|
|
5f9769 |
struct ovn_port *op;
|
|
|
5f9769 |
struct ovn_northd_lb *lb;
|
|
|
5f9769 |
+ struct ovn_igmp_group *igmp_group;
|
|
|
5f9769 |
|
|
|
5f9769 |
char *svc_check_match = xasprintf("eth.dst == %s", svc_monitor_mac);
|
|
|
5f9769 |
|
|
|
5f9769 |
@@ -11443,14 +11451,19 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
|
|
|
5f9769 |
&lsi.actions,
|
|
|
5f9769 |
&lsi.match);
|
|
|
5f9769 |
}
|
|
|
5f9769 |
+ HMAP_FOR_EACH (igmp_group, hmap_node, igmp_groups) {
|
|
|
5f9769 |
+ build_lswitch_ip_mcast_igmp_mld(igmp_group,
|
|
|
5f9769 |
+ lsi.lflows,
|
|
|
5f9769 |
+ &lsi.actions,
|
|
|
5f9769 |
+ &lsi.match);
|
|
|
5f9769 |
+ }
|
|
|
5f9769 |
free(svc_check_match);
|
|
|
5f9769 |
|
|
|
5f9769 |
ds_destroy(&lsi.match);
|
|
|
5f9769 |
ds_destroy(&lsi.actions);
|
|
|
5f9769 |
|
|
|
5f9769 |
/* Legacy lswitch build - to be migrated. */
|
|
|
5f9769 |
- build_lswitch_flows(datapaths, ports, lflows, mcgroups,
|
|
|
5f9769 |
- igmp_groups);
|
|
|
5f9769 |
+ build_lswitch_flows(datapaths, ports, lflows);
|
|
|
5f9769 |
|
|
|
5f9769 |
/* Legacy lrouter build - to be migrated. */
|
|
|
5f9769 |
build_lrouter_flows(datapaths, ports, lflows, meter_groups, lbs);
|
|
|
5f9769 |
--
|
|
|
5f9769 |
2.29.2
|
|
|
5f9769 |
|