Right now its not possible to use a map with snat/dnat to alter both address and port at the same time. This series teaches nft to accept this: map y4 { type ipv4_addr : ipv4_addr . inet_service elements = { 192.168.7.2 : 10.1.1.1 . 4242 } } meta l4proto tcp meta nfproto ipv4 dnat ip to ip saddr map @y4 i.e., it allows: 1. A mapping that contains a concatenated expression. 2. nat expression will peek into set type and detect when the mapping is of 'addr + port' type. Linearization will compute the register that contains the port part of the mapping. 3. Delinarization will figure out when this trick was used by looking at the length of the mapping: 64 == ipv4addr+service, 160 == ipv6addr+service. What does not work: Anonymous mappings, i.e. meta l4proto tcp meta nfproto ipv4 dnat ip to ip saddr map { 1.2.3.4 : 1.2.3.5 . 53, .. doesn't work. When evaluating "1.2.3.4", this is still a symbol and unlike with named sets, nft doesn't have a properly declared set type. This is similar to the 'maps-on-LHS-side' issue. Phil suggested to allow this: ... to ip saddr map { type ipv4_addr : ipv4_addr . inet_service; 1.2.3.4 : 1.2.3.5 . 53, .. i.e. re-use the declarative syntax from map code. Another related issue: "typeof" doesn't work with concatenations so far. I don't know when I will have time to look into this more. I have incomplete patches for concat typeof (udata) support and a patch to extend the grammar for the proposed { type ... in anon sets (doesn't cause grammar problems). I will continue to work on it but don't know yet when I will do so, so I am sending the finished patches I have at this time.