Hi Jakub, On 9/10/25 10:43 PM, Jakub Libosvar wrote: > > >> On Sep 9, 2025, at 9:59 AM, Dumitru Ceara <[email protected]> wrote: >> >> Hi Jakub, >> >> Thanks for the bug report and for the fix! Sorry for the delay in >> reviewing this. >> >> On 7/28/25 7:52 PM, Jakub Libosvar via dev wrote: >>> The logical router port for outport of a logical router was calculated >>> based on the subnet matching of LRPs on the given LR. This doesn't work >>> in case IPv6 local-link addresses are used. >>> >>> The patch introduces a generic function that calculates outport by >>> strict matching on the nexthop address. This function is used when >>> generating the logical flow from the logical router policy. >>> >>> This problem becomes more complex when a router is connected to >>> complicated topology where the L2 domain is stretched over multiple >>> logical switches or even localnet ports. This complex solution is not >>> included in this patch and will be part of a followup patch. >>> >> >> What worries me a bit about this approach is that, in general, the only >> restriction for mac addresses is that they need to be unique in the L2 >> domain they're used in. >> >> Let's consider a topology that's not covered by the cases you tested below: >> >> R1 ------- R2 -------- R3 >> netA netB >> >> We have two IP networks, netA and netB. >> >> In theory R1 and R3 could have the same MAC address, e.g., >> 00:00:00:00:00:01 and that shouldn't cause any routing issues. The only >> constraints are: >> - R1 and R2 should have different MAC addresses on netA >> - R2 and R3 should have different MAC addresses on netB > > I think if there are two same addresses then it’s a problem with the > CMS, it should not be using same MACs as they should be unique as > per EUI-48. In general, the problem you’re describing is not tied to > a MAC address but to “same IP” problem. Same can happen also if netA > and netB use the same IP range and R1 and R2 LRPs have the same IP. >
In my opinion, netA and netB having the same IP range (overlapping subnets) is a misconfiguration and won't work anyway in OVN. >> >> Now, if we add a policy on R2: >> if dst == 2001::/64 then reroute 0000:00ff:fe00:0001 >> >> Then ovn-northd still can't choose any port. Arguably the policy is >> incorrect though, because it's ambiguous. So, in order to fix that, >> what we could do is add support for "output_port" for >> Logical_Router_Policy (like we have for Logical_Router_Static_Route). >> >> The CMS (configuring the policy) should always be able know which >> output_port to configure in these cases? > > yes, output_port works for my use case too and we know what > output_port we want to set when we’re creating the policy. > > For me it is fine, just thinking out loud if a mechanism exists in > northd that can find the “right” output_port then it should also > consider local-link-addresses too. The ambiguity, as I tried to > explain above, also happens with colliding IPs, not necessarily same > MAC addresses. Right, I still think the best we can do in these cases is let the CMS choose (through output_port). >> >>> Same problem seems to exist when finding the outport from the logical >>> router static route. The function responsible for finding the right LRP >>> is genereic enough so it can be re-used later for the static route too >>> in another followup patch. >> >> As mentioned above, I think the CMS should probably be using >> "output_port" for the static routes in these cases. From the man page >> of "output_port": >> >> 'When this is specified and there are multiple IP addresses on the >> router port and none of them are in the same subnet of "nexthop", OVN >> chooses the first IP address as the one via which the "nexthop" is >> reachable.' >> >> If OVN would support output_port for policies too, would that be enough >> for the use case you're targetting? > > Yes :) > OK, I'll work on a patch that adds that. >> >> I had started reviewing the code in this patch but only left some >> comments on the test itself below. I think it's better to first decide >> on the best approach to solve the problem before continuing with the review. > > Thanks a lot for looking at it! > No problem, thanks for the report and patch! Regards, Dumitru > Jakub >> >> Looking forward to hearing back from you! >> >> Regards, >> Dumitru >> >>> >>> Reported-at: https://issues.redhat.com/browse/FDP-1554 >>> Reported-by: Jakub Libosvar <[email protected]> >>> Signed-off-by: Jakub Libosvar <[email protected]> >>> --- >>> northd/northd.c | 257 ++++++++++++++++++++++++++++++++++++++++++-- >>> tests/ovn-northd.at | 117 ++++++++++++++++++++ >>> 2 files changed, 364 insertions(+), 10 deletions(-) >>> >>> diff --git a/northd/northd.c b/northd/northd.c >>> index 764575f21..84dc76770 100644 >>> --- a/northd/northd.c >>> +++ b/northd/northd.c >>> @@ -11080,6 +11080,235 @@ lrp_find_member_ip(const struct ovn_port *op, >>> const char *ip_s) >>> return find_lport_address(&op->lrp_networks, ip_s); >>> } >>> >>> +/* >>> + * Check if the port has the given IPv6 link-local address. >>> + * >>> + * Parameters: >>> + * op: The ovn_port to check >>> + * lla_address: The IPv6 link-local address to check for >>> + * >>> + * Returns: >>> + * true if the port has the given IPv6 link-local address, false >>> otherwise >>> +*/ >>> +static bool lrp_has_ipv6_lla(const struct ovn_port *op, const char >>> *lla_address) >>> +{ >>> + struct in6_addr lla_addr; >>> + if (!ipv6_parse(lla_address, &lla_addr) || !in6_is_lla(&lla_addr)) { >>> + return false; >>> + } >>> + >>> + /* Check for exact LLA match in this port's addresses */ >>> + for (size_t j = 0; j < op->lrp_networks.n_ipv6_addrs; j++) { >>> + struct ipv6_netaddr *addr = &op->lrp_networks.ipv6_addrs[j]; >>> + if (ipv6_addr_equals(&addr->addr, &lla_addr)) { >>> + return true; >>> + } >>> + } >>> + return false; >>> +} >>> + >>> +/* Generic helper function to find router port that can reach IPv6 >>> link-local address. >>> + * >>> + * IPv6 Link-Local Addresses (LLAs) are interface-scoped and require exact >>> + * address matching per RFC 4291, not subnet matching like regular IPv6. >>> + * >>> + * This function searches for the exact LLA in the following order: >>> + * 1. Local router ports on the same router >>> + * 2. Directly peered router ports (peer= connections) >>> + * 3. Router ports reachable via logical switch connections >>> + * 4. Router ports reachable via localnet (same physical network) >>> + * >>> + * Parameters: >>> + * od: The router datapath to search from >>> + * lr_ports: Map of all logical router ports >>> + * lla_address: The IPv6 link-local address string to resolve >>> + * >>> + * Returns: >>> + * The ovn_port that can reach the target LLA, or NULL if not found. >>> + * >>> + * Note: This function is designed to be reusable for both routing policies >>> + * and static routes. The caller determines how to use the returned >>> port. >>> + */ >>> +static struct ovn_port * >>> +find_lrp_for_ipv6_lla(struct ovn_datapath *od, >>> + const struct hmap *lr_ports, >>> + const char *lla_address) >>> +{ >>> + struct in6_addr lla_addr; >>> + if (!ipv6_parse(lla_address, &lla_addr) || >>> + !in6_is_lla(&lla_addr)) { >>> + return NULL; >>> + } >>> + >>> + /* First, check if any of this router's ports has the exact LLA */ >>> + for (int i = 0; i < od->nbr->n_ports; i++) { >>> + struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; >>> + struct ovn_port *out_port = ovn_port_find(lr_ports, lrp->name); >>> + if (!out_port) { >>> + continue; >>> + } >>> + >>> + if (lrp_has_ipv6_lla(out_port, lla_address)) { >>> + return out_port; >>> + } >>> + } >>> + >>> + /* Second, check if the LLA is on a directly peered router port. >>> + * LRPs can be directly connected to other LRPs via the peer column. */ >>> + for (int i = 0; i < od->nbr->n_ports; i++) { >>> + struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; >>> + struct ovn_port *out_port = ovn_port_find(lr_ports, lrp->name); >>> + if (!out_port || !lrp->peer) { >>> + continue; >>> + } >>> + >>> + /* Find the peer LRP */ >>> + struct ovn_port *peer_lrp = ovn_port_find(lr_ports, lrp->peer); >>> + if (!peer_lrp || !peer_lrp->nbrp) { >>> + continue; >>> + } >>> + >>> + /* Check if the peer LRP has the target LLA */ >>> + if (lrp_has_ipv6_lla(peer_lrp, lla_address)) { >>> + return out_port; >>> + } >>> + } >>> + >>> + /* Third, check if the LLA is reachable through logical switch >>> connections. >>> + * We need to find router ports that connect to logical switches which >>> + * might have the target LLA as a connected router port. */ >>> + for (int i = 0; i < od->nbr->n_ports; i++) { >>> + struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; >>> + struct ovn_port *out_port = ovn_port_find(lr_ports, lrp->name); >>> + if (!out_port || !out_port->peer) { >>> + continue; >>> + } >>> + >>> + /* This router port connects to a logical switch */ >>> + struct ovn_datapath *peer_ls = out_port->peer->od; >>> + if (!peer_ls || !peer_ls->nbs) { >>> + continue; >>> + } >>> + >>> + /* Check all router ports connected to this logical switch */ >>> + struct ovn_port *op; >>> + VECTOR_FOR_EACH (&peer_ls->router_ports, op) { >>> + if (!op->peer) { >>> + continue; >>> + } >>> + >>> + /* Get the actual router port (not the switch-side port) */ >>> + struct ovn_port *remote_lrp = op->peer; >>> + if (!remote_lrp || !remote_lrp->nbrp) { >>> + continue; >>> + } >>> + >>> + /* Check if this remote router port has the target LLA */ >>> + if (lrp_has_ipv6_lla(remote_lrp, lla_address)) { >>> + return out_port; >>> + } >>> + } >>> + } >>> + >>> + /* Fourth, complex topologies with localnet connections. >>> + * TODO: For complex topologies, we could search through multiple >>> logical >>> + * switch hops connected via localnet ports on the same physical >>> network. >>> + * This would handle cases like: Router1 -> LS1(localnet) <-> >>> LS2(localnet) -> Router2 >>> + * However, since LLAs are typically link-scoped, we leave this for >>> future >>> + * enhancement and focus on the common direct connection cases above. >>> + */ >>> + >>> + return NULL; >>> +} >>> + >>> +/* Wrapper function for IPv6 LLA nexthop resolution. >>> + * >>> + * Determines if the given nexthop is an IPv6 LLA and resolves it using >>> exact >>> + * address matching. For non-LLA addresses, returns NULL so caller can use >>> + * regular subnet-based matching. >>> + * >>> + * This wrapper is designed for easy integration into both routing policies >>> + * and static routes without duplicating the LLA detection logic. >>> + * >>> + * Returns: >>> + * - Non-NULL: LRP that can reach the IPv6 LLA nexthop >>> + * - NULL: Not an LLA or LLA not found (use regular resolution) >>> + */ >>> +static struct ovn_port * >>> +resolve_ipv6_lla_nexthop(struct ovn_datapath *od, >>> + const struct hmap *lr_ports, >>> + const char *nexthop) >>> +{ >>> + if (!nexthop) { >>> + return NULL; >>> + } >>> + >>> + struct in6_addr nexthop_addr; >>> + if (ipv6_parse(nexthop, &nexthop_addr) && in6_is_lla(&nexthop_addr)) { >>> + return find_lrp_for_ipv6_lla(od, lr_ports, nexthop); >>> + } >>> + >>> + return NULL; /* Not an IPv6 LLA, use regular resolution */ >>> +} >>> + >>> +/* Generic function to find the outport for a given nexthop address. >>> + * >>> + * This function handles all possible OVN topology scenarios for nexthop >>> resolution: >>> + * 1. IPv6 Link-Local Addresses (LLAs) - Uses exact address matching per >>> RFC 4291 >>> + * 2. Regular IPv4/IPv6 addresses - Uses subnet-based matching >>> + * 3. Router-to-router peer connections via peer column >>> + * 4. Router connections through logical switches >>> + * 5. Complex topologies with localnet connections >>> + * >>> + * Parameters: >>> + * od: The source router datapath >>> + * lr_ports: Map of all logical router ports >>> + * nexthop: The nexthop IP address string to resolve >>> + * >>> + * Returns: >>> + * The ovn_port that can reach the nexthop, or NULL if not found. >>> + * >>> + * Note: This function is designed to be reusable across OVN components >>> + * (routing policies, static routes, etc.) without duplicating >>> topology logic. >>> + */ >>> +static struct ovn_port * >>> +get_outport_for_nexthop(struct ovn_datapath *od, >>> + const struct hmap *lr_ports, >>> + const char *nexthop) >>> +{ >>> + if (!nexthop) { >>> + return NULL; >>> + } >>> + >>> + /* Special handling for IPv6 link-local addresses. >>> + * LLAs require exact address matching, not subnet matching. */ >>> + struct ovn_port *lla_port = resolve_ipv6_lla_nexthop(od, lr_ports, >>> nexthop); >>> + if (lla_port) { >>> + return lla_port; >>> + } >>> + >>> + /* Check if this was an LLA that we couldn't resolve. >>> + * For LLAs, we don't fall back to subnet matching as it would be >>> incorrect. */ >>> + struct in6_addr nexthop_addr; >>> + if (ipv6_parse(nexthop, &nexthop_addr) && in6_is_lla(&nexthop_addr)) { >>> + /* LLA nexthop not found - return NULL and let caller handle >>> logging */ >>> + return NULL; >>> + } >>> + >>> + /* For non-LLA addresses (IPv4 and regular IPv6), use subnet-based >>> matching. >>> + * This searches through all router ports to find one whose network >>> contains the nexthop. */ >>> + for (int i = 0; i < od->nbr->n_ports; i++) { >>> + struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; >>> + struct ovn_port *out_port = ovn_port_find(lr_ports, lrp->name); >>> + >>> + if (out_port && lrp_find_member_ip(out_port, nexthop)) { >>> + return out_port; >>> + } >>> + } >>> + >>> + return NULL; >>> +} >>> + >>> static struct ovn_port* >>> get_outport_for_routing_policy_nexthop(struct ovn_datapath *od, >>> const struct hmap *lr_ports, >>> @@ -11089,19 +11318,27 @@ get_outport_for_routing_policy_nexthop(struct >>> ovn_datapath *od, >>> return NULL; >>> } >>> >>> - /* Find the router port matching the next hop. */ >>> - for (int i = 0; i < od->nbr->n_ports; i++) { >>> - struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; >>> - >>> - struct ovn_port *out_port = ovn_port_find(lr_ports, lrp->name); >>> - if (out_port && lrp_find_member_ip(out_port, nexthop)) { >>> - return out_port; >>> - } >>> + /* Use the generic nexthop resolution function */ >>> + struct ovn_port *out_port = get_outport_for_nexthop(od, lr_ports, >>> nexthop); >>> + if (out_port) { >>> + return out_port; >>> } >>> >>> + /* Handle logging for unresolved nexthops with routing policy context >>> */ >>> + struct in6_addr nexthop_addr; >>> + bool is_ipv6_lla = (ipv6_parse(nexthop, &nexthop_addr) && >>> + in6_is_lla(&nexthop_addr)); >>> + >>> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); >>> - VLOG_WARN_RL(&rl, "No path for routing policy priority %d on router >>> %s; " >>> - "next hop %s", priority, od->nbr->name, nexthop); >>> + if (is_ipv6_lla) { >>> + VLOG_WARN_RL(&rl, "IPv6 link-local nexthop %s not found on router >>> %s " >>> + "or reachable logical switches; LLAs require exact >>> address matching", >>> + nexthop, od->nbr->name); >>> + } else { >>> + VLOG_WARN_RL(&rl, "No path for routing policy priority %d on >>> router %s; " >>> + "next hop %s", priority, od->nbr->name, nexthop); >>> + } >>> + >>> return NULL; >>> } >>> >>> diff --git a/tests/ovn-northd.at b/tests/ovn-northd.at >>> index 5ddb15587..00926ac57 100644 >>> --- a/tests/ovn-northd.at >>> +++ b/tests/ovn-northd.at >>> @@ -3643,6 +3643,123 @@ AT_CHECK([grep "lr_in_policy[[^_]]" lr0flows2 | >>> ovn_strip_lflows | sort], [0], [ >>> AT_CLEANUP >>> ]) >>> >>> +OVN_FOR_EACH_NORTHD_NO_HV([ >>> +AT_SETUP([Router policies - IPv6 Link-Local Address (LLA) nexthop]) >> >> Thanks for adding tests! >> >>> +AT_KEYWORDS([router policies ipv6 lla link-local]) >>> +ovn_start >>> + >>> +# Test 1: Valid IPv6 LLA nexthop to peer router >>> +# Create logical switches >> >> Nit: for all comments in this test: comments should be sentences (start >> with a capital letter and end with a dot). >> >>> +check ovn-nbctl ls-add transit-sw >>> + >>> +# Create first router with port >>> +check ovn-nbctl lr-add router1 >>> +check ovn-nbctl lrp-add router1 r1-port1 02:de:ad:be:ef:01 192.168.1.1/24 >>> + >>> +# Connect router1 to transit switch >> >> Nit: "transit switch" is an overloaded term in OVN. I'd call this "sw" >> or something similar. >> >>> +check ovn-nbctl lsp-add transit-sw r1-lsp1 >>> +check ovn-nbctl lsp-set-type r1-lsp1 router >>> +check ovn-nbctl lsp-set-addresses r1-lsp1 router >>> +check ovn-nbctl lsp-set-options r1-lsp1 router-port=r1-port1 >>> + >>> +# Create second router with port >>> +check ovn-nbctl lr-add router2 >>> +check ovn-nbctl lrp-add router2 r2-port1 02:de:ad:be:ef:02 192.168.1.2/24 >>> + >>> +# Connect router2 to same transit switch >>> +check ovn-nbctl lsp-add transit-sw r2-lsp1 >>> +check ovn-nbctl lsp-set-type r2-lsp1 router >>> +check ovn-nbctl lsp-set-addresses r2-lsp1 router >>> +check ovn-nbctl lsp-set-options r2-lsp1 router-port=r2-port1 >>> + >>> +# Add routing policy with valid LLA nexthop pointing to router2's >>> auto-generated LLA >>> +# MAC 02:de:ad:be:ef:02 generates LLA: fe80::de:adff:febe:ef02 >>> +check ovn-nbctl --wait=sb lr-policy-add router1 100 "ip6.dst == >>> 2001:db8::/64" reroute fe80::de:adff:febe:ef02 >>> + >>> +# Verify logical flow was created with correct outport >>> +ovn-sbctl dump-flows router1 > router1flows >>> +AT_CAPTURE_FILE([router1flows]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router1flows | grep "priority=100" | >>> ovn_strip_lflows], [0], [dnl >>> + table=??(lr_in_policy ), priority=100 , match=(ip6.dst == >>> 2001:db8::/64), action=(xxreg0 = fe80::de:adff:febe:ef02; xxreg1 = >>> fe80::de:adff:febe:ef01; eth.src = 02:de:ad:be:ef:01; outport = "r1-port1"; >>> flags.loopback = 1; reg8[[0..15]] = 0; reg9[[9]] = 0; next;) >>> +]) >>> + >>> +# Test 2: Invalid IPv6 LLA nexthop should not create flow >>> +check ovn-nbctl --wait=sb lr-policy-add router1 200 "ip6.dst == >>> 2001:db8:1::/64" reroute fe80::dead:beef:cafe:babe >>> + >>> +# Check that NO flow was created for invalid LLA nexthop (should fail >>> gracefully) >> >> We could maybe check the northd log for the warn message: >> >> WARN|IPv6 link-local nexthop fe80::dead:beef:cafe:babe not found on >> router router1 or reachable logical switches; LLAs require exact address >> matching. >> >>> +ovn-sbctl dump-flows router1 > router1flows2 >>> +AT_CAPTURE_FILE([router1flows2]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router1flows2 | grep "priority=200" | wc >>> -l], [0], [0 >>> +]) >>> + >>> +# Test 3: Regular IPv6 (non-LLA) should still use subnet matching >>> +# First, delete the existing port and recreate it with IPv6 network >>> +check ovn-nbctl lrp-del r1-port1 >>> +check ovn-nbctl lrp-add router1 r1-port1 02:de:ad:be:ef:01 192.168.1.1/24 >>> 2001:db8:1::1/64 >>> +check ovn-nbctl --wait=sb lr-policy-add router1 300 "ip6.dst == >>> 2001:db8:2::/64" reroute 2001:db8:1::100 >>> + >>> +# Verify regular IPv6 routing still works (subnet matching) >>> +ovn-sbctl dump-flows router1 > router1flows3 >>> +AT_CAPTURE_FILE([router1flows3]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router1flows3 | grep "priority=300" | >>> ovn_strip_lflows], [0], [dnl >>> + table=??(lr_in_policy ), priority=300 , match=(ip6.dst == >>> 2001:db8:2::/64), action=(xxreg0 = 2001:db8:1::100; xxreg1 = 2001:db8:1::1; >>> eth.src = 02:de:ad:be:ef:01; outport = "r1-port1"; flags.loopback = 1; >>> reg8[[0..15]] = 0; reg9[[9]] = 0; next;) >>> +]) >>> + >>> +# Test 4: IPv4 routing should remain unchanged >>> +check ovn-nbctl --wait=sb lr-policy-add router1 400 "ip4.dst == >>> 10.0.0.0/16" reroute 192.168.1.100 >>> + >>> +# Verify IPv4 routing still works normally >>> +ovn-sbctl dump-flows router1 > router1flows4 >>> +AT_CAPTURE_FILE([router1flows4]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router1flows4 | grep "priority=400" | >>> ovn_strip_lflows], [0], [dnl >>> + table=??(lr_in_policy ), priority=400 , match=(ip4.dst == >>> 10.0.0.0/16), action=(reg0 = 192.168.1.100; reg5 = 192.168.1.1; eth.src = >>> 02:de:ad:be:ef:01; outport = "r1-port1"; flags.loopback = 1; reg8[[0..15]] >>> = 0; reg9[[9]] = 1; next;) >>> +]) >> >> We also support routing IPv4 packets with IPv6 next-hops. Would it be >> possible to add a test for that too? >> >>> + >>> +# Test 5: Direct LLA on local router port >>> +check ovn-nbctl lr-add router3 >>> +check ovn-nbctl lrp-add router3 r3-port1 02:de:ad:be:ef:03 192.168.2.1/24 >>> + >>> +# Add policy with LLA pointing to router3's own port (should work as >>> direct match) >> >> Hmm, should it though? This blackholes the traffic. >> >>> +# MAC 02:de:ad:be:ef:03 generates LLA: fe80::de:adff:febe:ef03 >>> +check ovn-nbctl --wait=sb lr-policy-add router3 500 "ip6.dst == >>> 2001:db8:3::/64" reroute fe80::de:adff:febe:ef03 >>> + >>> +# Verify direct LLA match works >>> +ovn-sbctl dump-flows router3 > router3flows >>> +AT_CAPTURE_FILE([router3flows]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router3flows | grep "priority=500" | >>> ovn_strip_lflows], [0], [dnl >>> + table=??(lr_in_policy ), priority=500 , match=(ip6.dst == >>> 2001:db8:3::/64), action=(xxreg0 = fe80::de:adff:febe:ef03; xxreg1 = >>> fe80::de:adff:febe:ef03; eth.src = 02:de:ad:be:ef:03; outport = "r3-port1"; >>> flags.loopback = 1; reg8[[0..15]] = 0; reg9[[9]] = 0; next;) >>> +]) >>> + >>> +# Test 6: IPv6 LLA nexthop to directly peered router port >>> +# Create two routers with directly peered ports using peer= parameter >>> +check ovn-nbctl lr-add router4 >>> +check ovn-nbctl lr-add router5 >>> + >>> +# Create peered router ports with IPv6 networks >>> +# MAC 02:de:ad:be:ef:04 generates LLA: fe80::de:adff:febe:ef04 >>> +# MAC 02:de:ad:be:ef:05 generates LLA: fe80::de:adff:febe:ef05 >>> +check ovn-nbctl lrp-add router4 r4-r5 02:de:ad:be:ef:04 192.168.4.1/24 >>> 2001:db8:4::1/64 peer=r5-r4 >>> +check ovn-nbctl lrp-add router5 r5-r4 02:de:ad:be:ef:05 192.168.4.2/24 >>> 2001:db8:4::2/64 peer=r4-r5 >>> + >>> +# Add routing policy on router4 with LLA nexthop pointing to router5's >>> auto-generated LLA >>> +check ovn-nbctl --wait=sb lr-policy-add router4 600 "ip6.dst == >>> 2001:db8:6::/64" reroute fe80::de:adff:febe:ef05 >>> + >>> +# Verify logical flow was created with correct outport for peer connection >>> +ovn-sbctl dump-flows router4 > router4flows >>> +AT_CAPTURE_FILE([router4flows]) >>> + >>> +AT_CHECK([grep "lr_in_policy" router4flows | grep "priority=600" | >>> ovn_strip_lflows], [0], [dnl >>> + table=??(lr_in_policy ), priority=600 , match=(ip6.dst == >>> 2001:db8:6::/64), action=(xxreg0 = fe80::de:adff:febe:ef05; xxreg1 = >>> fe80::de:adff:febe:ef04; eth.src = 02:de:ad:be:ef:04; outport = "r4-r5"; >>> flags.loopback = 1; reg8[[0..15]] = 0; reg9[[9]] = 0; next;) >>> +]) >>> + >>> +AT_CLEANUP >>> +]) >>> + >>> OVN_FOR_EACH_NORTHD_NO_HV([ >>> AT_SETUP([ACL allow-stateless omit conntrack - Logical_Switch]) >>> ovn_start >> > _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
