From patchwork Tue Aug 17 17:51:29 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1517777 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=2605:bc80:3010::138; helo=smtp1.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=So6hhNkq; dkim-atps=neutral Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GpzB44bvQz9sVq for ; Wed, 18 Aug 2021 03:51:56 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 9D43280D09; Tue, 17 Aug 2021 17:51:53 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7WPOYQZo67ac; Tue, 17 Aug 2021 17:51:49 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [IPv6:2605:bc80:3010:104::8cd3:938]) by smtp1.osuosl.org (Postfix) with ESMTPS id 021D280CF7; Tue, 17 Aug 2021 17:51:49 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id CA1E2C0010; Tue, 17 Aug 2021 17:51:48 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1FAA7C000E for ; Tue, 17 Aug 2021 17:51:48 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id 0F39A606C6 for ; Tue, 17 Aug 2021 17:51:48 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Authentication-Results: smtp3.osuosl.org (amavisd-new); dkim=pass (1024-bit key) header.d=redhat.com Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id N9px-M6vE9xR for ; Tue, 17 Aug 2021 17:51:43 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by smtp3.osuosl.org (Postfix) with ESMTPS id 23CE0605E5 for ; Tue, 17 Aug 2021 17:51:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1629222701; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=PMwR7ORBh4E/30ULBIDfl7VbVSvwuKwKREg958dvlo0=; b=So6hhNkqVBss3l+3xRifZo/Riyeii+3WWfcJ+SwST/mCWftN21vCeSTNOhk2JnK4JrIpmL aur899nGHzMGJyFeiwfxn9pNouonc5F/aXav+zpqymV2AZXcPa0p0lc1lYER9uQRNGVskO 3aVtXKGBT+cqLTm+nG9fqIiXD2GaDpM= Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-154-RvsvLsbLPRypaDZOyU9KvA-1; Tue, 17 Aug 2021 13:51:35 -0400 X-MC-Unique: RvsvLsbLPRypaDZOyU9KvA-1 Received: by mail-wr1-f71.google.com with SMTP id q19-20020adfbb93000000b00156a96f5178so3513134wrg.11 for ; Tue, 17 Aug 2021 10:51:35 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=PMwR7ORBh4E/30ULBIDfl7VbVSvwuKwKREg958dvlo0=; b=EfuUUDYvxRhbdhREFiRU9GlHbxrirYN4jzDY2y7ZibMVj3Ln8nQfKvz8dmnF8r70Vp lD9zi7yk3sANZcXBWYmWIWQ6MKPiJ6+wd1mz4x/P66UINwo0VlOJYQ8hJ3Mt9zpuxyE3 hsU39t4ncnc/G1heNHVD4UOeLVvdpMHfaomOsutzVZg2szH+yW9zct/C0fLKZZ05+89v FBinOsLu4rk781F4DSe8hEoXS25EcX1Ns148wY9lrYFbZN/uZOvkjASY0bZsYHIJod0H Lr2IWEFaBDLEUrLl+UhI0fvvLOjeO7477Z8oXcCHnuMdaXCBXi+r8e7W9fVrJQGBER/Q jKfA== X-Gm-Message-State: AOAM532qFlQt3YOnfx7w2jSkLMAhafsAUPQTdy2whb3giPNBsZsFrm4p sxRV3ZjJXalFAp9onlTvCYVdxHK3ivLL3om/3PTQSqx/dH9RQRjeouLBt8v3fok6SA1p1txgRLM HfzmMzgtpR0JgpSUQ54f8fVPqQ/zygk7ZHP7vj6lBnPJTooHdChRGfNCwqeywyXvhJY1grmHzot DS3JH4 X-Received: by 2002:adf:e48d:: with SMTP id i13mr5921198wrm.288.1629222694176; Tue, 17 Aug 2021 10:51:34 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz2TWlV/JdO2c+jaZ6K8kHknng5VMkA0llQcCG4XCb0yw/njKXn0yWPOmJNFE1/j76iBsB0hw== X-Received: by 2002:adf:e48d:: with SMTP id i13mr5921156wrm.288.1629222693666; Tue, 17 Aug 2021 10:51:33 -0700 (PDT) Received: from lore-desk.redhat.com (net-47-53-237-136.cust.vodafonedsl.it. [47.53.237.136]) by smtp.gmail.com with ESMTPSA id k3sm2875907wms.28.2021.08.17.10.51.32 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Aug 2021 10:51:33 -0700 (PDT) From: Lorenzo Bianconi To: ovs-dev@openvswitch.org Date: Tue, 17 Aug 2021 19:51:29 +0200 Message-Id: X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH v2 ovn] northd: reduce number of nd_na lb logical flows X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" As it has been already done for IPv4, collapse IPv6 Neighbour Advertisment flows for load balancer using address list and reduce the number of logical flows from N*M to N where N is the number of logical router port and M is the number of Virtual IPs. https://bugzilla.redhat.com/show_bug.cgi?id=1970258 Signed-off-by: Lorenzo Bianconi --- Changes since v1: - rebase on top of ovn master - add DDlog support --- northd/ovn-northd.c | 41 +++++++++++++++++++-------- northd/ovn_northd.dl | 66 ++++++++++++++++++++++++++++++++------------ tests/ovn-northd.at | 36 ++++++++---------------- 3 files changed, 90 insertions(+), 53 deletions(-) diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c index e80876af1..ee08281c3 100644 --- a/northd/ovn-northd.c +++ b/northd/ovn-northd.c @@ -9694,8 +9694,7 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op, ds_put_format(&actions, "%s { " "eth.src = %s; " - "ip6.src = %s; " - "nd.target = %s; " + "ip6.src = nd.target; " "nd.tll = %s; " "outport = inport; " "flags.loopback = 1; " @@ -9703,8 +9702,6 @@ build_lrouter_nd_flow(struct ovn_datapath *od, struct ovn_port *op, "};", action, eth_addr, - ip_address, - ip_address, eth_addr); ovn_lflow_add_with_hint__(lflows, od, S_ROUTER_IN_IP_INPUT, priority, ds_cstr(&match), ds_cstr(&actions), NULL, @@ -11742,7 +11739,6 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, &op->nbrp->header_, lflows); } - const char *ip_address; if (sset_count(&op->od->lb_ips_v4)) { ds_clear(match); if (is_l3dgw_port(op)) { @@ -11763,17 +11759,40 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op, ds_destroy(&load_balancer_ips_v4); } - SSET_FOR_EACH (ip_address, &op->od->lb_ips_v6) { + if (sset_count(&op->od->lb_ips_v6)) { ds_clear(match); + ds_clear(actions); + + struct ds load_balancer_ips_v6 = DS_EMPTY_INITIALIZER; + + ds_put_cstr(&load_balancer_ips_v6, "{ "); + ds_put_and_free_cstr(&load_balancer_ips_v6, + sset_join(&op->od->lb_ips_v6, ", ", " }")); + + ds_put_format(match, "inport == %s && nd_ns && nd.target == %s", + op->json_key, ds_cstr(&load_balancer_ips_v6)); if (is_l3dgw_port(op)) { - ds_put_format(match, "is_chassis_resident(%s)", + ds_put_format(match, " && is_chassis_resident(%s)", op->cr_port->json_key); } + ds_put_format(actions, + "nd_na { " + "eth.src = %s; " + "ip6.src = nd.target; " + "nd.tll = %s; " + "outport = inport; " + "flags.loopback = 1; " + "output; " + "};", + REG_INPORT_ETH_ADDR, + REG_INPORT_ETH_ADDR); + ovn_lflow_add_with_hint__(lflows, op->od, S_ROUTER_IN_IP_INPUT, 90, + ds_cstr(match), ds_cstr(actions), NULL, + copp_meter_get(COPP_ND_NA, + op->od->nbr->copp, + meter_groups), NULL); - build_lrouter_nd_flow(op->od, op, "nd_na", - ip_address, NULL, REG_INPORT_ETH_ADDR, - match, false, 90, NULL, - lflows, meter_groups); + ds_destroy(&load_balancer_ips_v6); } if (!op->od->is_gw_router && !op->od->n_l3dgw_ports) { diff --git a/northd/ovn_northd.dl b/northd/ovn_northd.dl index 6cc5d7248..947637f2a 100644 --- a/northd/ovn_northd.dl +++ b/northd/ovn_northd.dl @@ -5260,6 +5260,44 @@ LogicalRouterNdFlow(router, lrp, "nd_na", ipv6, true, mac, extra_match, drop, pr LogicalRouterArpNdFlow(router, nat@NAT{.external_ip = IPv6{ipv6}}, lrp, mac, extra_match, drop, priority). +relation LogicalRouterNdFlowLB( + lr: Intern, + lrp: Option>, + ip: string, + mac: string, + extra_match: Option, + external_ids: Map) +MeteredFlow(.logical_datapath = lr._uuid, + .stage = s_ROUTER_IN_IP_INPUT(), + .priority = 90, + .__match = __match, + .actions = actions, + .tags = map_empty(), + .controller_meter = lr.copp.get(cOPP_ND_NA()), + .external_ids = external_ids) :- + LogicalRouterNdFlowLB(.lr = lr, .lrp = lrp, .ip = ip, + .mac = mac, .extra_match = extra_match, + .external_ids = external_ids), + var __match = { + var clauses = vec_with_capacity(4); + match (lrp) { + Some{p} -> clauses.push("inport == ${json_string_escape(p.name)}"), + None -> () + }; + clauses.push("nd_ns && nd.target == ${ip}"); + clauses.append(extra_match.to_vec()); + clauses.join(" && ") + }, + var actions = + "nd_na { " + "eth.src = ${mac}; " + "ip6.src = nd.target; " + "nd.tll = ${mac}; " + "outport = inport; " + "flags.loopback = 1; " + "output; " + "};". + relation LogicalRouterArpFlow( lr: Intern, lrp: Option>, @@ -5343,8 +5381,7 @@ MeteredFlow(.logical_datapath = lr._uuid, } else { ("${action} { " "eth.src = ${mac}; " - "ip6.src = ${ip}; " - "nd.target = ${ip}; " + "ip6.src = nd.target; " "nd.tll = ${mac}; " "outport = inport; " "flags.loopback = 1; " @@ -5412,7 +5449,7 @@ var residence_check = match (is_redirect) { true -> Some{"is_chassis_resident(${json_string_escape(chassis_redirect_name(lrp.name))})"}, false -> None } in { - (var all_ips_v4, _) = get_router_load_balancer_ips(router, false) in { + (var all_ips_v4, var all_ips_v6) = get_router_load_balancer_ips(router, false) in { if (not all_ips_v4.is_empty()) { LogicalRouterArpFlow(.lr = router, .lrp = Some{lrp}, @@ -5422,21 +5459,14 @@ var residence_check = match (is_redirect) { .drop = false, .priority = 90, .external_ids = map_empty()) - } - }; - for (RouterLBVIP(.router = &Router{._uuid= lr_uuid}, .vip = vip)) { - Some{(var ip_address, _)} = ip_address_and_port_from_lb_key(vip) in { - IPv6{var ipv6} = ip_address in - LogicalRouterNdFlow(.lr = router, - .lrp = Some{lrp}, - .action = "nd_na", - .ip = ipv6, - .sn_ip = false, - .mac = rEG_INPORT_ETH_ADDR(), - .extra_match = residence_check, - .drop = false, - .priority = 90, - .external_ids = map_empty()) + }; + if (not all_ips_v6.is_empty()) { + LogicalRouterNdFlowLB(.lr = router, + .lrp = Some{lrp}, + .ip = "{ " ++ all_ips_v6.join(", ") ++ " }", + .mac = rEG_INPORT_ETH_ADDR(), + .extra_match = residence_check, + .external_ids = map_empty()) } } } diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at index 190f78261..b55b01f82 100644 --- a/tests/ovn-northd.at +++ b/tests/ovn-northd.at @@ -1698,13 +1698,10 @@ match=(inport == "lrp" && arp.op == 1 && arp.tpa == { 192.168.2.1, 192.168.2.4, action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp" && ip6.dst == {fe80::200:ff:fe00:1, ff02::1:ff00:1} && nd_ns && nd.target == fe80::200:ff:fe00:1), dnl -action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:1; nd.target = fe80::200:ff:fe00:1; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp" && nd_ns && nd.target == fe80::200:ff:fe00:101:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:101:8080; nd.target = fe80::200:ff:fe00:101:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) - table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp" && nd_ns && nd.target == fe80::200:ff:fe00:102:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:102:8080; nd.target = fe80::200:ff:fe00:102:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +match=(inport == "lrp" && nd_ns && nd.target == { fe80::200:ff:fe00:101:8080, fe80::200:ff:fe00:102:8080 }), dnl +action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp-public" && arp.op == 1 && arp.tpa == 43.43.43.1 && arp.spa == 43.43.43.0/24), dnl action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) @@ -1713,13 +1710,10 @@ match=(inport == "lrp-public" && arp.op == 1 && arp.tpa == { 192.168.2.1, 192.16 action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp-public" && ip6.dst == {fe80::200:ff:fe00:100, ff02::1:ff00:100} && nd_ns && nd.target == fe80::200:ff:fe00:100), dnl -action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:100; nd.target = fe80::200:ff:fe00:100; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) - table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp-public" && nd_ns && nd.target == fe80::200:ff:fe00:101:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:101:8080; nd.target = fe80::200:ff:fe00:101:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp-public" && nd_ns && nd.target == fe80::200:ff:fe00:102:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:102:8080; nd.target = fe80::200:ff:fe00:102:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +match=(inport == "lrp-public" && nd_ns && nd.target == { fe80::200:ff:fe00:101:8080, fe80::200:ff:fe00:102:8080 }), dnl +action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) ]) # xreg0[0..47] isn't used anywhere else. @@ -1773,13 +1767,10 @@ match=(inport == "lrp" && arp.op == 1 && arp.tpa == { 192.168.2.1, 192.168.2.4, action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp" && ip6.dst == {fe80::200:ff:fe00:1, ff02::1:ff00:1} && nd_ns && nd.target == fe80::200:ff:fe00:1), dnl -action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:1; nd.target = fe80::200:ff:fe00:1; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp" && nd_ns && nd.target == fe80::200:ff:fe00:101:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:101:8080; nd.target = fe80::200:ff:fe00:101:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) - table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp" && nd_ns && nd.target == fe80::200:ff:fe00:102:8080), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:102:8080; nd.target = fe80::200:ff:fe00:102:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +match=(inport == "lrp" && nd_ns && nd.target == { fe80::200:ff:fe00:101:8080, fe80::200:ff:fe00:102:8080 }), dnl +action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp-public" && arp.op == 1 && arp.tpa == 43.43.43.1 && arp.spa == 43.43.43.0/24), dnl action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) @@ -1788,13 +1779,10 @@ match=(inport == "lrp-public" && arp.op == 1 && arp.tpa == { 192.168.2.1, 192.16 action=(eth.dst = eth.src; eth.src = xreg0[[0..47]]; arp.op = 2; /* ARP reply */ arp.tha = arp.sha; arp.sha = xreg0[[0..47]]; arp.tpa <-> arp.spa; outport = inport; flags.loopback = 1; output;) table=3 (lr_in_ip_input ), priority=90 , dnl match=(inport == "lrp-public" && ip6.dst == {fe80::200:ff:fe00:100, ff02::1:ff00:100} && nd_ns && nd.target == fe80::200:ff:fe00:100 && is_chassis_resident("cr-lrp-public")), dnl -action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:100; nd.target = fe80::200:ff:fe00:100; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) - table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp-public" && nd_ns && nd.target == fe80::200:ff:fe00:101:8080 && is_chassis_resident("cr-lrp-public")), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:101:8080; nd.target = fe80::200:ff:fe00:101:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +action=(nd_na_router { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) table=3 (lr_in_ip_input ), priority=90 , dnl -match=(inport == "lrp-public" && nd_ns && nd.target == fe80::200:ff:fe00:102:8080 && is_chassis_resident("cr-lrp-public")), dnl -action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = fe80::200:ff:fe00:102:8080; nd.target = fe80::200:ff:fe00:102:8080; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) +match=(inport == "lrp-public" && nd_ns && nd.target == { fe80::200:ff:fe00:101:8080, fe80::200:ff:fe00:102:8080 } && is_chassis_resident("cr-lrp-public")), dnl +action=(nd_na { eth.src = xreg0[[0..47]]; ip6.src = nd.target; nd.tll = xreg0[[0..47]]; outport = inport; flags.loopback = 1; output; };) ]) # Priority 91 drop flows (per distributed gw port), if port is not resident.