8

I would like to forward all L3 packets received on eth0 to another interface lets call m0 (m0 is a custom interface tied into custom hardware with a distinct L2 framing mechanism) as well as the reverse m0->eth0. A sample implementation for m0 could be a SLIP interface for example. I want to achieve this using userspace tools preferably.

The tricky part is I don't want to route. I don't care what the source or destination ipv4 addresses are, and I don't care what the MAC addresses are either. I just want to blindly grab everything from interface 0 and shovel it over interface 1 (and vice versa) without modifying the L3 packets.

I know that everything (in this use case) coming in over eth0 is ipv4 UDP packets that fit in the Ethernet mtu 1500, no fragments. Additionally, it needs to work with multicast addressed packets.

I'm worried that the only way to achieve this is with custom software that is camping on the interface(s) in promiscuous mode. I would like to avoid this because it would be hard to avoid entering a scenario where I loop packets back to their origin.

For example,

  1. Poll eth0 and m0 to see if data is received
  2. packet A received at eth0
  3. packet A captured at eth0 and sent to m0
  4. packet A received at m0
    1. packet A has already been dealt with but how does the software know that? I would have to keep some sort of table of previously handled packets... nasty.

As far as setting it up in Linux, all the research I have done has led me to using combinations of the following, but I don't think they are appropriate in this use case:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -A FORWARD -i eth0 -o m0 -j ACCEPT
iptables -A FORWARD -i m0 -o eth0 -j ACCEPT

Achievable with Static Routing

Verified the interfaces are all working and it isn't a hardware problem by setting static routes and confirming bidirectional messaging. I'm starting to think it simply isn't achievable.

PC0 can now directly connect to PC1; tested with:

    ping 192.168.2.110 -t 10

Received response from PC1 through the radios.

network map:

                              eth0               eth0
                          192.168.0.111      192.168.2.112
              PC0 --- eth --- unit111 --- rf --- unit112 --- eth --- PC1
        192.168.0.110     192.168.1.111      192.168.1.112       192.168.2.110
                               m0                 m0

PC0:

        IFPC=enx4865ee1495b5
        ip link set $IFPC up
        ip addr flush $IFPC
        ip addr add 192.168.0.110/24 dev $IFPC
        ip route add 192.168.1.0/24 via 192.168.0.111
        ip route add 192.168.2.0/24 via 192.168.0.111

unit111:

        ip link set eth0 up
        ip addr flush eth0
        ip addr add 192.168.0.111/24 dev eth0
        ip link set m0 up
        ip addr flush m0
        ip addr add 192.168.1.111/24 dev m0
        ip route add 192.168.2.0/24 via 192.168.1.111
        echo 1 > /proc/sys/net/ipv4/ip_forward

unit112:

        ip link set eth0 up
        ip addr flush eth0
        ip addr add 192.168.2.112/24 dev eth0
        ip link set m0 up
        ip addr flush m0
        ip addr add 192.168.1.112/24 dev m0
        ip route add 192.168.0.0/24 via 192.168.1.112
        echo 1 > /proc/sys/net/ipv4/ip_forward

PC1:

        IFPC=enp0s31f6
        ip link set $IFPC up
        ip addr flush $IFPC
        ip addr add 192.168.2.110/24 dev $IFPC
        ip route add 192.168.1.0/24 via 192.168.2.112
        ip route add 192.168.0.0/24 via 192.168.2.112

Application Context

This is for a radio that has its own L2/L1 used for RF transmission. It is guaranteed placement in a system at the edge of a network and the only packets it receives over its Ethernet interface are to go out over RF. The interface to the L2 used in the RF chain is a DMA that I built a network interface for (m0) because I thought it would simplify connecting it to the Ethernet interface. All of the L2/L1 used for M0 is an FPGA implementation shuffling packets over the m0 DMA.

From the point of view of systems sending/receiving packets from the radio, the radio is basically supposed to look like a wire; packet in, packet out.

Transmit Chain:

[eth rx frame]->[??forward to m0??]->[m0 places pkt in dma for l2 chain]->[frame (L2),mod,out to rf]

Receive chain:

[rf,demod,deframe(L2)]->[m0 rx pkt creates skb]->[??forward to eth0??]->[eth0 rx skb transmits ethernet frame]

The radio is full duplex, it should be able to perform the transmit and receive simultaneously. That is get packets from the Ethernet and transmits them over rf as well as receive packets over rf and send them back out to the Ethernet.

I can place and recover packets into the RF chain using normal socket code through m0 no problem. I just can't figure out how to forward all traffic between the interfaces without touching the packets or opening the interfaces in promiscuous and doing it manually in C code (which as described earlier has its own bag of worms).

intika
  • 13,920
  • 7
  • 41
  • 79
gutelfuldead
  • 80
  • 1
  • 6
  • and a bridge is not suitable because...? – frostschutz Dec 23 '19 at 19:53
  • @frostschutz brctl doesn't like it; modified the question to add the output of attempting to bridge the two devices. Again the error is because m0 is not an ethernet device that uses its own framing. – gutelfuldead Dec 23 '19 at 20:07
  • 1
    packets can be moved with tc ... action mirred ... redirect . But they are left completely untouched: you'd emit an ethernet frame on m0 which obviously wouldn't work. – A.B Dec 23 '19 at 20:18
  • @A.B that's a really interesting idea I haven't heard of tc before. If it works but carries around the L2 header/crc it may be worth modifying the m0 driver code to just strip it and let that be that... Though I would have to also re-add the L2 header for packets going from m0->eth0 which is also a problem... – gutelfuldead Dec 23 '19 at 20:21
  • @A.B do you know offhand what the command would be to forward traffic between the two interfaces? I looked at the tc man page but it wasn't clear on how I could do that. – gutelfuldead Dec 23 '19 at 20:25
  • 1
    yes, but I can't try to explain it. `tc qdisc add dev eth0 ingress ; tc filter add dev eth0 ingress matchall action mirred egress redirect dev m0` and the symetrical commands the other way around (exchange eth0 and m0) (hoping your m0 interface doesn't give trouble about this). – A.B Dec 23 '19 at 20:39
  • 1
    @gutelfuldead oh, I see. so, you (kind of) have a TUN but you really want a TAP... – frostschutz Dec 23 '19 at 20:46
  • 1
    @frostschutz at the end of the day I really want any skb that is created in eth0 to be placed in m0. Any skb that is created in m0 to go to eth0. If I have to remove/generate L2 MAC headers I suppose I can do it in m0's driver code but I'm trying to avoid it. – gutelfuldead Dec 23 '19 at 20:51
  • Can you explain why not routing (I don't mean NAT). Is it the fact the TTL is altered on the packet or something different? I'm curious more than anything. – Philip Couling Dec 23 '19 at 23:46
  • 1
    Seems to me iptables *should* have a mechanism to let you chose which interface to send a packet. This would be a "target". So I wonder if this might help you https://serverfault.com/questions/345111/iptables-target-to-route-packet-to-specific-interface – Philip Couling Dec 23 '19 at 23:51
  • @frostschutz The Linux bridge driver requires sufficiently Ethernet-like interfaces (because it works on MAC addresses): https://elixir.free-electrons.com/linux/v5.4.6/source/net/bridge/br_if.c#L571 – TooTea Dec 27 '19 at 20:32
  • iptables with raw table may be helpful, you should explain what you are trying to achieve there is may be a better solution – intika Jan 01 '20 at 04:37
  • see iptables `-j TEE` target, although it probably changes dst ip hdr. otherwise see `iptables -j MARK` + `ip rule ... fwmark` for nfmark-based routing (as Philip Couling suggested Dec 23 '19 at 23:51) it probably does not alter the packet. – bandie Jan 07 '20 at 11:20

2 Answers2

4

Edit: Forgot that detail "no bridging", but the second article should do the trick as requested, providing the layer 3 solution that can connect different network types such as ethernet and wireless LANs.

Original Answer:

I've done a little search using the phrase "linux kernel interface passthrough", which led me to a few articles on debian.org that seem to provide exactly the answer that you are looking for, so no further fancy explanation here as I don't have anything sensible to add. Note that the second article especially deals with bridging a wired network to a wireless network, dealing with potential problems related to Access Point security.

The software related to in the articles would normally be available in the current Debian repositories.

Article 1: "Bridging Network Connections" at https://wiki.debian.org/BridgeNetworkConnections

Article 2: "Bridging Network Connections with Proxy ARP" at https://wiki.debian.org/BridgeNetworkConnectionsProxyArp (Layer 3 Bridge)

I hope this provides a sensible way forward as I might get a headache if rewriting the given advice (which wouldn't add any value anyway).

Mr. Donutz
  • 370
  • 1
  • 4
  • I hadn't heard of proxy arp before. This seems to be a good solution to fix some potential issues with static routes though I'm not sure it will resolve the fundamental problem of Packet In Packet Out. I intend to mess around with it on the hardware some and learn a bit more. It seems primarily useful when using NAT routing. It also seems like another way of performing what was done with the static routes earlier with a more general rule set. I really need to read up on it more; thanks for giving me another tool to evaluate! – gutelfuldead Jan 06 '20 at 21:26
-2
echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -A FORWARD -i wlan1 -o wlan0 -j ACCEPT
iptables -A FORWARD -i wlan0 -o wlan1 -m state --state ESTABLISHED,RELATED \
         -j ACCEPT
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
roaima
  • 107,089
  • 14
  • 139
  • 261
Soheil
  • 1