Hi VPP team,
I'm currently trying to setup a full IPv6 network, and while everything's 
working fine by now, I'm trying to implement NAT64 to give a compatibility 
layer for my services using VPP.
I don't clearly understand why, but it seems when you set an interface as "in" 
it is interpreted as all the traffic within the interface will be NAT64 
translated, regardless of whether the destination matches the configured NAT64 
prefix. Even though I specify the prefix explicitly (e.g., 64:ff9b::/96), it 
doesn't help - ALL IPv6 traffic gets translated.

Expected behavior:
Only IPv6 packets with destinations matching the configured NAT64 prefix (e.g., 
64:ff9b::192.0.2.1) should be translated to IPv4. Other IPv6 traffic should 
pass through normally.

Actual behavior:
ALL IPv6 traffic on the interface is translated, extracting an IPv4 address 
from the destination regardless of the prefix.

Code evidence:
I see there's the following code in nat64_in2out.c (lines 1080-1084):
if (nat64_not_translate (sw_if_index0, ip60->dst_address))
{
next0 = NAT64_IN2OUT_NEXT_IP6_LOOKUP;
goto trace0;
}
This is the ONLY check before translation occurs, and it only verifies if the 
destination is a local interface address. There's no verification that the 
destination IPv6 address actually matches the configured NAT64 prefix.
Then the translation unconditionally calls (line 227):
nat64_extract_ip4 (&old_daddr.ip6, &new_daddr, fib_index);
This function (nat64_extract_ip4 in nat64.c lines 1324-1386) blindly extracts 
32 bits from the IPv6 address based solely on the prefix LENGTH, without ever 
verifying that the prefix itself matches:
void
nat64_extract_ip4 (ip6_address_t * ip6, ip4_address_t * ip4, u32 fib_index)
{
nat64_main_t *nm = &nat64_main;
nat64_prefix_t *p, *gp = 0;
u8 plen = 0;
vec_foreach (p, nm->pref64)
{
if (p->fib_index == fib_index)
{
plen = p->plen;  // Only gets the LENGTH, not the prefix itself
break;
}
// ...
};
// Extracts IPv4 based on length, no prefix matching
switch (plen)
{
case 96:
ip4->as_u32 = ip6->as_u32[3];  // Just takes last 32 bits
break;
// ... other cases
}
}

Impact:
With a /96 prefix configured, ANY IPv6 destination (e.g., 2001:db8::1.2.3.4) 
will have its last 32 bits extracted as the IPv4 address (1.2.3.4), even though 
the prefix is 2001:db8:: instead of 64:ff9b::.

Workaround attempt:
The only workaround I can see is to add a Loopback interface in my VRF, set it 
as "in" for NAT64, and add an entry to route only the NAT64 prefix traffic to 
that interface. I tried this approach but I wasn't able to make it works.

Question:
Is this the intended behavior? If so, how can I configure NAT64 to only 
translate traffic matching the specific prefix while allowing other IPv6 
traffic to pass through normally?
If this is a bug, the fix would likely involve adding prefix matching logic in 
the packet processing path before calling nat64_extract_ip4().
Thank you for your help!
-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#26493): https://lists.fd.io/g/vpp-dev/message/26493
Mute This Topic: https://lists.fd.io/mt/116167893/21656
Group Owner: [email protected]
Unsubscribe: https://lists.fd.io/g/vpp-dev/leave/14379924/21656/631435203/xyzzy 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to