0

Is it possible to create a tap (or taps, if two are required?) between two physical interfaces so that all traffic (ethernet frames) between the two interfaces is passed through the application connected to the tap?

diagram of desired setup

If this is possible, how can this be achieved from a configuration standpoint?

I am familiar with reading and writing to a tap interface from an application, I am just looking for how to set this up so that the application can read and write the traffic going in both directions. The linux device basically becoming a invisible ethernet bridge.

My goal is to be able to have the application in between do two things:

In one direction: Filter certain frames based on destination MAC - for example all packets from eth0 to eth1 that are not to dest 01:01:01:01:01:01 or ff:ff:ff:ff:ff:ff are discarded

In the other direction: delay some frames - for example all packets from eth1 to eth0 are buffered and then only sent every X ticks for Y ticks

If this isn't possible or even if it is - is there a better approach to achieve this?

Edit: With the approach @dirkt mentions in his answer:

Yes. Create an application that has two tuntap interfaces tap0 and tap1, then >bridge tap0 with eth0 and tap1 with eth1.

would this be the appropriate pseudo code/right idea for how to implement the bridge between the two (eth0/tap0 and eth1/tap1) in the application layer?


counter = 0

//eth0 is bridged to tap0
tap0 = open ("tap0") 

//eth1 is bridged to tap1
tap1 = open ("tap1") 

forever {

    //buffer all packets received by eth1 (tap1) - do I need to buffer them constantly or will they wait at the file pointer until I read them (within reason)
    packet_buffer[] = read(tap1) 

    //every 100 cycles (for simplicity)
    if (counter == 100) { 

        //reset counter
        counter = 0

        //write all buffered packets from eth1 (tap1) to eth0 (tap0)
        foreach (packet_buffer as packet){
            write(tap0, packet) 
        }

        //empty packet buffer so we can start filling it again (yes very simplified - would likely use a ring buffer)
        packet_buffer = []

    }


    //if eth0 (tap0) gets a packet
    if ( packet = read(tap0) ) { 

        //forward to eth1 (tap1) if the destination is 01:01:01:01:01:01 or ff:ff:ff:ff:ff:ff
        if(packet.dest == 01:01:01:01:01:01 OR packet.dest == ff:ff:ff:ff:ff:ff ){ 
            write(tap1, packet)
        }

    }

    //increment counter
    counter++

}
  • At first you can read the frames going from eth1 to eth0 (because tap0 is in the bridge, but as the bridge learns, you will not see some of them, by default a bridge is a switch not a hub). You will not be able to delay or discard them, because all members of the bridge will get them at the same time. What are you trying to solve? – Eduardo Trápani May 14 at 0:14
  • @EduardoTrápani - would it be possible then to achieve with two taps (one bridged to each eth interface, and the application acting as the "bridge" and passing that data between them? I'm trying to set this up to experiment/test a TDMA like scheme for sensors communicating over a daisy chained network - but I am admittedly more experienced with hardware then OS level stuff like this – Digistump May 14 at 1:05
0

Is it possible to create a tap (or taps, if two are required?) between two physical interfaces so that all traffic (ethernet frames) between the two interfaces is passed through the application connected to the tap?

Yes. Create an application that has two tuntap interfaces tap0 and tap1, then bridge tap0 with eth0 and tap1 with eth1.

tap between two bridged physical interfaces

If eth0 and eth1 are already bridged, then this doesn't work. You have to use ebtables to "steal" packets between those interfaces inside the bridge, and direct them somewhere else.

In one direction: Filter certain frames based on destination MAC

You can do this directly with ebtables.

In the other direction: delay some frames

You can use something like

tc qdisc add dev tap0 root netem delay 100ms

to add delay to an interface, but to do it for "some frames" and in one direction and so on is probably indeed easier to do in an application.

| improve this answer | |
  • Thank you - I am familiar with tc and ebtables - what I actually want to implement in both directions is more complex, especially on the delay side which is why I'm looking to tap. – Digistump May 14 at 1:26
  • please see my edit to the original question - would that pesudo code be the right idea for how to implement a bridge between the two taps (and therefore between the two eth) with these "filters" at the application layer? – Digistump May 14 at 1:27
  • Programming advice is out of scope of this stackexchange, but keep in mind you have to be able to (1) simultaniously forward in both directions, so use select etc. or threads, and (2) if you want to delay for some fixed time, you need an internal queue with timestamps, and you empty the queue based on the timestamp and current time. – dirkt May 14 at 6:06
  • Thanks and I should have been more clear - I was trying to ask if that was the proper way to forward in both directions and it sounds like it is - assuming threads, etc are all taken care of properly. Thanks again! – Digistump May 14 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.