Layer 2 Server: how to classify frames using their physical source interface

Hi all,

I'm developing a WiFi Mesh software (based on EasyMesh) in Python3. But I'm facing an issue with the part of ieee1905 which needs to use "Neighbor Multicast".

I have a Layer 2 server (receives Ethernet frames) placed in br-lan, which receives all LAN traffic (from the eth switch and wifi). The device that i'm using for the tests is TP Link Archer C7v5.

In short, the Neighbor Multicast consist in check one flag in the payload, if the flag is not set, the multicast frames (to IEEE 1905 Multicast MAC Address) should not be relayed. So, what I've made:

------------------------1) Split all ethernet ports of the switch --------------------------------

And of course, move all the switching function to the Linux Kernel. I need this because I want to resolve in software the relay desition for each physical ethernet interface. If a neighbor multicast enters in one Eth interface, I need to inspect it in software first, and when I see that the flag is not set, I don't forward it to the rest. I've achieved that by using a VLAN per port and bridging all with brctl in br-lan:

gauchomesh_split_interfaces

Which in practice is made in /etc/config/network:


config interface 'loopback'
	option ifname 'lo'
	option proto 'static'
	option ipaddr '127.0.0.1'
	option netmask '255.0.0.0'

config globals 'globals'

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.2.1'
	option ifname 'eth0.1 eth0.2 eth0.3 eth0.4'
	option delegate '0'

config interface 'wan'
	option ifname 'eth0.5'
	option proto 'dhcp'

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option vid '1'
	option ports '2 0t'

config switch_vlan
	option device 'switch0'
	option vlan '5'
	option ports '1 0t'
	option vid '5'

config switch_vlan
	option device 'switch0'
	option vlan '2'
	option ports '3 0t'
	option vid '2'

config switch_vlan
	option device 'switch0'
	option vlan '3'
	option ports '4 0t'
	option vid '3'

config switch_vlan
	option device 'switch0'
	option vlan '4'
	option ports '5 0t'
	option vid '4'

--------------------------------------2) Layer 2 Firewall Rules ---------------------------------

Using Ebtables , I can use configurations in order to forward every IEEE 1905 Multicast Packet to just br-lan interface (no to every physical interface in the bridge), where is my Layer 2 Server who will determine if the frame should be relayed or not.

For example i used:

ebtables_config

-------------------------------------------THE PROBLEM ----------------------------------------

So... "what is the problem?" maybe are you asking. The problem is that... OK I can intercept and decide which frame should be relayed or not in software but... from which physical interface it has come?

I need to know if the frame has entered, for example, from eth0.3. So, if the flag is not set, I won't resend it, but I need to know from where it comes because I'm trying to make a table of Interface/Neighbors. But if the flag is set, I still need to know the physical interface, because I should retransmit the frame to every interface except the source, which at the moment I don't know how to detect (In the example, I should send it to eth0.1, eth0.2, eth0.4, wlan0 and wlan1).

In summary, my question is how can I detect from which physical interface has come a frame received in br-lan?

Any idea or suggetion is welcome.

Thanks in advance,

Pablo.

Doing this in ebtables instead of the nftables system is probably not a good idea. nftables is the modern linux way to handle this stuff, and it supports bridge filtering as well. Debian and Arch and most of the major distributions have moved to nftables with a thin veneer of iptables compatibility layer (the iptables command is basically a translation layer that creates nftables commands underneath).

That being said, I'm pretty sure both ebtables and nftables have ways to determine which physical interface things came in on.

For example in nftables it appears ibriport gives the input bridge port: https://wiki.nftables.org/wiki-nftables/index.php/Matching_packet_metainformation

I don't think your ebtables -o command does what you think... basically it says that "if this packet would normally be sent out "br-lan" then continue..." but br-lan isn't a bridge port, and -o matches bridge ports... in fact --logical-out is the match of interest, but it still doesn't do what you want.

If I were thinking of doing this, I'd probably look into nftables and queuing packets to userspace: https://wiki.nftables.org/wiki-nftables/index.php/Queueing_to_userspace

1 Like

First of all I must tell that with this configuration all works as I described. When a IEEE1905 multicast frame is received, it's passed to the logic interface of the bridge (br-lan, where is the "server" located) and then dropped. I've made a lot of tests with a device sending this kind of frame in periods of 5 seconds and the only device which receives the frame is the neighbor listening in br-lan.

I think that it works because br-lan in some way is a network interface as the rest, no matter if it represents directly a physical interface, a logic bridge or not (due to "if" interfaces are over the network abstraction layer). Anyway, if this is the reason or not, that is working well.

The problem is not identify the receiving interface, the problem is how to communicate it to my application in a way as standard as possible.

So I had a new idea: now I've assigned unique mac address to every interface which represents a physical port, and now I'll explore de "MAC NAT" method or something like that to replace the source MAC Address by the MAC of the receiving interface. Then, the application will know from which interface the frame has entered. Now the obvious question is: "but don't you need the true source MAC Address?"... totally, yes. But I've forgot to mention that in the standard (IEEE1905) el source MAC Address is carried in the payload too. Taking advantage of this redundancy, maybe I could do the trick

I will let you know how it goes.

Thanks!!

Pablo.

What is going on, I think, is that the packet comes in on one port of your bridge, the bridge realizes it's a multicast packet, so it forks this packet into multiple delivery paths: one to anyone listening on br-lan and one to forward out all the other bridge ports.

The forwarded packet fork hits the ebtables FORWARD chain, reaches the -j DROP, and disappears.

the second rule doesn't ever trigger since you've dropped the packet...

So, of course, whoever is listening on br-lan does in fact get the packet because it was delivered before the forwarding table.

Maybe that's it, I forgot to mention that I've switched the order of the rules.

I'll try later just leaving the "drop" rule and see what happens.

I'm almost done, I could change the source mac address (to the port from which it has entered), and stopping the relay of the frame (it's just seen by br-lan).

But the problem is the frame reaches br-lan unmodified, the source mac still being the original. I see the change if I relay the frame to outside (receiving it in other device).

So I'm wondering about te creation of a new virtual interface (abstraction layer interface) which won't be br-lan... so I can forward it to this new interface which will see the frame changed.

But I'm not achieving the creation of it, like doing:

config interface 'AL'

	option ifname 'al1905'
	option macaddr '68:FF:7B:3B:53:92'

At the moment the rules are:

	ebtables -A INPUT -p 0x893a -i eth0.1 -d 01:80:C2:00:00:13 -j mark --set-mark 11 --mark-target CONTINUE #preparamos ebtables para pasar el multicast IEEE1905 a la aplicacion y no reenviarlo por los demas puertos automaticamente
	ebtables -t nat -A POSTROUTING --mark 11 -p 0x893a -j snat --to-source 68:ff:7b:3b:53:99  #hay que hacer una tabla con: interfaz/mac address/marca
	ebtables -A FORWARD -p 0x893a -d 01:80:C2:00:00:13 -j DROP 

This is just for one physycal port, I should do the same for everyone.

Once created this new interface for the abstracion layer, where the application will be addressed, I think that I can add the a rule just before the "DROP":

	ebtables -A FORWARD --mark 11 -p 0x893a -o al1905 -d 01:80:C2:00:00:13 -j CONTINUE

I've created the interface... I will be exploring this way.

Well, how I made it:

1) Create a veth pair of interfaces (virtual ethernet) properly

I will name the pair e-1905 (where the application will listen) and p-1905 (this one will be bridged in br-lan). It would be great reaching this using just one interface (not two), but this way works so go ahead.

First in /etc/config/network config file (or via UCI) you should assign an unique MAC Address and bridge p-1905 with all the LAN ports:

config interface 'AL_lado_app'

	option ifname 'e-1905'
	option macaddr '68:FF:7B:3B:53:98'

config interface 'AL_lado_bridge'

	option ifname 'p-1905'
	option macaddr '68:FF:7B:3B:53:97'

config interface 'lan'
	option type 'bridge'
	option proto 'static'
	option netmask '255.255.255.0'
	option ipaddr '192.168.2.1'
	option ifname 'eth0.1 eth0.2 eth0.3 eth0.4 p-1905'
	option macaddr '68:FF:7B:3B:53:91'
	option delegate '0'

But the veth pair actually does not exist, so we need to create them and restart the network service:

	opkg update
	opkg install ip-full
	opkg install kmod-ebtables-ipv4 # verificar tener este modulo porque si no el postrouting no anda
	opkg install kmod-veth

	ip link add dev p-1905 type veth peer name e-1905
	ifconfig p-1905 down #esta se pone en el bridge
	ifconfig e-1905 down #aca se tiene que parar la aplicacion
	ifconfig p-1905 up #esta se pone en el bridge
	ifconfig e-1905 up #aca se tiene que parar la aplicacion

	ebtables -A FORWARD -p 0x893a -i p-1905 -j mark --set-mark 20 --mark-target CONTINUE #para que la poronga del linux bridge no le cambie la mac address a la AL, no se por que mierda hace eso
	ebtables -t nat -A POSTROUTING --mark 20 -p 0x893a -j snat --to-source 68:FF:7B:3B:53:98 --snat-target CONTINUE

	service network restart

The rule in ebtables is needed because, for some reason, the frames generated in e-1905 are mac-nated by default (they go outside with br-lan mac address), so if we cant to see the e-1905 MAC Address outside we need this rule to explicitly do that.

Remember that e-1905 and p-1905 are totally mirrored, when we make firewall configurations we use p-1905 which is the side bridged in br-lan but the source MAC Address should be the e-1905 MAC Address (in this use case).

2) Change the source MAC Address to multicast frames with the port Address from which it has come

In this example, we have 4 ports so:

	ebtables -A FORWARD -p 0x893a -i eth0.1 -d 01:80:C2:00:00:13 -j mark --set-mark 11 --mark-target CONTINUE #preparamos ebtables para pasar el multicast IEEE1905 a la aplicacion y no reenviarlo por los demas puertos automaticamente
	ebtables -t nat -A POSTROUTING --mark 11 -p 0x893a -j snat --to-source 68:FF:7B:3B:53:93 --snat-target CONTINUE

	ebtables -A FORWARD -p 0x893a -i eth0.2 -d 01:80:C2:00:00:13 -j mark --set-mark 12 --mark-target CONTINUE #preparamos ebtables para pasar el multicast IEEE1905 a la aplicacion y no reenviarlo por los demas puertos automaticamente
	ebtables -t nat -A POSTROUTING --mark 12 -p 0x893a -j snat --to-source 68:FF:7B:3B:53:94 --snat-target CONTINUE

	ebtables -A FORWARD -p 0x893a -i eth0.3 -d 01:80:C2:00:00:13 -j mark --set-mark 13 --mark-target CONTINUE #preparamos ebtables para pasar el multicast IEEE1905 a la aplicacion y no reenviarlo por los demas puertos automaticamente
	ebtables -t nat -A POSTROUTING --mark 13 -p 0x893a -j snat --to-source 68:FF:7B:3B:53:95 --snat-target CONTINUE

	ebtables -A FORWARD -p 0x893a -i eth0.4 -d 01:80:C2:00:00:13 -j mark --set-mark 14 --mark-target CONTINUE #preparamos ebtables para pasar el multicast IEEE1905 a la aplicacion y no reenviarlo por los demas puertos automaticamente
	ebtables -t nat -A POSTROUTING --mark 14 -p 0x893a -j snat --to-source 68:FF:7B:3B:53:96 --snat-target CONTINUE

3) Make firewall configurations to drop the multicast frames except to p-1905 input/output

	ebtables -A FORWARD -p 0x893a -d 01:80:C2:00:00:13 -i p-1905 -j ACCEPT #aceptamos encaminar tramas multicast que entren por p-1905, especialmente para permitir el relayed multicast generando un solo envio de e-1905
	ebtables -A FORWARD -p 0x893a -d 01:80:C2:00:00:13 ! -o p-1905 -j DROP #dropeamos de todas las interfaces menos la de la abstration layer

// --------------------------------------------------------------------------------------------

And that's all. All IEEE1905 multicast frames are forwarded just to e-1905 (and with source MAC Address changed to the receiving port adddress), and e-1905 can send frames with his own MAC Address.

Thanks!!

Pablo.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.