Hi all, reading the conntrack code, and thinking about optimizations (there are plenty...), I come to this question: as implemented, the ip_nat_info field of each conntrack contains an array of 'manips', max. 6 of them. Each manip applies to a certain mask of hooks, and changes either the source or destination IP address of the current skb. The changes happen as the various hook functions in the NAT code are executed.
An alternative implementation would apply address mangling to each individual skb exactly once. For both directions, the conntracking structure would contain the set of changes to apply to IP and protocol addresses, and possibly there would be a _precomputed_ checksum adjust stored within the conntrack. Now, the "step-by-step" application in the current framework, if I understand things correctly, is visible in the iptables rule chains in the various tables. What I wonder about is, how many rulesets _rely_ on such "partial modifications" of the individual skb, and what is the purpose of that usage? I am looking for examples here. best regards Patrick For the curious, here's the data structure I'm thinking about: - tuples in the hash are "normalized". The "smaller" port comes first, and if there's a tie (same port in both directions), the "smaller" IP comes first. The incoming skb has its addresses normalized (the result remembered in a variable called "flip"). This consolidates the two direction's tuples for non-address-rewriting conntracks. - 64 byte 'struct ip_conn': contains the normalized tuple for the connection. In NAT situations, this represents the "non-REPLY" direction of the connection. A pointer then leads to: - 32 byte 'struct ip_conn_twin': the tuple for the REPLY direction, in NAT situations. The tuples are not mirrors of each other, in this situation. Now, I would like to use nothing but the described tuple storage for packet manipulation.