mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 11:44:16 +00:00
zebra: Attempt to explain the rnh tracking code better
I got asked today what was going on in the rnh code. I had to take time off of what I was doing and rewrap my head around this code, since it's been a long time. As that this question may come up again in the future I am trying to document this better so that someone coming behind us will be able to read this and get a better idea of what the algorithm is attempting to do. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
This commit is contained in:
parent
0aef4e4041
commit
28237d73ad
@ -795,13 +795,77 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
|
|||||||
struct rnh *rnh;
|
struct rnh *rnh;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are storing the rnh's associated withb
|
* We are storing the rnh's associated with
|
||||||
* the tracked nexthop as a list of the rn's.
|
* the tracked nexthop as a list of the rnh's
|
||||||
|
* on the rn that we have matched to. As an
|
||||||
|
* example if you have these rnh's:
|
||||||
|
* rnh 1.1.1.1
|
||||||
|
* rnh 1.1.1.2
|
||||||
|
* rnh 1.1.3.4
|
||||||
|
* rnh 4.5.6.7
|
||||||
|
* Now imagine that you have in the tree these
|
||||||
|
* prefix's:
|
||||||
|
* 1.1.1.1/32
|
||||||
|
* 1.1.1.0/24
|
||||||
|
* 1.1.0.0/16
|
||||||
|
* 0.0.0.0/0
|
||||||
|
*
|
||||||
|
* The 1.1.1.1 rnh would be stored on 1.1.1.1/32
|
||||||
|
* The 1.1.1.2 rnh would be stored on 1.1.1.0/24
|
||||||
|
* The 1.1.3.4 rnh would be stored on the 1.1.0.0/16
|
||||||
|
* and finally the 4.5.6.7 would be stored on the 0.0.0.0/0
|
||||||
|
* prefix.
|
||||||
|
*
|
||||||
* Unresolved rnh's are placed at the top
|
* Unresolved rnh's are placed at the top
|
||||||
* of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
|
* of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
|
||||||
* As such for each rn we need to walk up the tree
|
* As such for each rn we need to walk up the tree
|
||||||
* and see if any rnh's need to see if they
|
* and see if any rnh's need to see if they
|
||||||
* would match a more specific route
|
* would match a more specific route
|
||||||
|
*
|
||||||
|
* Now if a 1.1.1.2/32 prefix was added to the tree
|
||||||
|
* this function would start at this new node and
|
||||||
|
* see that the 1.1.1.2/32 node has no rnh's and
|
||||||
|
* there is nothing to do on this node currently,
|
||||||
|
* so the function would walk the parent pointers, until the
|
||||||
|
* 1.1.1.0/24 node is hit with the 1.1.1.2 rnh. This function
|
||||||
|
* would then call zebra_evaluate_rnh() which would then
|
||||||
|
* do a LPM and match on the 1.1.1.2/32 node. This function
|
||||||
|
* would then pull the 1.1.1.2 rnh off the 1.1.1.0/24 node
|
||||||
|
* and place it on the 1.1.1.1/32 node and notify the upper
|
||||||
|
* level protocols interested about the change( as necessary ).
|
||||||
|
* At this point in time a sequence number is added to note
|
||||||
|
* that the rnh has been moved.
|
||||||
|
* The function would also continue to walk up the tree
|
||||||
|
* looking at the list of rnh's and moving them around
|
||||||
|
* as necessary. Since in this example nothing else
|
||||||
|
* would change no further actions are made.
|
||||||
|
*
|
||||||
|
* Another case to consider is a node being deleted
|
||||||
|
* suppose the 1.1.1.2/32 route is being deleted.
|
||||||
|
* This function would start at the 1.1.1.1/32 node,
|
||||||
|
* perform a LPM and settle on the 1.1.1.0/24 node
|
||||||
|
* as where it belongs. The code would update appropriate
|
||||||
|
* interested parties and additionally also mark the sequence
|
||||||
|
* number and walk up the tree. Eventually it would get to
|
||||||
|
* the 1.1.1.0/24 node and since the seqno matches we would
|
||||||
|
* know that it is not necessary to reconsider this node
|
||||||
|
* as it was already moved to this spot.
|
||||||
|
*
|
||||||
|
* This all works because each node's parent pointer points
|
||||||
|
* to a node that has a prefix that contains this node. Eventually
|
||||||
|
* the parent traversal will hit the 0.0.0.0/0 node and we know
|
||||||
|
* we are done. We know this is pretty efficient because when
|
||||||
|
* a more specific is added as we walk the tree we can
|
||||||
|
* find the rnh's that matched to a less specific very easily
|
||||||
|
* and move them to a more specific node. Also vice-versa as a
|
||||||
|
* more specific node is removed.
|
||||||
|
*
|
||||||
|
* Long term the rnh code might be improved some as the rnh's
|
||||||
|
* are stored as a list. This might be transformed to a better
|
||||||
|
* data structure. This has not proven to be necessary yet as
|
||||||
|
* that we have not seen any particular case where a rn is
|
||||||
|
* storing more than a couple rnh's. If we find a case
|
||||||
|
* where this matters something might need to be done.
|
||||||
*/
|
*/
|
||||||
while (rn) {
|
while (rn) {
|
||||||
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
|
||||||
|
Loading…
Reference in New Issue
Block a user