# Cyphal/UDP redundancy

**URL:** <https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822>\
**Category:** Specification\
**Created:** [January 28, 2023, 1:16am UTC](https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822 "2023-01-28T01:16:56Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![scottdixon](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scottdixon/32/39_2.png) [@scottdixon](https://forum.opencyphal.org/u/scottdixon)\
**Post date:** [January 28, 2023, 1:16am UTC](https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822/1 "2023-01-28T01:16:56Z")

</div>

The current specification defines redundant transports abstractly and redundant CAN transports concretely. What is the story for UDP? It’s interesting because Cyphal/TSN can use 802.1CB to meet this requirement but I’m not sure what the plain-old-UDP story should be. Any thoughts on this out there?

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [January 28, 2023, 6:14pm UTC](https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822/2 "2023-01-28T18:14:23Z")

</div>

> [@scottdixon](#):
>
> The current specification defines redundant transports abstractly and redundant CAN transports concretely.

This may not be entirely accurate. The Specification defines redundancy in terms of the behaviors observable on the network while it avoids procedural-level, concrete description (as was the case in v0). The relevant sections are:

- 4.1.2 Redundant transports
- 4.1.3.4 Transmission over redundant transports
- 4.1.4.2 Behaviors

The most pertinent fragment comes from the latter section:

 ![image](https://forum.opencyphal.org/uploads/default/original/2X/f/f7006e702e87ed96ec948fa21b879dbd55f7fcd6.png)

The last paragraph essentially requires a no-fail-over behavior for monotonic transfer-ID transports, such as UDP. The tactics that are chosen to achieve the required behavior is a matter that is outside of the scope of the Specification. One possible approach is described here: [pycyphal.transport.redundant package — PyCyphal 1.27.1 documentation](https://pycyphal.readthedocs.io/en/stable/api/pycyphal.transport.redundant.html)

The important thing to notice is that transport redundancy is independent of the kind of the transport used, aside from one property, which is whether the transfer-ID is expected to overflow while the network is operational (cyclic transfer-ID) or not (monotonic transfer-ID). The former requires fail-over while the latter allows the network to utilize all transports simultaneously and thus achieve no fail-over delay, similar to 802.1CB.

The strong decoupling between the specific transports and the logic that facilitates redundancy enables heterogeneous transport redundancy. This has already been tested with PyCyphal, for example, where there are integration tests that utilize Cyphal/UDP alongside Cyphal/serial in a redundant group.

For Cyphal/TSN specifically, a redundant TSN network might be seen by Cyphal as a single non-redundant transport since the underlying levels are to take care of the redundancy management. This remains to be researched though.

---

<div class="post-metadata">

**Author:** ![scottdixon](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/scottdixon/32/39_2.png) [@scottdixon](https://forum.opencyphal.org/u/scottdixon)\
**Post date:** [February 1, 2023, 12:01am UTC](https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822/3 "2023-02-01T00:01:55Z")

</div>

In conversations I’ve had on this topic the concept of redundancy has been at issue. I submit the below figure to help focus the conversation:

 ![Redundancy by OSI layer](https://forum.opencyphal.org/uploads/default/original/2X/6/6ef0cfb7d912106c278a6c50171e56751b88ba77.png)

Here we see three different ways of providing network redundancy by OSI layer. Layer 1 is opaque to the end system and is therefore not considered. Layer 7 is undefined by Cyphal. It is only Layer 4 that we are discussing.

Sorry if this is painfully obvious but it does become interesting when we consider 802.1CB which provides layer 2 redundancy in a way that won’t be entirely opaque to our specification. That, however, is future work. For Cyphal/UDP I’m reading that you expect a node to handle multiple Ethernet MACs as part of a redundant group. I think that’s something we should prototype to be sure it works as expected.

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [February 1, 2023, 12:03pm UTC](https://forum.opencyphal.org/t/cyphal-udp-redundancy/1822/4 "2023-02-01T12:03:35Z")

</div>

> [@scottdixon](#):
>
> For Cyphal/UDP I’m reading that you expect a node to handle multiple Ethernet MACs as part of a redundant group. I think that’s something we should prototype to be sure it works as expected.

Certainly. I have done some rudimentary prototyping with PyCyphal already. We should revisit this once again after this is in:

> <https://github.com/OpenCyphal/pycyphal/pull/253>
>
> This MR is based on \[this\](https://forum.opencyphal.org/t/cyphal-udp-architectur…al-issues-caused-by-the-dependency-between-the-nodes-ip-address-and-its-identity/1765) proposol discussed in the OpenCyphal forum.
> 
> In short, the changes can be broken down into three pieces:
> 
> \### 1. Datagram header format
> 
> \*Current\*:
> 
> \`\`\`
> uint8 version = 0
> uint8 priority
> void16 
> uint32 frame\_index\_eot
> uint64 transfer\_id
> void64
> \`\`\`
> 
> \*Proposal\*:
> 
> \`\`\`
> uint8 version = 1 # UPDATE
> uint8 priority
> uint16 source\_node\_id # NEW
> uint32 frame\_index\_eot
> uint64 transfer\_id
> void64
> \`\`\`
> 
> Note: \`version\` will be bumped to 1, however no backward-compatibility changes are made (since the protocol is still in development).
> 
> \### 2. Message
> 
> \*Current\*:
> 
> \`\`\`
> fixed reserved
> (9 bits) (3 bits)
> \_\_\_\_\_\_\_\_ \_
> / \\ / \\
> 11101111.0ddddddd.000sssss.ssssssss
> \\\_\_/ \\\_\_\_\_\_/ \\\_\_\_\_\_\_\_\_\_\_\_\_/
> (4 bits) (7 bits) (13 bits)
> IPv4 subnet-ID subject-ID
> multicast \\\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/
> prefix (23 bits)
> collision-free multicast
> addressing limit of
> Ethernet MAC for IPv4
> \`\`\`
> 
> \*Proposal\*:
> 
> \`\`\`
> fixed message reserved
> (9 bits) select. (3 bits)
> \_\_\_\_\_\_\_\_ res.| \_
> / \\ vv / \\
> 11101111.0ddddd00.000sssss.ssssssss
> \\\_\_/ \\\_\_\_/ \\\_\_\_\_\_\_\_\_\_\_\_\_/
> (4 bits) (5 bits) (13 bits)
> IPv4 subnet-ID subject-ID
> multicast \\\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/
> prefix (23 bits)
> collision-free multicast
> addressing limit of
> Ethernet MAC for IPv4
> \`\`\`
> 
> \### 3. Service
> 
> \*Current\*: regular unicast
> 
> 
> \*Proposal\*:
> 
> \`\`\`
> fixed service
> (9 bits) res. selector
> \_\_\_\_\_\_\_\_ ||
> / \\ vv
> 11101111.0ddddd01.nnnnnnnn.nnnnnnnn
> \\\_\_/ \\\_\_\_/ \\\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/
> (4 bits) (5 bits) (16 bits)
> IPv4 subnet-ID node-ID
> multicast \\\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_/
> prefix (23 bits)
> collision-free multicast
> addressing limit of
> Ethernet MAC for IPv4
> \`\`\`
> 
> \### TODO
> 
> \- \[x\] Datagram
> \- \[x\] Message
> \- \[x\] Service
> \- \[x\] Implement \[Scott's changes\](https://forum.opencyphal.org/t/cyphal-udp-architectural-issues-caused-by-the-dependency-between-the-nodes-ip-address-and-its-identity/1765/60)
> \- \[x\] Add anonymous mode
> \- \[x\] Update documentation
