Not all features use modules, so module format is optional in most cases. Looking at your “/proc/config.gz” will tell you what features are enabled (along with whether it is integrated or module format), so to determine what your kernel is configured for:
gunzip < /proc/config.gz | less
I see a couple of useful URLs on iptables kernel config options here (important: I don’t know if all of what is listed here applies to the 4.x kernels, or if perhaps it was written for 3.x kernels or even older):
I see the following are already present/enabled:
I see the following are missing:
- # CONFIG_IP_NF_NAT is not set
- CONFIG_IP_NF_CONNTRACK is not found at all...maybe not applicable
- # CONFIG_NF_NAT_MASQUERADE_IPV4 is not set...not actually required for nat
The following command will summarize this for your kernel:
gunzip < config.gz | egrep '(CONFIG_IP_NF_IPTABLES|CONFIG_IP_NF_IPTABLES|CONFIG_IP_NF_NAT|CONFIG_IP_NF_CONNTRACK|CONFIG_NF_NAT_MASQUERADE)'
I would suggest starting with “/proc/config.gz” for configuration, add CONFIG_IP_NF_NAT as a module, and set CONFIG_LOCALVERSION to “-tegra” (or whatever the suffix is for your “uname -r”). Then you just add the module and “sudo depmod -a”.
Note that if you enable something for iptables which is not needed you will increase kernel size, possibly slow down firewall packet filtering, or add security problems. If you add something as a non-module you may wish to change CONFIG_LOCALVERSION, but if you stick to building as a module you can keep the “-tegra” CONFIG_LOCALVERSION.
I believe you will find only desktop distributions provide modules not needed for the base install. This is not something specific to Jetsons, nor was it left out by accident, it is the intentional approach to minimize excess for all embedded systems. When I look at what is in one Fedora desktop PC’s module directory I see 110MB of modules, but perhaps only 20% of it is used despite my using a lot of features my Jetson never touches.
One of the properties of loading a module is that it becomes part of the kernel and needs a physical address, not just a virtual address…it can’t be swapped out. Enabling features not needed essentially removes physical RAM memory the kernel might need for other purposes. ARMv8 (arm64) is much better than ARMv7 (arm32), but in particular modules have an additional requirement: They must be loaded in kernel address physical memory such that a direct branch instruction does not exceed its maximum branch offset (jumping from one memory location to another implies an address offset magnitude). On arm64 I think it is 128M (128Mbyte offset span), and on arm32 it is 32M…this is also shared with initrd (and thus starting with initrd compounds the issue). If the sum total of initrd and modules exceed this your kernel will mysteriously crash and burn when it runs the kernel code and tries to do a direct branch to an address it can’t reach. I don’t know what the x86_64 direct branch limit is, but it is extremely large in comparison to any ARM architecture…desktops are more or less free to build and install as many modules as desired.