BPI-R2 Kernel 4.14 HNAT


(Alexey Loukianov) #61

Looking at the code it seems that bridge case is supported. Hooks are registered for NF_BR_PRE_ROUTING and NF_BR_POST_ROUTING so there are two chances for a given skb to get an HW NAT entry - in NF_INET_POST_ROUTING or in NF_BR_POST_ROUTING. If I get the logic correctly it means that mtk hwnat is only able to accelerate SNAT cases which should be enough as this is the most popular case.

Looking at the code I’d say that there are 4096 entries in HW NAT table but it does not necessarily means that your connections would always end up in hwnat table. Entry index is determined by an skb hash so if your connection happens to have the same hash as some other connection that was already bound into hwnat - new connection won’t be handled by hwnat. Then it looks like there’s a rate detection algo in place and connection rate should be big enough to pass over the threshold and be bound into hwnat entry. Take this with a grain of salt as my understanding of the mtk hwnat code is “ad hoc” - spent about an hour looking at the patch trying to understand what’s going on in there.


(Frank W.) #62

Snat imho is only possible if you have a fixed ip-address. Here in germany private internet-access is mostly done with ppp-connections and dynamic ip

Remeber that this code is the old code from 4.9. New code is only working in openwrt and uses offload-framework,but i have not seen it yet (know it only from discussions)

And for bridge…in prerouting in-interface for lan/wan is marked as FOE_MAGIC_GE_LAN/WAN and if NOT bridge as invalid…bridge is not marked…also only lan/wan is handled in postrouting. Maybe new code handles also bridges/ppp-interfaces. also hnat is usable for traffic which is internally routed (eg. Lxc/docker) if it also uses nat…i don’t know why interfaces matter…nat-handler should only be called if nat is setup…independ on which interface


(Alex) #63

4.14 from yours repo. no bridges and wifi clients


(Alex) #64

I think ixia can makes similar flows and this leads to problems in hnat.


(Frank W.) #65

I’m not sure if udp can be bound to hnat…maybe this needs sessions (tcp)


(Alexey Loukianov) #66

SNAT is just a generic name of a technique when source IP address of a packet gets changed to something else after the moment of routing decision. MASQUERADE is just a shortcut for SNAT auto-changing source IP of a packet to be the IP that’s assigned to the outgoing interface. It does not matter if you’ve got dynamic IP that’s assigned to your connection in any way be it PPtP, PPPoE or a simple DHCP - as long as your router is a box that this IP is assigned to and all packets coming from your local clients behind the router are mangled to look as originating from the IP that was assigned to router - your’re using SNAT and your local clients are told to be located “behind the NAT”.

Yep. That’s because each packet in skb will traverse nf stack twice: first time as NFPROTO_BRIDGE with input interface set to actual lanX the packet had come from and second time as NFPROTO_IPV4 with input interface set to brXXX. So HNAT_SKB_CB(skb)->iif will be set to one of FOE_MAGIC_GE_LAN/WAN. Or to FOE_INVALID if input interface is not wan or lanX. Then in postrouting phase in case some specific conditions are met a new entry in hwnat table is filled in representing this particular flow.

UDP is supported too as long as the flow is tracked by the conntrack. Essentially what hwnat code is doing is checking if a packet is tracked by conntrack (ctinfo and ct in mtk_hnat_nf_post_routing) and in case it is - detaches ct helper (if any) from this flow and creates a hwnat entry for it in skb_to_hnat_info().

Is there a place where this code can be found? I’m curious to take a look onto it.


(Alexey Loukianov) #67

That’s quite possible. You can add a debug printks before return 0 in here to reveal what’s happening:

	if ((IS_LAN(out) && FROM_GE_WAN(skb)) ||
	    (IS_WAN(out) && FROM_GE_LAN(skb))) {
		if (!skb_hnat_is_hashed(skb))
			return 0;

		entry = &host->foe_table_cpu[skb_hnat_entry(skb)];
		if (entry_hnat_is_bound(entry))
			return 0;

		if (skb_hnat_reason(skb) == HIT_UNBIND_RATE_REACH &&
		    skb_hnat_alg(skb) == 0) {
			if (fn && fn(skb, out))
				return 0;

(Frank W.) #68

imho they are only for openwrt (depend on offload framework) and reported to be unstable.

@moore can you post a link to the patches?


(Alexey Loukianov) #69

Looking at moore’s posts in this topic I assume that patches are available in the upstream openwrt git repo in trunk branch. Getting them tied to the emerging fastpath/offload support in linux kernel is a good thing as the software offload core is ~3x times faster in itself compared to the normal nf NAT packets traversing. But it being a relatively new code it is not so stable and compatible. I’ve seen a lot of complaints on openwrt forums about IPSEC requiring special rules to work with offloading enabled, various incompatibilities with wireguard, IPv6 and so on. Couple it with hwnat support tied into this and instability is an expected thing. Nevertheless thanks for pointing me towards this implementation, will take a look at it later on.


(Alex) #70

I’ll try tcp test tomorrow


(Alex) #71

i’n not a developer and don’t know how to compile hwnat module. if you have an instruction, i will try


(Frank W.) #72

You use 4.14 from my repo? just change hwnat-code and use build.sh to compile full kernel again


(Alexey Loukianov) #73

Here are relevant commits from openwrt repo backporting offload support to 4.14 and implementing hw NAT for MT7621:

https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=b7265c59ab7dd0ec5dccb96e7b0dc1432404feb7
https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=103335644265d96c656a7de3d5994fbd11246300
https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=424a9ae128bd2045cd4bfd6e3229f2529d150a25

I can’t see any recent activity related to this patches and a question that was asked on OpenWrt forums not a while ago also seems to be left without a promising answer: