Yeah sorry, English is not my first language and I started by the solution, not the problem.

    So here is my setup:

NETWORK A is a wired network with private IPv4/24 addr a public IPv6/64 addr NETWORK B is a wireless network with private IPv4/24 addr a public IPv6/64 addr The Broadband equipment provides a single IPv4/32 public addr and a public IPv6 /64 addr (French broadband provider Free/Proxad) So the OpenBSD box (PC Engines APU) has one public IPv4/32 addr and one public IPv6 addr on a /64 network.


    NETWORK A <-> (re0) (bridge0) (re2) <-> Broadband equipment
    NETWORK B <-/  (athn0)

    TV Decoder <-> (re0 vlan 100) (bridge1) (re2 vlan 100) <->  IPTV Server


The only way I can manage this setup is by bridging the IPv6 traffic and routing/NATing the IPv4 traffic. So what I did, I started from the BLOCKNONIP code and made a bridge that passes only IPv6 traffic. This setup is very common in France and was working perfectly with my patch on OpenBSD 4.x.

    There is a bridge0 with
        re0
        athn0
        re2 (modified blocknonip)

    And a bridge1 with
        re2.100
        re0.100

Since I upgraded to 5.8 I found that IPv4 ARP requests were slipping through my version of blocknonip. This is a problem because the broadband equipment picks them up. When I started looking at the code, I found that ARP requests from NETWORK B (only from NETWORK B, never NETWORK A, don't know why, maybe because B doesn't have an IP address assigned) were being resent to the external network via new code path that didn't exist in 4.8/4.9. Also, ARP requests on the bridge1 are being resent to the bridge0. Those packets are being sent by bridge_output(). These are not forwarded packets. In my setup, receiving an ARP request from athn0 will spawn another ARP request on re0. Receiving an ARP request on re2.100 will spawn another request on re0 (besides forwarding the request to re0.100). That one does not feel very right even without my patch. So my questions were :

First of all, is bridge_output() used to forward packets now? Or is it only for local traffic? If it is sometimes used to forward packets, then a check against BLOCKNONIP would be needed? Reyk Floeter confirmed that it was used only for local traffic.

Second, why bridge_output()? In my understanding output is never done directly on the bridge, it is always on one of the underlying interfaces? This could have implications for pf too? From what I saw bridge_output() is used directly only in one obscure case for sending back ICMP errors. But it is also the output function of the interface? This is why I have a hard time finding the origin of those ARP requests. So this is my real question, who sends ARP requests directly on the bridge via bridge_output()?

    Thank you and I hope that I was clear enough.

On 22/11/15 20:37, Martin Pieuchot wrote:
On 22/11/15(Sun) 18:30, Momtchil Momtchev wrote:
On 22/11/2015 17:48, Martin Pieuchot wrote:
On 22/11/15(Sun) 16:56, Momtchil Momtchev wrote:
On 22/11/2015 15:52, Martin Pieuchot wrote:
When you say "the bridge changed somewhat" are you saying that you see
a regression?  Could you share your setup that, I guess work with 4.9,
and no longer work with 5.8.


I don't understand what you mean with "_BLOCKNONIPV6_ bridge". ifconfig(8)
clearly say:

      blocknonip interface
          Mark interface so that no non-IPv4, IPv6, ARP, or Reverse ARP
          packets are accepted from it or forwarded to it from other
          bridge member interfaces
     I have a modified bridge that adds a new bridge option - BLOCKNONIPV6 -
to block IPv4 traffic but pass IPv6 traffic. There's no regression, my only
problem was that in 4.9 bridge_output() was never used in my particular
case. In 5.8 bridge_output() is used for some strange forwarding of ARP
packets - every ARP request on the internal side coming from a bridge
interface without an IP address (yes, only on interfaces without an IP
address) spawns an ARP request on the external side. That request is coming
from bridge_output(), not the usual bridge code path in bridgeintr().
The result of your analysis is either incorrect or there's a bug I
couldn't found by looking briefly at the code.  In both cases I can't
help you because you're not sharing the important pieces of informations.

When an ARP packet is received on a bridge member bridgeintr() is called.
So what you say about "strange forwarding of ARP packets" doesn't match
with what you say as "That request is coming from bridge_output()".

                                                                       In a
non-modified stock OpenBSD bridge this would be the correct behaviour, so
there is no bug here.
What would be this correct behaviour?  I don't understand what you're
describing so I cannot say if I agree that there's no bug here.  But I'd
be glad if I could understand.

                       It is just somewhat weird that some ARP requests are
forwarded through bridge_output(), not through the usual code path.
Why do you think it is weird?  What make you think that it isn't taking
the "usual code path".  What is the "usual code path" for you?

     My question is who uses bridge_output()? Except one obscure case for
sending back ICMP errors,
Why do you think it is an obscure case?

                           normally all local traffic should originate in the
output() function of the underlying interface? Or am I missing something?
What do you mean by "local traffic"?  I thought your were talking about
forwarding?

The picture is as follow:

                                RECEIVING     SENDING
                                (userland)   (userland)
                                
                                  ^             |
  INCOMING (interrupt handler)    |             |
      |                           |             |
      v                                         v
   if_input -> pseudo_input -> | STACK | -> if_output -> if_enqueue -> if_start
                                                             ^
                     |                                       |
                     `------------->  | BRIDGE | -------------'

     If you think that my feature presents any interest, I can tidy it up and
submit it. It splits BLOCKNONIP into BLOCKNONIPV4 and BLOCKNONIPV6. I need
it because in my particular case IPv4 should be NATed and IPv6 should be
switched as you cannot split IPv6 into arbitrary subnets below /64, so you
have to keep it whole. It is the only way to route and filter both IPv4 and
IPv6 traffic with one particular French broadband service provider but there
could maybe be other uses for it.
I think it might be interesting, at least to better understand your uses
case and the possible bug/limitation in bridge(4).

Reply via email to