Skip to content

A library to handle RouTing in a Self Generated manner for binary trees.

License

Notifications You must be signed in to change notification settings

Legrandgroup/librtsgtree

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

librtsgtree

A library to handle RouTing in a Self Generated manner for binary trees.

In order to compile this library, just type:

make clean all

This will result in a static library called librtsgtree.a. There is no support for shared library but this could easily be implemented in the Makefile.

If your platform supports native 128-bit integer arithmetic, you can disable the emulation of 128-bit by using the -DHAS_INT128 compiler directive, together with either -DIS_LITTLE_ENDIAN or -DIS_BIG_ENDIAN (please see the [Makefile] content for details)

Code documentation is formatted using doxygen and can be generated using:

make doxygen-doc

Unit tests can be run by issueing:

make check

If you want to use cpputest (needs to be installed) rather than the integrated test harness, just add -DUSE_CPPUTEST to the compiler directives (please see the [Makefile] content for an example)

The lines below describe the algorithm for this project.

Binary-tree distributed routing

This page discusses a technical architecture for addressing and routing inside a binary-tree.

We assume that this binary consists of nodes that are linked point-to-point (interconnecting segments)

The addressing described here is done so that the routing rules can be generated locally.

Integer case

Let's build a tree with 7 nodes N1, N2, N3, N4, N5, N6, N7 (the number of nodes will be represented by a value B, that must be a power of 2 minus 1: B=2^Rmax - 1)

We illustrate below the small binary tree made of these 7 nodes, interconnected with 7 network segments (the top-most segment being the entry into our tree)

          |
          S4
          |
      +---N---+        rank 1
      |   4   |
      |       |
      |S2   S6|
      |       |
   +--N--+ +--N--+     rank 2
   |  2  | |  6  |
   |     | |     |
   |S1 S3| |S5 S7|
   |     | |     |
   N     N N     N     rank 3
   1     3 5     7

On this figure, interconnecting networks segments are noted Sn, and nodes (addressable and routing) are noted Nn

Node numbering follows the uplink segment numbering (Nn always has segment Sn as uplink)

Let's call:

  • Nn: the identifier of each node n (with 1 >= n >= B), each node having an ID that is unique (inside the tree)
  • Sn: network segment between node Nn and its parent node
  • LC(n): left child network segment for node Nn (and thus also left child node ID)
  • RC(n): right child network segment for node Nn (and thus also right child node ID)
  • Rmax: the maximum rank of a node in the tree (aka the tree depth)
  • B: the total number of nodes addressed in the tree (must be a power of 2 minus 1: B=2^Rmax - 1)
  • R: the rank of a node in the tree (root node has R=1, bottom nodes have R=Rmax)
  • P: the prefix length (not used for the integer case, but used later on for IPv4 and IPv6 routing)
  • A: for IPv4 trees this is the number of host bits of the network segments (not used for the integer case, but used later on for IPv4 routing) for IPv6 trees, this is the number of bits allocated for local networks attached to each node

Warning: A has thus different meanings between IPv4 trees and IPv6 trees.

In IPv4, it is a provision of bits to address interconnecting network segments inside the addressing space of the tree

In IPv6, we don't need to use the addressing space of the tree, we use link-local IPv6, however, we can then also benefit from local network attached to tree nodes. Each node thus route to a local network which is allocated a prefix of /A (A=64 recommended)

In the small example above, B = 7 = ( 2^3 ) - 1, thus Rmax = 3 (the bottom rank is rank 3)

Root node properties

We can get the identity of the root node ID:

n = (B+1)/2 = 2^(Rmax-1) = 2^2 = 4

(N4 is the root node and has segment S4 as uplink).

The root can thus self-generate its ID by knowing B (or Rmax).

Once the root is determined, we can number all subnodes in the tree.

Determination of children nodes properties

Based on the value of its parent node number p, and parent node rank Rp, and whether its is the left of right child of its parent node, every node can then define its own properties (ID and network segment)

Rank determination

Practically, Rp can even be calculated if we know p and Rmax:

We count the right most 0 bits from the right of our node ID p, this count will be called b

Rp = R(p) = Rmax - b

So let say we have b = 2 bits set to 0 (third least significant bit is 1), R(p) = Rmax - 2

If there is no bit set to 1, we assume b = Rmax (higher values for b should not be used, they would lead to a negative rank)

In practice, we are not using the subnetwork with all values set to 0 (there is no node N0), so the case with b = Rmax should never occur.

Left children

As a left child, a node will get its node number:

n = LC(p) = p - 2^(Rmax - 1 - Rp)

Right children

As a left child, a node will get its node number:

n = RC(p) = p + 2^(Rmax - 1 - Rp)

Example

For example, for the left child of N4 (the root node in our example):

  • p = 4
  • Rp = 1

LC(4) = 4 - 2^(3-1-1) = 4 - 2 = 2

Left child for N4 is thus N2

The right child of N4 will have an ID: RC(4) = 4 + 2^(3-1-1) = 6, thus this will be node N6

The left child of N6 being: LC(6) = 6 - 2^(3-1-2) = 5

The right child of N6 being: RC(6) = 6 + 2^(3-1-2) = 7

IPv4 addressing and routing in a binary tree

The integer example above is now applied to IPv4 addresses.

The specificities of IPv4 are that:

  • Nodes will be routing devices, but also addressable endpoints.
  • Network segments Sn between two nodes will have their own IPv4 subnet.
  • In this example, we only need to reach routing nodes, so addresses are only allocated for nodes.
  • Each network segment Sn will thus consist of a point-to-point link with two hosts (the two extremity nodes), these network segments will use /30 subnets.
  • By convention, within each /30 subnet, top hosts (path to the root) will take the low IP address inside the subnet, bottom hosts (children) will take the high IP address.
  • Also, nodes all have multiple addresses, but their reference IPv4 address used for communication should be the top one (the one used for the path to the root), as this is the only interface that must be up to be able to communicate with the outside.

IPv4 range to binary tree size

We have a whole IPv4 range allocated for the tree, represented by the range's prefix length P.

A /8 network would give P=8

The individual addresses available with this prefix are encoded with (in IPv4) 32-P bits.

For example, on a /8 network, we have 32-8=24 bits for addressing, or 2^24 possible combinations

We will use /30 interconnecting segments (subnets), so host are encoded using A=2 bits within each /30 network.

Small subnets (/31) for point to point links is discussed in RFC3021, in a effort to save IP addresses, in that case each interconnection network would use A=1 bit

/31 subnets would give us an extra rank in the tree (with a /8 (P=8), we would be able to fit a tree with Rmax = 32 - P - A = 23). But because it may require adaptation of the operating system, it is safer to stick to /30 network, at least initially, reserving extreme addresses for network address and broadcast address, as it is done conventionally. This ensures that any implementation (linux kernel, lwip, etc..) will behave as expected.

Using /30 subnets, for a total /8 (P=8) IP network Rmax = 32 - P - A = 22

Routing applied to IPv4 binary trees

The data can be exchanged within the binary tree from any node to any other.

Nodes can generate their routing table automatically, given their node number n and rank Rn

Indeed:

  • n allows us to know the associated top subnet Sn
  • n and Rn allow us to calculate child node numbers LC(n) and RC(n)
  • LC(n) and RC(n) allow us to know the associated subnets

Left and right routes (to children)

We will setup a first routing rule to each child and its subchildren.

We take LC(n), or RC(n) represent it in binary and left shift by A = 2 (to take into account the host bits required for interconnecting links addressing).

We then keep only the Rn (rank) most significant bits by applying a "bitwise and" mask, this will be the base network for left and right child routes.

The prefix for left and right child rules being P + R

Route up

The next rule allows us to reach our parent subnet Sn, we will use n to compute the top network (use n, represent it in binary and left shift by A = 2 (to take host bits into account)).

The prefix for the top rule will be 32 - A (/30)

A last rule will be a default gateway via our parent to reach the part of the tree that is not below us.

Example using IPv4 private range 192.168.0.0/24

In this example, we are using a /24 range:

P = 24

Interconnection networks are /30 subnets:

A = 2

Therefore our maximum depth is:

Rmax = 32 - 24 - 2 = 6

We thus have 6 bits for nodes numbering.

B = 2^6 - 1 = 63 nodes in this tree

Root subnet

Root node ID:

n = 2^(6-1) = 32 = 100000b

Root is thus N32

Its uplink network is S32.

Note:

Each node can actually guess its node ID based on the size of the tree (Rmax, that would be harcoded on all devices), and on the top interface subnetwork characteristics (that are provided when using ppp IPv4 configuration via ppp's LCP).

A node can thus build all its configuration when the ppp link is brought up on the top interface:

From the uplink network subnet, we apply a "bitwise and" mask with ((2^Rmax - 1 << A), the result will be right shifted of A bits to get the Rmax bits of the network ID (Sn) and thus get the node ID (n)

In our case, the root node will get IPv4 address 192.168.0.130/30 via ppp.

It knows Rmax = 6, and we use /30 interconnecting subnets by convention (A = 2) thus the mask would be:

2^6 - 1 << 2 = 11111100b

We represent the IPv4 address 192.168.0.130 as binary:

uint32(192.168.0.130) = ((192 * 256) + 168) * 65536) + 130 = 11000000 10101000 00000000 10000010b

We apply the mask, then right shift:

(11000000 10101000 00000000 10000010b & 11111100b)>>2 = 100000b = 32

From the node ID, we also can also calculate our rank calculation from node ID. In 100000b, there are 5 right bits set to 0, so b = 5:

R(32) = Rmax - 5 = 1

S32 subnet prefix is built using the network ID (32) left shifted to give room for the 2 last bits (host ID)

100000 00b

We apply a "binary or" of this ID with the network prefix 192.168.0.0/24 and we will get the IPv4 range for S32:

192.168.0.128/30

As explained above, by convention, within this /30 subnet, N32 being the bottom host of S32, it will take the high IPv4: N32 will have IPv4 address 192.168.0.130/30 on S32, and this will be the reference IPv4 address for N32

Root's left child

LC(p) = p - 2^(Rmax - 1 - Rp)

LC(32) = 32 - 2^(6 - 1 - 1) = 16 = 010000b

N32's left child is N16

And the subnet between N32 and N16 is S16

S16 subnet prefix is built using the network ID (16) left shifted to give room for the 2 last bits (host ID)

010000 00b

We apply a "binary or" of this ID with the network prefix 192.168.0.0/24 and we will get the IPv4 range for S16:

192.168.0.64/30

Root's right child

RC(p) = p + 2^(Rmax - 1 - Rp)

RC(32) = 32 + 2^(6 - 1 - 1) = 48 = 110000b

N32's right child is N48

And the subnet between N32 and N48 is S48

S48 subnet prefix is built using the network ID (48) left shifted to give room for the 2 last bits (host ID)

110000 00b

We apply a "binary or" of this ID with the network prefix 192.168.0.0/24 and we will get the IPv4 range for S48:

192.168.0.192/30

Root node's routing table

We apply the routing rule calculation described above on the root node of our example tree.

Root node has ID n=32

Node children's route prefix: P + R = 24 + 1 = 25

Most significant bits mask for node's (left and right) children routes (rank R = 1):

100000b

Left interface routes

Left child: LC(32) = 16 = 010000b

(010000b & 100000b) << 2 = 00000000b = 0

Node's route with left child as next hop via left interface:

  • 192.168.0.0/25

Right interface routes

Right child: RC(32) = 48 = 110000b

(110000b & 100000b) << 2 = 10000000b = 128

Node's route with right child as next hop via right interface:

  • 192.168.0.128/25

Top interface route

Top route: n = 32 = 100000b

(100000 << 2) = 10000000b = 128

Node's route via parent as next hop via top interface:

  • 192.168.0.128/30
  • default route

Visual representation

Let's now illustrate both addressing and routing for the 192.168.0.0/24 subnet taken as example above.

Such a tree will allow addressing 6 nodes at least (most unbalanced tree, nodes placed only in a daisy chain) or B=2^6 - 1=63 nodes at most (balanced tree).

Visual example for IPv4 balanced tree routing

  • Nodes are represented by a blue circle containing Nn (with n being the node ID)
    A node

  • Interconnecting segments Sn (/30 subnets) are represented within blue rectangles
    At the bottom of the segment, the network ID part is displayed in binary (the last 2 bits addressing the hosts within the network, and the global /24 bit prefix are both omitted)
    On this binary value, a blue vertical line is delimiting the left bits used for routing by the parent node (0 in the example below)
    At the top, on top nodes, is displayed the last byte of the IPv4 subnetwork in decimal, with a /30 prefix (192.168.0.64/30 for the example below)
    An interconnecting segment

  • Most node have several network interfaces, and thus several IP addresses, they are represented for each interface in both binary and dotted decimal form + prefix.
    On the top representation, the first 3 bytes between parenthesis correspond to the network prefix, and are displayed in decimal form for lisibility. The remaining bits contain the variable part, with the host part of the /30 network highlighted (host 01b within a network ID of 010000b in the example below)
    A network interface IP address

  • Routing rules are displayed next to each node, for the interface where the packet should be sent.
    The example below means the node should route all traffic to 192.168.0.0/25 to this interface's next hop (which is the other extremity of the point-to-point link).
    An IP route

Using the maximum IPv4 private range 10.0.0.0/8

By choosing addresses in range 10.0.0.0/30 (private network RFC1918) a 22-depth (Rmax = 22) tree is possible.

Such a tree will allow addressing 22 nodes at least (most unbalanced tree, nodes placed only in a daisy chain) or B=2^22-1=4194303 nodes at most (balanced tree).

Subnet and hosts addresses are:

10.0.0.0 (10.0.0.0 reserved for network, 10.0.0.3 reserved for broadcast, 10.0.0.1 and 10.0.0.2 for hosts)

10.0.0.4 (10.0.0.4 reserved for network, 10.0.0.7 reserved for broadcast, 10.0.0.5 and 10.0.0.6 for hosts)

10.0.0.8

...

10.0.0.(4n)

...

10.0.0.252

10.0.1.0

...

10.0.1.252

...

10.0.255.252

...

10.255.255.252

IPv6 addressing and routing in a binary tree

We apply once more the integer example above, but this time to IPv6 addresses.

There are a few differences with the IPv4 case above, mainly because there are link-local addresses assigned to each extremity of point-to-point links, and we can use this addressing for routes' next hops.

The specificities of IPv6 are that:

  • Nodes will be routing devices, but also addressable endpoints (same as IPv4)
  • Network segments Sn between two nodes will not have any IPv6 subnet, we will use link local.
  • In this scenario, we either only need to reach routing nodes (in that case A=0, so addresses are only allocated for nodes), or to reach routing nodes plus local networks attached to routing nodes (A>0)
  • Each network segment Sn will thus consist of a point-to-point link with two hosts (the two extremity nodes), automatically configured with link local IP addresses fe80::/8 at extremities.
  • Also, nodes all have multiple link local addresses, but only one site-global IPv6 address, this reference IPv6 address used for communication should be allocated:
    • if A=0, to the top interface (the one used for the path to the root), as this is the only interface that must be up to be able to communicate with the outside.
    • if A>0, to the first IPv6 address of the local network interface range (bottom interface)

If we will only want to address the nodes of the tree using site-local IPv6 addresses, we will use A=0 (first IPv6 tree example below)

If we want also to address subnets reachable behind each node of the tree using site-local IPv6 addresses, we will use A>0. This is really only required if there are other IPv6 addressable hosts behind each node of the tree (second IPv6 tree example below)

IPv6 range to binary tree size

We have a whole IPv6 range allocated for the tree, represented by the range's prefix length P.

The individual addresses available with this prefix are encoded with (in IPv6) 128-P bits.

We won't use our IPv6 prefix for interconnecting segments' subnets, so host are encoded using the full IPv6 range, that is /P

For the IPv6 case, interconnecting subnets are thus inexistant (we will not allocate any range for these subnets).

Either we directly address the top interface of nodes (A=0) or we address nodes using their bottom interface (A>0)

We will build a tree with Rmax = 128 - P - A

For example, on a /48 network (P=48), we have 128 - 48 = 80 bits for addressing, or 2^80 possible nodes if A=0, or 2^16 possible nodes if A=64 (we allocate a /64 prefix reachable behind each node)

Routing applied to IPv6 binary trees

The data can be exchanged within the binary tree from any node to any other.

Nodes can generate their routing table automatically, given their node number n and rank Rn

Indeed:

  • n allows us to know the associated top subnet Sn
  • n and Rn allow us to calculate child node numbers LC(n) and RC(n)
  • LC(n) and RC(n) allow us to know the associated subnets

Left and right routes (to children)

We will setup a first routing rule to each child and its subchildren.

  1. Case when our children are not at the very bottom of the tree (R<Rmax-1)

The algorithm is the same as the IPv4 case

We take LC(n), or RC(n) represent it in binary.

We then keep only the Rn (rank) most significant bits by applying a "bitwise and" mask, this will be the base network for left and right child routes.

The prefix for left and right child rules being P + R

  1. Case when our children are the leaves of the tree (R=Rmax-1)

We only have one host to address on left and one on right interfaces, so we will directly calculate the child's IPv6 address and add a route to this child using:

  • a host route (/128) if A = 0
  • or a local subnet route (/A) if A > 0

Route up

The next rule allows us to reach our parent host Nn (this is only for non-root nodes, the root node only has a default gateway with next hop to the entry node using its fe80::/64 link-local address).

The prefix for the top rule will be /128-A... we will address only our parent (if A=0) or our parent's local subnet (if A>0)

A last rule will be a default gateway via our parent, to reach the part of the tree that is not below us.

Example using IPv6 site-local range fd00::/124 addressing only tree nodes (A=0)

In this example, we are using a /124 range:

P = 124

In this example, there are no IPv6 local network attached to nodes, we can only address tree nodes, thus hosts/nodes are directly numbered inside the /124 range:

A = 0

Therefore our maximum depth is:

Rmax = 128 - 124 = 4

We thus have 4 bits for nodes numbering.

B = 2^4 - 1 = 15

Root subnet

Root node ID:

n = 2^(4-1) = 8 = 1000b

Root is thus N8

Its uplink network is S8.

Each node can actually get its node ID via parent characteristics (such as the parent ppp hostname configuration received via ppp's LCP).

For example, let's say the parent hostname always sends the following hostname via ppp's LCP:

*-[LR]n

With:

  • '*' containing the parent hostname
  • [LR] being letter L or R if we are handling the left of right node respectively
  • n being the node ID of the parent

For example: "node-R8" sent by node N8 (which has hostname "node") to its right child

If no *-[RL]n pattern is found in the parent hostname by the child, the child will assume it is the root node, and compute its node ID using the 2^(Rmax - 1) formula.

  • Let's say we receive "node-R8" as per the example above, we compute our own node ID: n = RC(8) = 12 = 00001100b Once we know our node ID (12), we also can also calculate our rank calculation from node ID. In 00001100b, there are 2 right bits set to 0, so b = 2: R(12) = Rmax - 2
  • Let's say we receive "smartbox" as the parent hostname, we will elect ourselves as the root ID (parent hostname does not match pattern *-[LR]n). We thus use the root node ID calculation: n = 2^(Rmax-1)

As explained above, by convention, N8 will assign the site-local IPv6 address for the node on the top network interface (the interface to S8):

N8 will have IPv6 address fd00::8/128 on S8, and this will be the reference IPv6 address for N8

Root's left child

LC(p) = p - 2^(Rmax - 1 - Rp)

LC(8) = 8 - 2^(4 - 1 - 1) = 4 = 0100b

N8's left child is N4

On the ppp link to N4, we will announce ourselves to the child via the hostname:

"node-L8"

Root's right child

RC(p) = p + 2^(Rmax - 1 - Rp)

RC(8) = 8 + 2^(4 - 1 - 1) = 12 = 1100b

N8's right child is N12

On the ppp link to N12, we will announce ourselves to the child via the hostname:

"node-R8"

Root node's routing table

We apply the routing rule calculation described above on the root node of our example tree.

Root node has ID n=8

Node children's route prefix: P + R = 124 + 1 = 125

Most significant bits mask for node's (left and right) children routes (rank R = 1):

1000b

Left interface routes

Left child: LC(8) = 4 = 0100b

0100b & 1000b = 0000b = 0x0

Node's route with left child as next hop via left interface:

  • fd00::0/125

Right interface routes

Right child: RC(8) = 12 = 1100b

1100b & 1000b = 1000b = 0x8

Node's route with right child as next hop via right interface:

  • fd00::8/125

Top interface route

Node's route via parent as next hop via top interface:

  • default route

Warning: We don't have a route to the parent node's site-local address, but this is the exception for root nodes.

All other nodes will have (in addition to the default route) a host route to their parent

Visual representation

Let's now illustrate both addressing and routing for the fd00::/124 subnet taken as example above.

Such a tree will allow addressing 4 nodes at least (most unbalanced tree, nodes placed only in a daisy chain) or B=2^4-1=15 nodes at most (balanced tree).

Visual example for IPv6 balanced tree routing

Example using IPv6 site-local range fd00::/60 addressing tree nodes and per-node /64 local networks (A=64)

In this example, we address /64 networks per tree node.

We will use a /60 range:

P = 60

In this example, there are /64 IPv6 local network attached to each node.

A = 64

Therefore our maximum depth is:

Rmax = 128 - 60 - 64 = 4

We thus have 4 bits for nodes numbering.

B = 2^4 - 1 = 15

Root subnet

Root node ID:

n = 2^(4-1) = 8 = 1000b

Root is thus N8

Its uplink network is S8.

The same note described in the A=0 case applies here for top-down characteristics propagation via hostnames

As explained above, and on the contrary to the A=0 case, by convention, N8 will assign the IPv6 address for the node to the bottom network interface (local network, taking either the first IPv6 address in stateful mode, or a stateless IPv6 address if the local network is a /64):

N8 will use an IPv6 address in the range fd00:0:0:8/64 on its bottom interface, and this will be the reference IPv6 address for N8

Root's left child

LC(p) = p - 2^(Rmax - 1 - Rp)

We get the same values as in the A=0 case

Root's right child

RC(p) = p + 2^(Rmax - 1 - Rp)

We get the same values as in the A=0 case

Root node's routing table

We apply the routing rule calculation described above on the root node of our example tree.

Root node has ID n=8

Node children's route prefix: P + R = 60 + 1 = 61

Most significant bits mask for node's (left and right) children routes (rank R = 1):

1000b

Left interface routes

Left child: LC(8) = 4 = 0100b

(0100b & 1000b) << 64 = 0x0

Node's route with left child as next hop via left interface:

  • fd00:0:0:0::/61

Right interface routes

Right child: RC(8) = 12 = 1100b

(1100b & 1000b) << 64 = 0x8 0000 0000 0000 0000

Node's route with right child as next hop via right interface:

  • fd00:0:0:8::/61

Top interface route

Node's route via parent as next hop via top interface:

  • default route

Warning: We don't have a route to the parent node's site-local address, but this is the exception for root nodes.

All other nodes will have (in addition to the default route) a host route to their parent

Visual representation

Let's now illustrate both addressing and routing for the fd00::/60 subnet taken as example above.

Such a tree will allow addressing 4 nodes at least (most unbalanced tree, nodes placed only in a daisy chain) or B = 2^4-1 = 15 nodes at most (balanced tree).

Visual example for IPv6 balanced tree routing with locally attached /64 networks

Compared to the previous IPv6 visual representation, there are /64 networks attached to each bottom interface of each tree node (we detail the range for this local network, vertically in black, under each node)

Using the maximum IPv6 site-local range fd00::/8

By choosing addresses in range fd00::/8 (private network RFC4193) a prefix can be randomly generated (see https://en.wikipedia.org/wiki/Unique_local_address#Definition)

We have two solutions:

  • We provide a 64 bit-wide network to each node N of the tree, allowing each of these nodes to map their field bus endpoints with IPv6 /64 stateless autoconfigured addresses. This leaves us with 56 bits to address our tree (128 - 8 - 64)
  • Or we use the entire fd00::/8 prefix This leaves us with the next 120 bits to address our tree (128 - 8)

Warning: If there is a /64 prefix for each node, we can thus directly address any device located on the field bus (Zigbee or other). The feasability of this solution needs to be checked

IPv6 also has the advantage of being able to address routing nodes (nodes' own interfaces) outside of the global addressing space (using link-local addressing fe80::/64)

In that case, we will probably have to apply case 1 even to parents of leaves when calculating routes down to the last rank.

About

A library to handle RouTing in a Self Generated manner for binary trees.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published