Skip to content
/ umrp Public

Fully userspace deamon that runs the Media Redundancy Protocol (MRP) states machine

License

Notifications You must be signed in to change notification settings

giometti/umrp

Repository files navigation

Media Redundancy Protocol(MRP)

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).

MRP

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.

Dependencies

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

Build

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

Build another ifdriver

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

Enable DBus support

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).

Usage

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

Tested rings

Here a list of actually tested ring configurations

One simple ring (no interconnection roles)

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

Two rings with one interconnection

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.

Three rings with two interconnections

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.

Known bugs

  • At the moment just the Kbact ifdriver is known to work properly.

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

This code may require licenses from owners of applicable rights.