Mandatory netif header?

Dear resolving IOTlers,

in several lengthy discussions on Github we (mostly Martine and me) discussed if the netif header in GNRC should be mandatory. As a context: the netif header in GNRC is a pseudo-header that contains (optional) link-layer information such as the source and destination address, the information about the used interface, and some additional, again optional, information about link-layer metrics (RSSI and LQI).

Until recently, it was optional to include this header while passing the packet up the stack. However, recently, I introduced a patch to change this, by asserting the presence of the netif header while receiving a packet in the IPv6 implementation. The current discussion is about reverting this change.

My rationale to _keep_ this change is the following: * In my opinion a protocol running logically directly above the link-layer,   such as IP (adaptation layers like 6LoWPAN may exist in between) will   typically require information about the interface that received the packet.   (The same is true for other layers, e.g. UDP cannot work without information   from the IP header.) * Not in all cases a physical interface may be involved, but for those cases   there should typically be a pseudo-interface. The only case, where we do not   have a pseudo-interface right now (as far as I know) is the loopback case.   In my opinion, it is - for efficiency reasons - completely okay not to   provide a loopback device in GNRC, but I still don't see a reason why a   netif header indicating a pseudo interface should do any harm here.   Implementation detail:   So far, KERNEL_PID_UNDEF is used as identifier in my proposal, but we could   also define the PID of the IPv6 thread as loopback device identifier. * Finally, I think asserting a present netif header makes the code easier,   because one does not have to cover exception cases and provide different   branches for netif-header-is-present and netif-header-is-NOT-present.

Cheers, Oleg

Hi,

In my opinion a protocol running logically directly above the link-layer, such as IP (adaptation layers like 6LoWPAN may exist in between) will typically require information about the interface that received the packet. (The same is true for other layers, e.g. UDP cannot work without information from the IP header.)

While your statement is true for UDP the argument does not hold for IP in my opinion. UDP (or TCP) need the IP information, because IP otherwise doesn’t know how to send the packet, since UDP does not handle this kind of information. IP on the other hand has ARP/NDP to resolve an IP address into link-layer information. Furthermore, as far as we discussed so far we talked only about reception of a packet and there this information is only important for routing protocols and IP-internal stuff (and for the most part only the non-address related information from these header, like the interface identifier and the link-layer metrics). In these cases the information is provided for natural interfaces. Pseudo-interfaces as you define them usually are not handled by these kind of operation in a sensible way so packets from those can just ignore packets without a netif header.

Not in all cases a physical interface may be involved, but for those cases there should typically be a pseudo-interface. The only case, where we do not have a pseudo-interface right now (as far as I know) is the loopback case. In my opinion, it is - for efficiency reasons - completely okay not to provide a loopback device in GNRC, but I still don’t see a reason why a netif header indicating a pseudo interface should do any harm here. Implementation detail: So far, KERNEL_PID_UNDEF is used as identifier in my proposal, but we could also define the PID of the IPv6 thread as loopback device identifier.

Well unless you want to send all IPv6 packets to the loopback to the IPv6 thread this would require an additional check anyways.

Finally, I think asserting a present netif header makes the code easier, because one does not have to cover exception cases and provide different branches for netif-header-is-present and netif-header-is-NOT-present.

I have the complete opposite impression: Currently the check for a netif header is AFAIK only present at the point of your patch. So we have a little bit more complex code at this point (where the complexity is only as far as a assert(netif) vs if(netif) { iface = netif->iface } else {iface = KERNEL_PID_UNDEF}), while anything else that is a pseudo-interface now needs to prepend a netif header to the packet.

Cheers, Martine

Hi Martine!

IP on the other hand has ARP/NDP to resolve an IP address into link-layer information.

Yes, but ARP/NDP needs link-layer information to work, right?

Furthermore, as far as we discussed so far we talked only about reception of a packet and there this information is only important for routing protocols and IP-internal stuff (and for the most part only the non-address related information from these header, like the interface identifier and the link-layer metrics). In these cases the information is provided for natural interfaces. Pseudo-interfaces as you define them usually are not handled by these kind of operation in a sensible way so packets from those can just ignore packets without a netif header.

I don't see any argument against having a netif header here, either.

> Implementation detail: > So far, KERNEL_PID_UNDEF is used as identifier in my proposal, but we could > also define the PID of the IPv6 thread as loopback device identifier.

Well unless you want to send all IPv6 packets to the loopback to the IPv6 thread this would require an additional check anyways.

Why? If the PID inside the netif header is the PID of the IPv6 thread, the interface is assumed to be loopback. But let's discuss this afterwards, that's really just an implementation detail. We can also introduce other values for that.

> Finally, I think asserting a present netif header makes the code easier, > because one does not have to cover exception cases and provide different > branches for netif-header-is-present and netif-header-is-NOT-present.

I have the complete opposite impression: Currently the check for a netif header is AFAIK only present at the point of your patch. So we have a little bit more complex code at this point (where the complexity is only as far as a `assert(netif)` vs `if(netif) { iface = netif->iface } else {iface = KERNEL_PID_UNDEF}`)

Anything inside the layer which works directly on top of the link-layer needs to perform the check if the header is present when it is interested in its information. If it's always present I can skip this check.

while anything else that is a pseudo-interface now needs to prepend a netif header to the packet.

That's a one-time work - and a very simple one. Moreover, this would it make possible to distinguish between, let's say loopback and ZEP pseudo interfaces. If I just set iface to KERNEL_PID_UNDEF, I cannot.

Basically, you're proposing to set the interface to KERNEL_PID_UNDEF in the network layer if no information is present, I propose to set the interface to KERNEL_PID_UNDEF if no better fitting device exists before passing it up to the network layer. In my opinion is just more consistent to handle all interfaces the same way - whether they are physical devices or only logical devices.

Cheers, Oleg