This application is a fork of [https://github.com/microchip-ung/mrp](URL) and it’s born to implement a MRP state machine in user-space only by dropping the kernel support to offload to HW the transmition of MRP_Test frames and MRP_InTest frames, forward all MRP frames and the detection when the ring becomes open or closed.
By dropping this kernel support we can implement a clean MRP state machine as described into the International Standard IEC 62439-2 (Edition 2.0 - 2016-03).
This is the second proposal of implementing a subset of the standard. It supports the following roles:
-
Media Redundancy Manager(MRM),
-
Media Redundancy Client(MRC),
-
Media Redundancy Auto-Manager(MRA),
-
Media Redundancy Interconnection Manager(MIM), and
-
Media Redundancy Interconnection Client(MIC).
In a MRP ring, each node needs to support MRP and in a ring can be only one MRM and multiple MRC. It is possible to have multiple instances of MRP on a single node. But a port can be part of only one MRP instance. In an Interconnect MRP ring, there are only 4 nodes where one node is MIM and the other 3 nodes are MIC.
The MRM is responsible for detecting when there is a loop in the ring. It is sending the frame MRP_Test to detect the loops. It would send MRP_Test on both ports in the ring and if the frame is received at the other end, then the ring is closed. Meaning that there is a loop. In this case it sets the port state to BLOCKED, not allowing traffic to pass through except MRP frames. In case it stops receiving MRP_Test frames from itself then the MRM will detect that the ring is open, therefor it would notify the other nodes of this change and will set the state of the port to be FORWARDING.
Similar with the MRP ring, in the interconnect ring, MIM sends MRP_InTest frames on all 3 ports and expects to receive at least on one port the MRP_InTest frames. The MIM can operate in a different mode where it sends CFM frames on the interconnect port.
The MRC is responsible for forwarding MRP_Test frames between the ring ports (and not to flood on other ports) and to listen when there is a change in the network to clear the FDB.
The MIM is responsible for forwarding MRP_Test frames between ring ports and MRP_InTest frames between all ports.
It depends on the following libs 'libnl', 'libev', 'libmnl' and
'libcfm' and on a kernel that has MRP support (at least v5.8). This last
requirement, at the moment, is mandatory for compiling the code only since the
daemon can be easily modified in order to not use kernel MRP support at all (see ifdriver_*.c
code).
CFM can be found here: https://github.com/microchip-ung/cfm
cmake -B build/ -S .
make -C build
Note: by default the system will use the ifdriver netlink (file ifdriver_netlink.c
). See below if you wish using another ifdriver.
To wipe all generated files during the compilation just use:
rm -rf build
If your system doesn’t support the default netlink ifdriver you can use another one just by appending the string -DMRP_IFDRIVER=<name>
to the cmake
command line. For instance to use the Kbact ifdriver (file ifdriver_kbact.c
) instead of the default one (see above) just use:
cmake -B build/ -S . -DMRP_IFDRIVER=kbact
If you wish using DBus support to remotely signal a port state change, just add the string -DMRP_HAVE_DBus1=ON
to the cmake
command line as below:
cmake -B build/ -S . -DMRP_HAVE_DBus1=ON
By default all Dbus messages are sent to the path /org/mrp/Event
by the interface org.mrp.Event
, but you may alter these defaults by using a command line as below:
cmake -B build/ -S . -DMRP_HAVE_DBus1=ON -DMRP_DBUS_PATH="/org/act/mrp" -DMRP_DBUS_IFACE="org.act.mrp"
Note: to successfully compile the code you may need to install the DBus library code (for instance on Debian based system you can use the command sudo apt install libdbus-1-dev
).
First the server needs to be start. Using the command
mrp_server &
By default the mrp_server doesn’t display any log message. It is possible to start the server using this command to display all the log to the console:
mrp_server -d &
Before configuring the mrp instance it is required to create a bridge and add at least 2 ports to the bridge.
ip link set dev eth0 up
ip link set dev eth1 up
ip link set dev eth2 up
ip link set dev eth3 up
ip link add name br0 type bridge
ip link set dev eth0 master br0
ip link set dev eth1 master br0
ip link set dev eth2 master br0
ip link set dev eth3 master br0
Now that the bridge is created, it is possible to add an MRP instance to the bridge. The client will communicate with the server and the server will notify the kernel via netlink interface.
mrp addmrp bridge br0 ring_nr 1 pport eth0 sport eth1 ring_role mrm
It is possible to create multiple MRP instances on a bridge but, a port can’t be in multiple MRP instances.
mrp addmrp bridge br0 ring_nr 2 pport eth2 sport eth3 ring_role mrm
To see the current status of the MRP instances:
mrp getmrp
bridge: br0 ring_nr: 1 pport: eth0 sport: eth1 ring_role: MRM ring_state: CHK_RO
bridge: br0 ring_nr: 2 pport: eth2 sport: eth3 ring_role: MRM ring_state: CHK_RC
To delete one of the instances is required to pass the bridge and the ring instance number:
mrp delmrp bridge br0 ring_nr 1
bridge: br0 ring_nr: 2 pport: eth2 sport: eth3 ring_role: MRM ring_state: CHK_RC
To create a node that has also an interconnect role:
mrp addmrp bridge br0 ring_nr 3 pport eth0 ssport eth1 ring_role mrc in_role mim in_id 1 iport eth3
By default interconnect mode is RC mode. All the nodes in the interconnect ring needs to operate in the same mode. To create a node with LC mode:
mrp addmrp bridge br0 ring_nr 3 pport eth0 ssport eth1 ring_role mrc in_role mim
in_id 1 iport eth3 in_mode lc cfm_instance 1 cfm_level 7 cfm_mepid 2
cfm_peer_mepid 1 cfm_dmac 00:00:00:00:00:02 cfm_maid ABCD
And once all the MRP rings are created set the bridge device up:
ip link set dev br0 up
For mode details on how to configure CFM: https://github.com/microchip-ung/cfm
Here a list of actually tested ring configurations
A ring with 2, 3, 4, and 8 nodes has been tested with the following layouts:
-
one MRM connected to 1, 2, 3, and 7 MRC
-
all nodes configured as MRA
Here is an ascii art of the network:
+---+ +---+ +---+ +---+ | A +---+ D +-----+ E +---+ H | +-+-+ +-+-+ +-+-+ +-+-+ | | | | +-+-+ +-+-+ +-+-+ +-+-+ | B +---+ C +-----+ F +---+ G | +---+ +---+ +---+ +---+
Ring A-B-C-D has been configured with RingID 1, while ring E-F-G-H with RingID 2. Interconnection ring C-D-E-F has been configured with InID 1 in RC mode. Then all combinations of the MRP roles has been tested on each node.
Here is an ascii art of the network:
+---+ +---+ +---+ +---+ +---+ +---+ | A +---+ C +-----+ D +---+ G +-----+ H +---+ J | +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ +-+-+ | | | | | | | +-+-+ +-+-+ +-+-+ +-+-+ | +-----+ B +-----+ E +---+ F +-----+ K +-----+ +---+ +---+ +---+ +---+
Ring A-B-C has been configured with RingID 1, ring D-E-F-G with RingID 2, and ring H-K-J with RingID 3. Interconnection ring B-C-D-E has been configured with InID 1 in RC mode, while interconnection ring F-G-H-K with InID 2 in RC mode. Then all combinations of the MRP roles has been tested on each node.
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
This code may require licenses from owners of applicable rights.