Page MenuHomeFreeBSD

Change the way of passing IPv6 packets via loopback.
AbandonedPublic

Authored by melifaro on Oct 11 2015, 6:58 PM.
Tags
None
Referenced Files
Unknown Object (File)
Thu, Apr 25, 9:49 PM
Unknown Object (File)
Fri, Apr 19, 2:10 AM
Unknown Object (File)
Mar 19 2024, 9:57 PM
Unknown Object (File)
Feb 23 2024, 10:56 AM
Unknown Object (File)
Dec 22 2023, 10:07 PM
Unknown Object (File)
Dec 1 2023, 9:23 AM
Unknown Object (File)
Nov 19 2023, 12:37 PM
Unknown Object (File)
Oct 29 2023, 12:06 AM
Subscribers

Details

Reviewers
ae
hrs
glebius
bz
Group Reviewers
network
Summary

Currently IPv6 code has to provide _two_ interface pointers to nd6_output_ifp() in order to pass the packet.
They are the same interface _except_ the loopback case: when first one (which if_output() function is used) is "loX", the second one needs to be "real" network interface where source/dst IPv6 addresses are from.
The reason besides this was the following:

Quoting KAME Changelog 1.910 2000/05/21:

2000-05-17  JINMEI, Tatuya  <jinmei@isl.rdc.toshiba.co.jp>
      * kame/sys/netinet6/nd6.c (nd6_output): 
      * kame/sys/netinet6/ip6_output.c (ip6_output):
      made scoped addresses more friendly with loopback interfaces;
      if a packet containing scoped addresses in the source or
      destination address fields is going to be sent on a loopback
      interface, pass looutput() the interface to which the scoped
      address(es) belongs.
      For example, you won't see "lo0" when you ping to your own
      link-local address.
      This is currently experimental and enabled only when the
      FAKE_LOOPBACK_IF kernel compile option is specified.

Actual commit in KAME: https://github.com/kame/kame/commit/1b854ebf614ac68a25ddd067843766655efdbb8b

It was turned on by default several months after:

2000-07-30  JINMEI, Tatuya  <jinmei@isl.rdc.toshiba.co.jp>
      * kame/sys/netinet6/(various files): made FAKE_LOOPBACK_IF default
      (as previously announced). At this moment, the older behavior can
      be specified by the "OLD_LOOPBACK_IF" kernel compilation option.

These changes were merged to FreeBSD as rS62587 .

There were a bunch of issues with this approach:

  • BPF has to handle this explicitly (worked around in rS162539)
  • loopback checksum problems (partially worked around in rS238871 , see kern/170070 )
  • Strange packet accounting: kern/165190

I believe current behavior needs to be changed because:

  • setting dst-ip ifp as _source_ of loopbacked packets is simply incorrect
  • accounting outgoing packets/bytes to physical interface instead of loopback is also incorrect
  • this makes IPv6 handling different from IPv4 for no reason
  • this behavior brings unnecessary complexity to inet6/, routing and loopback code

The actual proposal is to eliminate second ("origifp" interface pointer) and use the same handling logic as in IPv4.
What will change:

  • looutput() will count opackets/obytes on loopback
  • mac_ifnet_check_transmit() from looutput will also be called for loopback interface
  • if_simloop() will be called with loopback interface (exactly as in IPv4)

The latter might require some changes in firewalls configs, but typically loopback traffic is explicitly allowed (and now IPv6 behaviour is exactly the same as IPv4 in this place)

Test Plan

Before:
(IPv4/IPv6 addresses are attached to vtnet0):
ipfw config:
00100 0 0 count log icmp from me to me
00200 0 0 count log ipv6-icmp from me to me

ping -c1 10.111,0.12
ping6 -c1 2a02:6b8:0:415::12

BEFORE:
ipfw: 100 Count ICMP:8.0 127.0.0.1 10.111.0.12 out via lo0
ipfw: 100 Count ICMP:8.0 127.0.0.1 10.111.0.12 in via lo0
ipfw: 100 Count ICMP:0.0 10.111.0.12 127.0.0.1 out via lo0
ipfw: 100 Count ICMP:0.0 10.111.0.12 127.0.0.1 in via lo0
ipfw: 200 Count ICMPv6:136.0 [fe80::1] [fe80::5054:ff:fe04:1789] in via vtnet0
ipfw: 200 Count ICMPv6:128.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] out via lo0
ipfw: 200 Count ICMPv6:128.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] in via vtnet0
ipfw: 200 Count ICMPv6:129.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] out via lo0
ipfw: 200 Count ICMPv6:129.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] in via vtnet0

AFTER:
100 Count ICMP:8.0 127.0.0.1 10.111.0.12 out via lo0
100 Count ICMP:8.0 127.0.0.1 10.111.0.12 in via lo0
100 Count ICMP:0.0 10.111.0.12 127.0.0.1 out via lo0
100 Count ICMP:0.0 10.111.0.12 127.0.0.1 in via lo0
200 Count ICMPv6:136.0 [fe80::1] [fe80::5054:ff:fea5:2b2a] in via vtnet0
200 Count ICMPv6:128.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] out via lo0
200 Count ICMPv6:128.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] in via lo0
200 Count ICMPv6:129.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] out via lo0
200 Count ICMPv6:129.0 [2a02:6b8:0:415::12] [2a02:6b8:0:415::12] in via lo0

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Passed
Unit
No Test Coverage
Build Status
Buildable 745
Build 745: arc lint + arc unit

Event Timeline

melifaro retitled this revision from to Change the way of passing IPv6 packets via loopback..
melifaro updated this object.
melifaro edited the test plan for this revision. (Show Details)
melifaro added reviewers: network, ae, bz, glebius, hrs.
melifaro edited the test plan for this revision. (Show Details)
melifaro edited the test plan for this revision. (Show Details)
glebius edited edge metadata.

Of course, I vote with my both hands for the change, because that was me, who asked to make it. Calling if_output() of one ifnet on the other ifnet, is a VERY VERY BAD design bug.

P.S. Nice archaeology you made, Alexander :)

This revision is now accepted and ready to land.Oct 12 2015, 1:13 PM
hrs edited edge metadata.

The patch looks good to me.

Was this also related to net.inet6.icmp6.nd6_useloopback which QingLi removed a while ago?

ae requested changes to this revision.Oct 13 2015, 3:51 PM
ae edited edge metadata.

Actually we found some problems with this patch. Handling of IPv6 LLA should be done separately.

This revision now requires changes to proceed.Oct 13 2015, 3:51 PM

Probably I overlooked something, but does new ip6_output() work with a loopback from/to link-local addresses? I think scope checks will fail when lo0 is passed as the outgoing interface. I will take a look into the patch more closely in this weekend...

Yes, there is a problem with link-local addresses on loopback and other (unrelated) problem on filling rt_ifa which makes this absolutely weird.
I'm currently doing more archaeology/testing. I'll submit a different version of this patch soon