Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package bird3 for openSUSE:Factory checked 
in at 2026-04-10 17:53:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/bird3 (Old)
 and      /work/SRC/openSUSE:Factory/.bird3.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "bird3"

Fri Apr 10 17:53:22 2026 rev:7 rq:1345710 version:3.2.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/bird3/bird3.changes      2026-03-23 
17:14:32.864617890 +0100
+++ /work/SRC/openSUSE:Factory/.bird3.new.21863/bird3.changes   2026-04-10 
18:02:44.545940203 +0200
@@ -1,0 +2,15 @@
+Tue Apr  7 21:36:27 UTC 2026 - Martin Hauke <[email protected]>
+
+- Update to version 3.2.1
+  * ASPA: Fix downstream validation.
+  * BMP: Fix route sending.
+  * BGP: Fix route refresh after restart.
+  * BGP: Fix dynamic peer connection.
+  * Filters: Fix string attributes.
+  * Filters: Fix ROA check autoreload reconfiguration.
+  * Logging: Fix error handling.
+  * Kernel: Fix graceful recovery.
+  * Pipe: Fix rare collision bug.
+  * Config: Allow keyword redefinition.
+
+-------------------------------------------------------------------

Old:
----
  bird-3.2.0.tar.gz
  bird-doc-3.2.0.tar.gz

New:
----
  bird-3.2.1.tar.gz
  bird-doc-3.2.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ bird3.spec ++++++
--- /var/tmp/diff_new_pack.2tEzvI/_old  2026-04-10 18:02:45.093962809 +0200
+++ /var/tmp/diff_new_pack.2tEzvI/_new  2026-04-10 18:02:45.093962809 +0200
@@ -17,7 +17,7 @@
 
 %define bird_runtimedir %{_rundir}/bird
 Name:           bird3
-Version:        3.2.0
+Version:        3.2.1
 Release:        0
 Summary:        The BIRD Internet Routing Daemon
 License:        GPL-2.0-or-later

++++++ bird-3.2.0.tar.gz -> bird-3.2.1.tar.gz ++++++
++++ 14531 lines of diff (skipped)

++++++ bird-doc-3.2.0.tar.gz -> bird-doc-3.2.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-1.html 
new/bird-doc-3.2.1/doc/bird-1.html
--- old/bird-doc-3.2.0/doc/bird-1.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-1.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Introduction</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Introduction</TITLE>
  <LINK HREF="bird-2.html" REL=next>
 
  <LINK HREF="bird.html#toc1" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-2.html 
new/bird-doc-3.2.1/doc/bird-2.html
--- old/bird-doc-3.2.0/doc/bird-2.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-2.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Architecture</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Architecture</TITLE>
  <LINK HREF="bird-3.html" REL=next>
  <LINK HREF="bird-1.html" REL=previous>
  <LINK HREF="bird.html#toc2" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-3.html 
new/bird-doc-3.2.1/doc/bird-3.html
--- old/bird-doc-3.2.0/doc/bird-3.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-3.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Configuration</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Configuration</TITLE>
  <LINK HREF="bird-4.html" REL=next>
  <LINK HREF="bird-2.html" REL=previous>
  <LINK HREF="bird.html#toc3" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-4.html 
new/bird-doc-3.2.1/doc/bird-4.html
--- old/bird-doc-3.2.0/doc/bird-4.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-4.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Remote control</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Remote control</TITLE>
  <LINK HREF="bird-5.html" REL=next>
  <LINK HREF="bird-3.html" REL=previous>
  <LINK HREF="bird.html#toc4" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-5.html 
new/bird-doc-3.2.1/doc/bird-5.html
--- old/bird-doc-3.2.0/doc/bird-5.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-5.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Filters</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Filters</TITLE>
  <LINK HREF="bird-6.html" REL=next>
  <LINK HREF="bird-4.html" REL=previous>
  <LINK HREF="bird.html#toc5" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-6.html 
new/bird-doc-3.2.1/doc/bird-6.html
--- old/bird-doc-3.2.0/doc/bird-6.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-6.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Protocols</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Protocols</TITLE>
  <LINK HREF="bird-7.html" REL=next>
  <LINK HREF="bird-5.html" REL=previous>
  <LINK HREF="bird.html#toc6" REL=contents>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird-7.html 
new/bird-doc-3.2.1/doc/bird-7.html
--- old/bird-doc-3.2.0/doc/bird-7.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird-7.html  2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide: Conclusions</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide: Conclusions</TITLE>
  <LINK HREF="bird-6.html" REL=previous>
  <LINK HREF="bird.html#toc7" REL=contents>
 </HEAD>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/bird.html 
new/bird-doc-3.2.1/doc/bird.html
--- old/bird-doc-3.2.0/doc/bird.html    2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/bird.html    2026-04-01 20:02:46.000000000 +0200
@@ -2,7 +2,7 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 1.0.9">
- <TITLE>BIRD 3.2.0 User's Guide</TITLE>
+ <TITLE>BIRD 3.2.1 User's Guide</TITLE>
  <LINK HREF="bird-1.html" REL=next>
 
 
@@ -12,12 +12,12 @@
 Previous
 Contents
 <HR>
-<H1>BIRD 3.2.0 User's Guide</H1>
+<H1>BIRD 3.2.1 User's Guide</H1>
 
 <H2>Ondrej Filip <I>&lt;[email protected]&gt;</I>,
 Martin Mares <I>&lt;[email protected]&gt;</I>,
 Maria Matejka <I>&lt;[email protected]&gt;</I>,
-Ondrej Zajicek <I>&lt;[email protected]&gt;</I></H2>Fri, 26 Dec 2025 
17:16:05 +0100bird-userdoc
+Ondrej Zajicek <I>&lt;[email protected]&gt;</I></H2>Wed, 1 Apr 2026 
20:02:46 +0200bird-userdoc
 <P><HR>
 <EM>This document contains user documentation for the BIRD Internet Routing 
Daemon project.</EM>
 <HR>
Binary files old/bird-doc-3.2.0/doc/bird.pdf and 
new/bird-doc-3.2.1/doc/bird.pdf differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-1.html 
new/bird-doc-3.2.1/doc/prog-1.html
--- old/bird-doc-3.2.0/doc/prog-1.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-1.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 Previous
 <A HREF="prog.html#toc1">Contents</A>
 <HR>
-<H2><A NAME="s1">1.</A> <A HREF="prog.html#toc1">BIRD Design</A></H2>
+<H2><A NAME="bird-design"></A> <A NAME="s1">1.</A> <A 
HREF="prog.html#toc1">BIRD Design</A></H2>
 
-<H2><A NAME="ss1.1">1.1</A> <A HREF="prog.html#toc1.1">Introduction</A>
+<H2><A NAME="bird-design-introduction"></A> <A NAME="ss1.1">1.1</A> <A 
HREF="prog.html#toc1.1">Introduction</A>
 </H2>
 
 <P>This document describes the internal workings of BIRD, its architecture,
@@ -32,7 +32,7 @@
 the most important stuff and leaving the boring technical details better 
explained
 by the program source itself together with comments contained therein.
 <P>
-<H2><A NAME="ss1.2">1.2</A> <A HREF="prog.html#toc1.2">Design goals</A>
+<H2><A NAME="bird-design-goals"></A> <A NAME="ss1.2">1.2</A> <A 
HREF="prog.html#toc1.2">Design goals</A>
 </H2>
 
 <P>When planning the architecture of BIRD, we've taken a close look at the 
other existing routing
@@ -97,7 +97,7 @@
 </LI>
 </UL>
 <P>
-<H2><A NAME="ss1.3">1.3</A> <A HREF="prog.html#toc1.3">Architecture</A>
+<H2><A NAME="bird-design-architecture"></A> <A NAME="ss1.3">1.3</A> <A 
HREF="prog.html#toc1.3">Architecture</A>
 </H2>
 
 <P>The requirements set above have lead to a simple modular architecture 
containing
@@ -135,7 +135,7 @@
 <P>
 </DL>
 <P>
-<H2><A NAME="ss1.4">1.4</A> <A HREF="prog.html#toc1.4">Implementation</A>
+<H2><A NAME="bird-design-implementation"></A> <A NAME="ss1.4">1.4</A> <A 
HREF="prog.html#toc1.4">Implementation</A>
 </H2>
 
 <P>BIRD has been written in GNU C. We've considered using C++, but we've
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-2.html 
new/bird-doc-3.2.1/doc/prog-2.html
--- old/bird-doc-3.2.0/doc/prog-2.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-2.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-1.html">Previous</A>
 <A HREF="prog.html#toc2">Contents</A>
 <HR>
-<H2><A NAME="s2">2.</A> <A HREF="prog.html#toc2">Core</A></H2>
+<H2><A NAME="core"></A> <A NAME="s2">2.</A> <A 
HREF="prog.html#toc2">Core</A></H2>
 
-<H2><A NAME="ss2.1">2.1</A> <A HREF="prog.html#toc2.1">Forwarding Information 
Base</A>
+<H2><A NAME="forwarding-information-base"></A> <A NAME="ss2.1">2.1</A> <A 
HREF="prog.html#toc2.1">Forwarding Information Base</A>
 </H2>
 
 <P>
@@ -171,7 +171,7 @@
 <P>This debugging function audits a FIB by checking its internal consistency.
 Use when you suspect somebody of corrupting innocent data structures.
 
-<H2><A NAME="ss2.2">2.2</A> <A HREF="prog.html#toc2.2">Routing tables</A>
+<H2><A NAME="routing-tables"></A> <A NAME="ss2.2">2.2</A> <A 
HREF="prog.html#toc2.2">Routing tables</A>
 </H2>
 
 <P>
@@ -283,6 +283,247 @@
 </DL>
 <H3>Description</H3>
 <P>Implements draft-ietf-sidrops-aspa-verification-16.
+<P>Straightforward implementation of the draft algorithm would be messy, and
+would involve repeatedly checking the table for the same ASN. Therefore, we
+check the path in a streamed way.
+<P>First, necessary preparations are done, to unstuff the path
+(COMPRESSED_AS_PATH, as of -24), and also refusing confeds and sets right away.
+<P>For the algorithm, it's worth noting that the draft indexes the path
+from its end and from one, which has repeatedly brought off-by-one errors
+in our implementation, together with measuring the lengths of the up/down 
ramps.
+We index the path from its beginning and from zero.
+<P>We walk the AS Path from its beginning (which is the local-most ASN) to its 
end
+(which is the alleged origin ASN), and keep four pointers (indices) to it:
+<P>- <B>max_up</B>, the leftmost ASN which can still be part of the up-ramp 
for UNKNOWN
+- <B>min_up</B>, the leftmost ASN which is a definite part of the up-ramp for 
VALID
+- <B>max_down</B>, the rightmost ASN which can still be part of the down-ramp 
for UNKNOWN
+- <B>min_down</B>, the rightmost ASN which is a definite part of the down-ramp 
for VALID
+<P>The draft calls these points the ramp apexes (or apices?).
+<P>All these pointers are initially zero. Technically, they should be 
undefined, but
+for length-one path, both the up-ramp and down-ramp apex is actually at index 
zero.
+<P>The down-ramp then goes from zero index to <CODE>min_down</CODE> for VALID,
+and to <CODE>max_down</CODE> for UNKNOWN. The up-ramp goes backwards
+from the other end (<CODE>nsz-1</CODE>) to <CODE>min_up</CODE> for VALID, and 
to <CODE>max_up</CODE> for UNKNOWN.
+<H3>Example</H3>
+<P>
+<P>min_down = 2
+max_down = 4
+min_up = 4
+max_up = 3
+<P>+---+---+---+---+---+---+---+
+<CODE> 0 </CODE> 1 <CODE> 2 </CODE> 3 <CODE> 4 </CODE> 5 <CODE> 6 </CODE>
+<CODE> down-ramp </CODE> ????? <CODE>-------</CODE>
+<CODE>-----------</CODE> ? <CODE>  up-ramp  </CODE>
++---------------------------+
+<P>Here, again, AS(2) has no ASPA published, ending the certain down-ramp,
+and AS(4) has no ASPA published, ending the certain up-ramp. But, behold!
+The uncertain down-ramp must be ended here by AS(4) actually publishing
+ASPA not including AS(5).
+<P>Therefore, this scenario is impossible.
+<P>We process the AS Path by gradually appending more AS's to an empty path.
+<P>In all steps, it is invariant that, for the downstream algorithm, the 
certain (min)
+down-ramp and up-ramp must cover the whole path to get 
<CODE>ASPA_VALID</CODE>, and otherwise
+the possible (max) down-ramp and up-ramp must cover the whole path to get
+<CODE>ASPA_UNKNOWN</CODE>. Failure to cover the path yields 
<CODE>ASPA_INVALID</CODE>.
+The draft, as of -24, specifies the same but in double-negative.
+<P>Path coverage means that if <CODE>min_up == min_down + 1</CODE>, the path 
is still <CODE>ASPA_VALID</CODE>
+because the apexes are touching, as shown in sec. 5.1 of the draft -24.
+<P>We evaluate this condition at the end of the function. The upstream
+algorithm differs from the downstream algorithm only in such a way that the
+down-ramp is missing.
+<P>In every step, we look at the current ASN (indicated by <B>ap</B>) and its 
left
+and right neighbor, and ask:
+<P>- is there an ASPA by this ASN including the left neighbor?
+If yes, adding this ASN does not change <CODE>max_up</CODE> and 
<CODE>min_up</CODE> because the up-ramp
+is extended by this
+- is there an ASPA by this ASN including the right neighbor?
+If yes, adding the ASN of the right neighbor may move <CODE>max_down</CODE> 
and <CODE>min_down</CODE>
+to that one, unless the down-ramp is already cut off
+- is there any ASPA at all but not for the left neighbor?
+If yes, the up-ramp is broken by this relationship, and we have to move
+both <CODE>min_up</CODE> and <CODE>max_up</CODE> to this ASN
+- is there any ASPA at all but not for the right neighbor?
+If yes, the down-ramp ends here, unless it has been cut off
+by a previous occurence of this situation. We don't move anything.
+- is there no ASPA?
+If yes, we move <CODE>min_up</CODE> because the certain up-ramp is not extended
+by this. Contrary, <CODE>max_up</CODE> stays. The same way but opposite, we may
+move <CODE>max_down</CODE> (if still pointing here) because the maybe down-ramp
+may be extended by this.
+<P>The implementation may look slightly inefficient but we actually want to
+extend it later so that it always returns the complete information,
+i.e. all relevant AS Path chunks, for the users to investigate in the filters.
+<P>After ASPA gets enough traction so that this function performance is
+actually measurable, we expect to update the ASPA checking mechanisms to
+cache all the results, and combine the final result from various path chunks,
+without having to do an ASPA table lookup for every single unique ASN in the
+path.
+<H3>Example</H3>
+<P>
+<P>min_down = 2
+max_down = 4
+min_up = 4
+max_up = 3
+<P>+---+---+---+---+---+---+---+
+<CODE> 0 </CODE> 1 <CODE> 2 </CODE> 3 <CODE> 4 </CODE> 5 <CODE> 6 </CODE>
+<CODE> down-ramp </CODE> ????? <CODE>-------</CODE>
+<CODE>-----------</CODE> ? <CODE>  up-ramp  </CODE>
++---------------------------+
+<P>Here, again, AS(2) has no ASPA published, ending the certain down-ramp,
+and AS(4) has no ASPA published, ending the certain up-ramp. But, behold!
+The uncertain down-ramp must be ended here by AS(4) actually publishing
+ASPA not including AS(5).
+<P>Therefore, this scenario is impossible.
+<P>We process the AS Path by gradually appending more AS's to an empty path.
+<P>In all steps, it is invariant that, for the downstream algorithm, the 
certain (min)
+down-ramp and up-ramp must cover the whole path to get 
<CODE>ASPA_VALID</CODE>, and otherwise
+the possible (max) down-ramp and up-ramp must cover the whole path to get
+<CODE>ASPA_UNKNOWN</CODE>. Failure to cover the path yields 
<CODE>ASPA_INVALID</CODE>.
+The draft, as of -24, specifies the same but in double-negative.
+<P>Path coverage means that if <CODE>min_up == min_down + 1</CODE>, the path 
is still <CODE>ASPA_VALID</CODE>
+because the apexes are touching, as shown in sec. 5.1 of the draft -24.
+<P>We evaluate this condition at the end of the function. The upstream
+algorithm differs from the downstream algorithm only in such a way that the
+down-ramp is missing.
+<P>In every step, we look at the current ASN (indicated by <B>ap</B>) and its 
left
+and right neighbor, and ask:
+<P>- is there an ASPA by this ASN including the left neighbor?
+If yes, adding this ASN does not change <CODE>max_up</CODE> and 
<CODE>min_up</CODE> because the up-ramp
+is extended by this
+- is there an ASPA by this ASN including the right neighbor?
+If yes, adding the ASN of the right neighbor may move <CODE>max_down</CODE> 
and <CODE>min_down</CODE>
+to that one, unless the down-ramp is already cut off
+- is there any ASPA at all but not for the left neighbor?
+If yes, the up-ramp is broken by this relationship, and we have to move
+both <CODE>min_up</CODE> and <CODE>max_up</CODE> to this ASN
+- is there any ASPA at all but not for the right neighbor?
+If yes, the down-ramp ends here, unless it has been cut off
+by a previous occurence of this situation. We don't move anything.
+- is there no ASPA?
+If yes, we move <CODE>min_up</CODE> because the certain up-ramp is not extended
+by this. Contrary, <CODE>max_up</CODE> stays. The same way but opposite, we may
+move <CODE>max_down</CODE> (if still pointing here) because the maybe down-ramp
+may be extended by this.
+<P>The implementation may look slightly inefficient but we actually want to
+extend it later so that it always returns the complete information,
+i.e. all relevant AS Path chunks, for the users to investigate in the filters.
+<P>After ASPA gets enough traction so that this function performance is
+actually measurable, we expect to update the ASPA checking mechanisms to
+cache all the results, and combine the final result from various path chunks,
+without having to do an ASPA table lookup for every single unique ASN in the
+path.
+<H3>Example</H3>
+<P>
+<P>min_down = 2
+max_down = 4
+min_up = 4
+max_up = 3
+<P>+---+---+---+---+---+---+---+
+<CODE> 0 </CODE> 1 <CODE> 2 </CODE> 3 <CODE> 4 </CODE> 5 <CODE> 6 </CODE>
+<CODE> down-ramp </CODE> ????? <CODE>-------</CODE>
+<CODE>-----------</CODE> ? <CODE>  up-ramp  </CODE>
++---------------------------+
+<P>Here, again, AS(2) has no ASPA published, ending the certain down-ramp,
+and AS(4) has no ASPA published, ending the certain up-ramp. But, behold!
+The uncertain down-ramp must be ended here by AS(4) actually publishing
+ASPA not including AS(5).
+<P>Therefore, this scenario is impossible.
+<P>We process the AS Path by gradually appending more AS's to an empty path.
+<P>In all steps, it is invariant that, for the downstream algorithm, the 
certain (min)
+down-ramp and up-ramp must cover the whole path to get 
<CODE>ASPA_VALID</CODE>, and otherwise
+the possible (max) down-ramp and up-ramp must cover the whole path to get
+<CODE>ASPA_UNKNOWN</CODE>. Failure to cover the path yields 
<CODE>ASPA_INVALID</CODE>.
+The draft, as of -24, specifies the same but in double-negative.
+<P>Path coverage means that if <CODE>min_up == min_down + 1</CODE>, the path 
is still <CODE>ASPA_VALID</CODE>
+because the apexes are touching, as shown in sec. 5.1 of the draft -24.
+<P>We evaluate this condition at the end of the function. The upstream
+algorithm differs from the downstream algorithm only in such a way that the
+down-ramp is missing.
+<P>In every step, we look at the current ASN (indicated by <B>ap</B>) and its 
left
+and right neighbor, and ask:
+<P>- is there an ASPA by this ASN including the left neighbor?
+If yes, adding this ASN does not change <CODE>max_up</CODE> and 
<CODE>min_up</CODE> because the up-ramp
+is extended by this
+- is there an ASPA by this ASN including the right neighbor?
+If yes, adding the ASN of the right neighbor may move <CODE>max_down</CODE> 
and <CODE>min_down</CODE>
+to that one, unless the down-ramp is already cut off
+- is there any ASPA at all but not for the left neighbor?
+If yes, the up-ramp is broken by this relationship, and we have to move
+both <CODE>min_up</CODE> and <CODE>max_up</CODE> to this ASN
+- is there any ASPA at all but not for the right neighbor?
+If yes, the down-ramp ends here, unless it has been cut off
+by a previous occurence of this situation. We don't move anything.
+- is there no ASPA?
+If yes, we move <CODE>min_up</CODE> because the certain up-ramp is not extended
+by this. Contrary, <CODE>max_up</CODE> stays. The same way but opposite, we may
+move <CODE>max_down</CODE> (if still pointing here) because the maybe down-ramp
+may be extended by this.
+<P>The implementation may look slightly inefficient but we actually want to
+extend it later so that it always returns the complete information,
+i.e. all relevant AS Path chunks, for the users to investigate in the filters.
+<P>After ASPA gets enough traction so that this function performance is
+actually measurable, we expect to update the ASPA checking mechanisms to
+cache all the results, and combine the final result from various path chunks,
+without having to do an ASPA table lookup for every single unique ASN in the
+path.
+<H3>Example</H3>
+<P>
+<P>min_down = 2
+max_down = 4
+min_up = 4
+max_up = 3
+<P>+---+---+---+---+---+---+---+
+<CODE> 0 </CODE> 1 <CODE> 2 </CODE> 3 <CODE> 4 </CODE> 5 <CODE> 6 </CODE>
+<CODE> down-ramp </CODE> ????? <CODE>-------</CODE>
+<CODE>-----------</CODE> ? <CODE>  up-ramp  </CODE>
++---------------------------+
+<P>Here, again, AS(2) has no ASPA published, ending the certain down-ramp,
+and AS(4) has no ASPA published, ending the certain up-ramp. But, behold!
+The uncertain down-ramp must be ended here by AS(4) actually publishing
+ASPA not including AS(5).
+<P>Therefore, this scenario is impossible.
+<P>We process the AS Path by gradually appending more AS's to an empty path.
+<P>In all steps, it is invariant that, for the downstream algorithm, the 
certain (min)
+down-ramp and up-ramp must cover the whole path to get 
<CODE>ASPA_VALID</CODE>, and otherwise
+the possible (max) down-ramp and up-ramp must cover the whole path to get
+<CODE>ASPA_UNKNOWN</CODE>. Failure to cover the path yields 
<CODE>ASPA_INVALID</CODE>.
+The draft, as of -24, specifies the same but in double-negative.
+<P>Path coverage means that if <CODE>min_up == min_down + 1</CODE>, the path 
is still <CODE>ASPA_VALID</CODE>
+because the apexes are touching, as shown in sec. 5.1 of the draft -24.
+<P>We evaluate this condition at the end of the function. The upstream
+algorithm differs from the downstream algorithm only in such a way that the
+down-ramp is missing.
+<P>In every step, we look at the current ASN (indicated by <B>ap</B>) and its 
left
+and right neighbor, and ask:
+<P>- is there an ASPA by this ASN including the left neighbor?
+If yes, adding this ASN does not change <CODE>max_up</CODE> and 
<CODE>min_up</CODE> because the up-ramp
+is extended by this
+- is there an ASPA by this ASN including the right neighbor?
+If yes, adding the ASN of the right neighbor may move <CODE>max_down</CODE> 
and <CODE>min_down</CODE>
+to that one, unless the down-ramp is already cut off
+- is there any ASPA at all but not for the left neighbor?
+If yes, the up-ramp is broken by this relationship, and we have to move
+both <CODE>min_up</CODE> and <CODE>max_up</CODE> to this ASN
+- is there any ASPA at all but not for the right neighbor?
+If yes, the down-ramp ends here, unless it has been cut off
+by a previous occurence of this situation. We don't move anything.
+- is there no ASPA?
+If yes, we move <CODE>min_up</CODE> because the certain up-ramp is not extended
+by this. Contrary, <CODE>max_up</CODE> stays. The same way but opposite, we may
+move <CODE>max_down</CODE> (if still pointing here) because the maybe down-ramp
+may be extended by this.
+<P>The implementation may look slightly inefficient but we actually want to
+extend it later so that it always returns the complete information,
+i.e. all relevant AS Path chunks, for the users to investigate in the filters.
+<P>After ASPA gets enough traction so that this function performance is
+actually measurable, we expect to update the ASPA checking mechanisms to
+cache all the results, and combine the final result from various path chunks,
+without having to do an ASPA table lookup for every single unique ASN in the
+path.
+<H3>Returns</H3>
+<P><CODE>ASPA_VALID</CODE>, <CODE>ASPA_UNKNOWN</CODE> or 
<CODE>ASPA_INVALID</CODE>.
+<H3>Accesses</H3>
+<P><B>tab</B> for reading.
 
 
 <HR><H3>Function</H3>
@@ -573,7 +814,7 @@
 disconnect from it by calling <B>rt_unlock_table()</B>), if it exists
 in both configurations, leave it unchanged.
 
-<H2><A NAME="ss2.3">2.3</A> <A HREF="prog.html#toc2.3">Route attribute 
cache</A>
+<H2><A NAME="route-attribute-cache"></A> <A NAME="ss2.3">2.3</A> <A 
HREF="prog.html#toc2.3">Route attribute cache</A>
 </H2>
 
 <P>
@@ -873,10 +1114,10 @@
 user (which <B>rta_free()</B> tests by inspecting the use count).
 
 <P>
-<H2><A NAME="ss2.4">2.4</A> <A HREF="prog.html#toc2.4">Routing protocols</A>
+<H2><A NAME="routing-protocols"></A> <A NAME="ss2.4">2.4</A> <A 
HREF="prog.html#toc2.4">Routing protocols</A>
 </H2>
 
-<H3>Introduction</H3>
+<H3><A NAME="routing-protocols-introduction"></A> Introduction</H3>
 
 <P>The routing protocols are the bird's heart and a fine amount of code
 is dedicated to their management and for providing support functions to them.
@@ -911,7 +1152,7 @@
 configuration of protocols, please refer to the configuration chapter and also
 to the description of the <B>proto_commit</B> function.
 <P>
-<H3>Protocol states</H3>
+<H3><A NAME="routing-protocols-states"></A> Protocol states</H3>
 
 <P>As startup and shutdown of each protocol are complex processes which can be 
affected
 by lots of external events (user's actions, reconfigurations, behavior of 
neighboring routers etc.),
@@ -939,7 +1180,7 @@
 <P>
 <P>At any time, the core code can ask the protocol to shut itself down by 
calling its stop() hook.
 <P>
-<H3>Functions of the protocol module</H3>
+<H3><A NAME="routing-protocols-functions"></A> Functions of the protocol 
module</H3>
 
 <P>The protocol module provides the following functions:
 <HR><H3>Function</H3>
@@ -1102,7 +1343,7 @@
 protocol is shut down and a new instance is started with the new
 configuration after the shutdown is completed.
 
-<H2><A NAME="ss2.5">2.5</A> <A HREF="prog.html#toc2.5">Graceful restart 
recovery</A>
+<H2><A NAME="graceful-restart-recovery"></A> <A NAME="ss2.5">2.5</A> <A 
HREF="prog.html#toc2.5">Graceful restart recovery</A>
 </H2>
 
 <P>
@@ -1296,7 +1537,7 @@
 and might execute start callback of protocol; therefore,
 it should be used at tail positions of protocol callbacks.
 
-<H2><A NAME="ss2.6">2.6</A> <A HREF="prog.html#toc2.6">Protocol hooks</A>
+<H2><A NAME="protocol-hooks"></A> <A NAME="ss2.6">2.6</A> <A 
HREF="prog.html#toc2.6">Protocol hooks</A>
 </H2>
 
 <P>
@@ -1701,7 +1942,7 @@
 is removed from a routing table.
 <P>Please avoid using this function in new protocols.
 
-<H2><A NAME="ss2.7">2.7</A> <A HREF="prog.html#toc2.7">Interfaces</A>
+<H2><A NAME="interfaces"></A> <A NAME="ss2.7">2.7</A> <A 
HREF="prog.html#toc2.7">Interfaces</A>
 </H2>
 
 <P>
@@ -1902,7 +2143,7 @@
 <P>This function is called during BIRD startup to initialize
 all data structures of the interface module.
 
-<H2><A NAME="ss2.8">2.8</A> <A HREF="prog.html#toc2.8">MPLS</A>
+<H2><A NAME="mpls"></A> <A NAME="ss2.8">2.8</A> <A 
HREF="prog.html#toc2.8">MPLS</A>
 </H2>
 
 <P>
@@ -1967,7 +2208,7 @@
 - special handling of reserved labels
 <P>
 <P>
-<H2><A NAME="ss2.9">2.9</A> <A HREF="prog.html#toc2.9">Neighbor cache</A>
+<H2><A NAME="neighbor-cache"></A> <A NAME="ss2.9">2.9</A> <A 
HREF="prog.html#toc2.9">Neighbor cache</A>
 </H2>
 
 <P>
@@ -2146,7 +2387,7 @@
 <P>This function is called during BIRD startup to initialize
 the neighbor cache module.
 
-<H2><A NAME="ss2.10">2.10</A> <A HREF="prog.html#toc2.10">Command line 
interface</A>
+<H2><A NAME="command-line-interface"></A> <A NAME="ss2.10">2.10</A> <A 
HREF="prog.html#toc2.10">Command line interface</A>
 </H2>
 
 <P>
@@ -2231,7 +2472,7 @@
 <P>This function is called during BIRD startup to initialize
 the internal data structures of the CLI module.
 
-<H2><A NAME="ss2.11">2.11</A> <A HREF="prog.html#toc2.11">Object locks</A>
+<H2><A NAME="object-locks"></A> <A NAME="ss2.11">2.11</A> <A 
HREF="prog.html#toc2.11">Object locks</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-3.html 
new/bird-doc-3.2.1/doc/prog-3.html
--- old/bird-doc-3.2.0/doc/prog-3.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-3.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-2.html">Previous</A>
 <A HREF="prog.html#toc3">Contents</A>
 <HR>
-<H2><A NAME="s3">3.</A> <A HREF="prog.html#toc3">Configuration</A></H2>
+<H2><A NAME="configuration"></A> <A NAME="s3">3.</A> <A 
HREF="prog.html#toc3">Configuration</A></H2>
 
-<H2><A NAME="ss3.1">3.1</A> <A HREF="prog.html#toc3.1">Configuration 
manager</A>
+<H2><A NAME="configuration-manager"></A> <A NAME="ss3.1">3.1</A> <A 
HREF="prog.html#toc3.1">Configuration manager</A>
 </H2>
 
 <P>
@@ -249,7 +249,7 @@
 It's often used when a string literal occurs in the configuration
 and we want to preserve it for further use.
 
-<H2><A NAME="ss3.2">3.2</A> <A HREF="prog.html#toc3.2">Lexical analyzer</A>
+<H2><A NAME="lexical-analyzer"></A> <A NAME="ss3.2">3.2</A> <A 
HREF="prog.html#toc3.2">Lexical analyzer</A>
 </H2>
 
 <P>
@@ -457,7 +457,7 @@
 <P>This function returns a string representing the class
 of the given symbol.
 
-<H2><A NAME="ss3.3">3.3</A> <A HREF="prog.html#toc3.3">Parser</A>
+<H2><A NAME="parser"></A> <A NAME="ss3.3">3.3</A> <A 
HREF="prog.html#toc3.3">Parser</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-4.html 
new/bird-doc-3.2.1/doc/prog-4.html
--- old/bird-doc-3.2.0/doc/prog-4.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-4.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-3.html">Previous</A>
 <A HREF="prog.html#toc4">Contents</A>
 <HR>
-<H2><A NAME="s4">4.</A> <A HREF="prog.html#toc4">Filters</A></H2>
+<H2><A NAME="filters"></A> <A NAME="s4">4.</A> <A 
HREF="prog.html#toc4">Filters</A></H2>
 
-<H2><A NAME="ss4.1">4.1</A> <A HREF="prog.html#toc4.1">Filters</A>
+<H2><A NAME="filters"></A> <A NAME="ss4.1">4.1</A> <A 
HREF="prog.html#toc4.1">Filters</A>
 </H2>
 
 <P>
@@ -151,7 +151,7 @@
 <H3>Description</H3>
 <P>Compares two trees and returns 1 if they are same
 
-<H2><A NAME="ss4.2">4.2</A> <A HREF="prog.html#toc4.2">Trie for prefix sets</A>
+<H2><A NAME="trie-for-prefix-sets"></A> <A NAME="ss4.2">4.2</A> <A 
HREF="prog.html#toc4.2">Trie for prefix sets</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-5.html 
new/bird-doc-3.2.1/doc/prog-5.html
--- old/bird-doc-3.2.0/doc/prog-5.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-5.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-4.html">Previous</A>
 <A HREF="prog.html#toc5">Contents</A>
 <HR>
-<H2><A NAME="s5">5.</A> <A HREF="prog.html#toc5">Protocols</A></H2>
+<H2><A NAME="protocols"></A> <A NAME="s5">5.</A> <A 
HREF="prog.html#toc5">Protocols</A></H2>
 
-<H2><A NAME="ss5.1">5.1</A> <A HREF="prog.html#toc5.1">The Babel protocol</A>
+<H2><A NAME="the-babel-protocol"></A> <A NAME="ss5.1">5.1</A> <A 
HREF="prog.html#toc5.1">The Babel protocol</A>
 </H2>
 
 <P>
@@ -343,7 +343,7 @@
 <P>This function sets the TX overhead for an interface based on its
 authentication configuration.
 
-<H2><A NAME="ss5.2">5.2</A> <A HREF="prog.html#toc5.2">Bidirectional 
Forwarding Detection</A>
+<H2><A NAME="bidirectional-forwarding-detection"></A> <A NAME="ss5.2">5.2</A> 
<A HREF="prog.html#toc5.2">Bidirectional Forwarding Detection</A>
 </H2>
 
 <P>
@@ -420,7 +420,7 @@
 - RFC 5883 - BFD for multihop paths
 <P>
 <P>
-<H2><A NAME="ss5.3">5.3</A> <A HREF="prog.html#toc5.3">Border Gateway 
Protocol</A>
+<H2><A NAME="border-gateway-protocol"></A> <A NAME="ss5.3">5.3</A> <A 
HREF="prog.html#toc5.3">Border Gateway Protocol</A>
 </H2>
 
 <P>
@@ -970,7 +970,7 @@
 its consistency and converts it to a list of BIRD route attributes represented
 by an (uncached) <I>rta</I>.
 
-<H2><A NAME="ss5.4">5.4</A> <A HREF="prog.html#toc5.4">BGP Monitoring Protocol 
(BMP)</A>
+<H2><A NAME="bgp-monitoring-protocol-(bmp)"></A> <A NAME="ss5.4">5.4</A> <A 
HREF="prog.html#toc5.4">BGP Monitoring Protocol (BMP)</A>
 </H2>
 
 <P>
@@ -1063,7 +1063,7 @@
 <H3>NOTE</H3>
 <P>It does not connect to BMP collector yet.
 
-<H2><A NAME="ss5.5">5.5</A> <A HREF="prog.html#toc5.5">Open Shortest Path 
First (OSPF)</A>
+<H2><A NAME="open-shortest-path-first-(ospf)"></A> <A NAME="ss5.5">5.5</A> <A 
HREF="prog.html#toc5.5">Open Shortest Path First (OSPF)</A>
 </H2>
 
 <P>
@@ -1531,7 +1531,7 @@
 It's based on Dijkstra's shortest path tree algorithms.
 This function is invoked from <B>ospf_disp()</B>.
 
-<H2><A NAME="ss5.6">5.6</A> <A HREF="prog.html#toc5.6">Pipe</A>
+<H2><A NAME="pipe"></A> <A NAME="ss5.6">5.6</A> <A 
HREF="prog.html#toc5.6">Pipe</A>
 </H2>
 
 <P>
@@ -1554,7 +1554,7 @@
 handled similarly, but on the import side of ahooks.
 <P>
 <P>
-<H2><A NAME="ss5.7">5.7</A> <A HREF="prog.html#toc5.7">Router 
Advertisements</A>
+<H2><A NAME="router-advertisements"></A> <A NAME="ss5.7">5.7</A> <A 
HREF="prog.html#toc5.7">Router Advertisements</A>
 </H2>
 
 <P>
@@ -1582,7 +1582,7 @@
 RFC 6106 - DNS extensions (RDDNS, DNSSL)
 <P>
 <P>
-<H2><A NAME="ss5.8">5.8</A> <A HREF="prog.html#toc5.8">Routing Information 
Protocol (RIP)</A>
+<H2><A NAME="routing-information-protocol-(rip)"></A> <A NAME="ss5.8">5.8</A> 
<A HREF="prog.html#toc5.8">Routing Information Protocol (RIP)</A>
 </H2>
 
 <P>
@@ -1776,7 +1776,7 @@
 <P>In Demand Circuit mode, update packets must be acknowledged to ensure
 reliability. If they are not acknowledged, we need to retransmit them.
 
-<H2><A NAME="ss5.9">5.9</A> <A HREF="prog.html#toc5.9">RPKI To Router 
(RPKI-RTR)</A>
+<H2><A NAME="rpki-to-router-(rpki-rtr)"></A> <A NAME="ss5.9">5.9</A> <A 
HREF="prog.html#toc5.9">RPKI To Router (RPKI-RTR)</A>
 </H2>
 
 <P>
@@ -1789,25 +1789,25 @@
 transport. Transport is a way how to wrap a communication with a cache
 server. There is supported an unprotected TCP transport and an encrypted
 SSHv2 transport. The SSH transport requires LibSSH library. LibSSH is
-loading dynamically using <CODE><B>dlopen()</B></CODE> function. SSH support 
is integrated in
+loading dynamically using <B>dlopen()</B> function. SSH support is integrated 
in
 <CODE>sysdep/unix/io.c</CODE>. Each transport must implement an initialization
 function, an open function and a socket identification function. That's all.
 <P>This implementation is based on the RTRlib (http://rpki.realmv6.org/). The
 BIRD takes over files <CODE>packets.c</CODE>, <CODE>rtr.c</CODE> (inside 
<CODE>rpki.c</CODE>), <CODE>transport.c</CODE>,
 <CODE>tcp_transport.c</CODE> and <CODE>ssh_transport.c</CODE> from RTRlib.
 <P>A RPKI-RTR connection is described by a structure <I>rpki_cache</I>. The 
main
-logic is located in <CODE><B>rpki_cache_change_state()</B></CODE> function. 
There is a state
+logic is located in <B>rpki_cache_change_state()</B> function. There is a state
 machine. The standard starting state flow looks like <CODE>Down</CODE> 
&nbsp;&gt; <CODE>Connecting</CODE>
 &nbsp;&gt; <CODE>Sync-Start</CODE> &nbsp;&gt; <CODE>Sync-Running</CODE> 
&nbsp;&gt; <CODE>Established</CODE> and then the last three
 states are periodically repeated.
 <P><CODE>Connecting</CODE> state establishes the transport connection. The 
state from a
-call <CODE>rpki_cache_change_state(CONNECTING)</CODE> to a call 
<CODE><B>rpki_connected_hook()</B></CODE>
+call rpki_cache_change_state(CONNECTING) to a call <B>rpki_connected_hook()</B>
 <P><CODE>Sync-Start</CODE> state starts with sending <CODE>Reset Query</CODE> 
or <CODE>Serial Query</CODE> and
-then waits for <CODE>Cache Response</CODE>. The state from 
<CODE><B>rpki_connected_hook()</B></CODE> to
-<CODE><B>rpki_handle_cache_response_pdu()</B></CODE>
+then waits for <CODE>Cache Response</CODE>. The state from 
<B>rpki_connected_hook()</B> to
+<B>rpki_handle_cache_response_pdu()</B>
 <P>During <CODE>Sync-Running</CODE> BIRD receives data with IPv4/IPv6 Prefixes 
from cache
-server. The state starts from 
<CODE><B>rpki_handle_cache_response_pdu()</B></CODE> and ends
-in <CODE><B>rpki_handle_end_of_data_pdu()</B></CODE>.
+server. The state starts from <B>rpki_handle_cache_response_pdu()</B> and ends
+in <B>rpki_handle_end_of_data_pdu()</B>.
 <P><CODE>Established</CODE> state means that BIRD has synced all data with 
cache server.
 Schedules a refresh timer event that invokes <CODE>Sync-Start</CODE>. 
Schedules Expire
 timer event and stops a Retry timer event.
@@ -1819,8 +1819,8 @@
 restart a protocol, so all ROAs are flushed immediately.
 <P>The RPKI-RTR protocol (RFC 6810 bis) defines configurable refresh, retry and
 expire intervals. For maintaining a connection are used timer events that
-are scheduled by <CODE><B>rpki_schedule_next_refresh()</B></CODE>,
-<CODE><B>rpki_schedule_next_retry()</B></CODE> and 
<CODE><B>rpki_schedule_next_expire()</B></CODE> functions.
+are scheduled by <B>rpki_schedule_next_refresh()</B>,
+<B>rpki_schedule_next_retry()</B> and <B>rpki_schedule_next_expire()</B> 
functions.
 <P>A Refresh timer event performs a sync of <CODE>Established</CODE> 
connection. So it
 shifts state to <CODE>Sync-Start</CODE>. If at the beginning of second call of 
a
 refresh event is connection in <CODE>Sync-Start</CODE> state then we didn't 
receive a
@@ -2224,7 +2224,7 @@
 <DT><I>struct rpki_tr_sock *</I> <B>tr</B><DD><P>allocated RPKI transport 
structure
 </DL>
 
-<H2><A NAME="ss5.10">5.10</A> <A HREF="prog.html#toc5.10">Static</A>
+<H2><A NAME="static"></A> <A NAME="ss5.10">5.10</A> <A 
HREF="prog.html#toc5.10">Static</A>
 </H2>
 
 <P>
@@ -2248,7 +2248,7 @@
 added routes, removes the obsolete ones and reannounces changed ones.
 <P>
 <P>
-<H2><A NAME="ss5.11">5.11</A> <A HREF="prog.html#toc5.11">Direct</A>
+<H2><A NAME="direct"></A> <A NAME="ss5.11">5.11</A> <A 
HREF="prog.html#toc5.11">Direct</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-6.html 
new/bird-doc-3.2.1/doc/prog-6.html
--- old/bird-doc-3.2.0/doc/prog-6.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-6.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-5.html">Previous</A>
 <A HREF="prog.html#toc6">Contents</A>
 <HR>
-<H2><A NAME="s6">6.</A> <A HREF="prog.html#toc6">System dependent 
parts</A></H2>
+<H2><A NAME="sysdep"></A> <A NAME="s6">6.</A> <A HREF="prog.html#toc6">System 
dependent parts</A></H2>
 
-<H2><A NAME="ss6.1">6.1</A> <A HREF="prog.html#toc6.1">Introduction</A>
+<H2><A NAME="sysdep-intro"></A> <A NAME="ss6.1">6.1</A> <A 
HREF="prog.html#toc6.1">Introduction</A>
 </H2>
 
 <P>We've tried to make BIRD as portable as possible, but unfortunately
@@ -22,6 +22,7 @@
 so we need at least some OS specific code. The good news is that this
 code is isolated in a small set of modules:
 <P>
+<P>
 <DL>
 <DT><CODE>config.h</CODE><DD><P>is a header file with configuration 
information,
 definition of the standard set of types and so on.
@@ -34,7 +35,7 @@
 is the most arcane part of the system dependent stuff and some
 functions differ even between various releases of a single OS.
 </DL>
-<H2><A NAME="ss6.2">6.2</A> <A HREF="prog.html#toc6.2">Logging</A>
+<H2><A NAME="logging"></A> <A NAME="ss6.2">6.2</A> <A 
HREF="prog.html#toc6.2">Logging</A>
 </H2>
 
 <P>
@@ -145,7 +146,7 @@
 way that is async safe and can be used in signal handlers. No newline
 character is appended.
 
-<H2><A NAME="ss6.3">6.3</A> <A HREF="prog.html#toc6.3">Kernel 
synchronization</A>
+<H2><A NAME="kernel-synchronization"></A> <A NAME="ss6.3">6.3</A> <A 
HREF="prog.html#toc6.3">Kernel synchronization</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-7.html 
new/bird-doc-3.2.1/doc/prog-7.html
--- old/bird-doc-3.2.0/doc/prog-7.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-7.html  2026-04-01 20:02:46.000000000 +0200
@@ -12,9 +12,9 @@
 <A HREF="prog-6.html">Previous</A>
 <A HREF="prog.html#toc7">Contents</A>
 <HR>
-<H2><A NAME="s7">7.</A> <A HREF="prog.html#toc7">Library functions</A></H2>
+<H2><A NAME="library-functions"></A> <A NAME="s7">7.</A> <A 
HREF="prog.html#toc7">Library functions</A></H2>
 
-<H2><A NAME="ss7.1">7.1</A> <A HREF="prog.html#toc7.1">IP addresses</A>
+<H2><A NAME="ip-addresses"></A> <A NAME="ss7.1">7.1</A> <A 
HREF="prog.html#toc7.1">IP addresses</A>
 </H2>
 
 <P>
@@ -353,7 +353,7 @@
 stores the decoded address to a variable pointed to by <B>o</B>.
 Returns 0 if a parse error has occurred, else 0.
 
-<H2><A NAME="ss7.2">7.2</A> <A HREF="prog.html#toc7.2">Linked lists</A>
+<H2><A NAME="linked-lists"></A> <A NAME="ss7.2">7.2</A> <A 
HREF="prog.html#toc7.2">Linked lists</A>
 </H2>
 
 <P>
@@ -474,7 +474,7 @@
 <P>This function appends all elements of the list <B>l</B> to
 the list <B>to</B> in constant time.
 
-<H2><A NAME="ss7.3">7.3</A> <A HREF="prog.html#toc7.3">Miscellaneous 
functions.</A>
+<H2><A NAME="miscellaneous-functions."></A> <A NAME="ss7.3">7.3</A> <A 
HREF="prog.html#toc7.3">Miscellaneous functions.</A>
 </H2>
 
 <P>
@@ -618,17 +618,17 @@
 <H3>Description</H3>
 <P>This functions acts like ordinary <B>sprintf()</B> except that it checks 
available
 <H3>space to avoid buffer overflows and it allows some more format 
specifiers</H3>
-<P><CODE><I>I</I></CODE> for formatting of IP addresses (width of 1 is 
automatically replaced by
-standard IP address width which depends on whether we use IPv4 or IPv6; 
<CODE><I>I4</I></CODE>
-or <CODE><I>I6</I></CODE> can be used for explicit ip4_addr / ip6_addr 
arguments, <CODE><I>N</I></CODE> for
-generic network addresses (net_addr *), <CODE><I>R</I></CODE> for Router / 
Network ID (u32
-value printed as IPv4 address), <CODE><I>lR</I></CODE> for 64bit Router / 
Network ID (u64
+<P><CODE>%I</CODE> for formatting of IP addresses (width of 1 is automatically 
replaced by
+standard IP address width which depends on whether we use IPv4 or IPv6; 
<CODE>%I4</CODE>
+or <CODE>%I6</CODE> can be used for explicit ip4_addr / ip6_addr arguments, 
<CODE>%N</CODE> for
+generic network addresses (net_addr *), <CODE>%R</CODE> for Router / Network 
ID (u32
+value printed as IPv4 address), <CODE>%lR</CODE> for 64bit Router / Network ID 
(u64
 <H3>value printed as eight </H3>
-<P>-separated octets), <CODE><I>t</I></CODE> for time values (btime) with
-specified subsecond precision, and <CODE><I>m</I></CODE> resp. 
<CODE><I>M</I></CODE> for error messages (uses
+<P>-separated octets), <CODE>%t</CODE> for time values (btime) with
+specified subsecond precision, and <CODE>%m</CODE> resp. <CODE>%M</CODE> for 
error messages (uses
 <B>strerror()</B> to translate <B>errno</B> code to message text). On the 
other hand, it
-doesn't support floating point numbers. The <B>bvsnprintf()</B> supports 
<CODE><I>h</I></CODE> and
-<CODE><I>l</I></CODE> qualifiers, but <CODE><I>l</I></CODE> is used for 
s64/u64 instead of long/ulong.
+doesn't support floating point numbers. The <B>bvsnprintf()</B> supports 
<CODE>%h</CODE> and
+<CODE>%l</CODE> qualifiers, but <CODE>%l</CODE> is used for s64/u64 instead of 
long/ulong.
 <H3>Result</H3>
 <P>number of characters of the output string or -1 if
 the buffer space was insufficient.
@@ -722,7 +722,7 @@
 a <I>NULL</I> pointer.
 <P>Wherever possible, please use the memory resources instead.
 
-<H2><A NAME="ss7.4">7.4</A> <A HREF="prog.html#toc7.4">Message authentication 
codes</A>
+<H2><A NAME="message-authentication-codes"></A> <A NAME="ss7.4">7.4</A> <A 
HREF="prog.html#toc7.4">Message authentication codes</A>
 </H2>
 
 <P>
@@ -853,7 +853,7 @@
 compare it with received <B>mac</B>, return whether they are the same. 
<B>mac_verify()</B>
 is a shortcut function doing all usual steps for received messages.
 
-<H2><A NAME="ss7.5">7.5</A> <A HREF="prog.html#toc7.5">Flow specification 
(flowspec)</A>
+<H2><A NAME="flow-specification-(flowspec)"></A> <A NAME="ss7.5">7.5</A> <A 
HREF="prog.html#toc7.5">Flow specification (flowspec)</A>
 </H2>
 
 <P>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bird-doc-3.2.0/doc/prog-8.html 
new/bird-doc-3.2.1/doc/prog-8.html
--- old/bird-doc-3.2.0/doc/prog-8.html  2025-12-26 17:16:05.000000000 +0100
+++ new/bird-doc-3.2.1/doc/prog-8.html  2026-04-01 20:02:46.000000000 +0200
@@ -11,9 +11,9 @@
 <A HREF="prog-7.html">Previous</A>
 <A HREF="prog.html#toc8">Contents</A>
 <HR>
-<H2><A NAME="s8">8.</A> <A HREF="prog.html#toc8">Resources</A></H2>
+<H2><A NAME="resources"></A> <A NAME="s8">8.</A> <A 
HREF="prog.html#toc8">Resources</A></H2>
 
-<H2><A NAME="ss8.1">8.1</A> <A HREF="prog.html#toc8.1">Introduction</A>
+<H2><A NAME="resources-introduction"></A> <A NAME="ss8.1">8.1</A> <A 
HREF="prog.html#toc8.1">Introduction</A>
 </H2>
 
 <P>Most large software projects implemented in classical procedural
@@ -48,7 +48,7 @@
 <LI><I>Timers</I> (<I>timer</I>) </LI>
 <LI><I>Sockets</I> (<I>socket</I>) </LI>
 </UL>
-<H2><A NAME="ss8.2">8.2</A> <A HREF="prog.html#toc8.2">Resource pools</A>
+<H2><A NAME="resource-pools"></A> <A NAME="ss8.2">8.2</A> <A 
HREF="prog.html#toc8.2">Resource pools</A>
 </H2>
 
 <P>
@@ -174,7 +174,7 @@
 all data structures of the resource manager and creates the
 root pool.
 
-<H2><A NAME="ss8.3">8.3</A> <A HREF="prog.html#toc8.3">Memory blocks</A>
+<H2><A NAME="memory-blocks"></A> <A NAME="ss8.3">8.3</A> <A 
HREF="prog.html#toc8.3">Memory blocks</A>
 </H2>
 
 <P>
@@ -261,7 +261,7 @@
 <H3>Description</H3>
 <P><B>mb_free()</B> frees all memory associated with the block <B>m</B>.
 
-<H2><A NAME="ss8.4">8.4</A> <A HREF="prog.html#toc8.4">Linear memory pools</A>
+<H2><A NAME="linear-memory-pools"></A> <A NAME="ss8.4">8.4</A> <A 
HREF="prog.html#toc8.4">Linear memory pools</A>
 </H2>
 
 <P>
@@ -389,7 +389,7 @@
 the memory, therefore the function also invalidates other states that were
 saved between (on the same pool).
 
-<H2><A NAME="ss8.5">8.5</A> <A HREF="prog.html#toc8.5">Slabs</A>
+<H2><A NAME="slabs"></A> <A NAME="ss8.5">8.5</A> <A 
HREF="prog.html#toc8.5">Slabs</A>
 </H2>
 
 <P>
@@ -479,7 +479,7 @@
 <P>This function frees memory associated with the object <B>oo</B>
 and returns it back to the Slab <B>s</B>.
 
-<H2><A NAME="ss8.6">8.6</A> <A HREF="prog.html#toc8.6">Events</A>
+<H2><A NAME="events"></A> <A NAME="ss8.6">8.6</A> <A 
HREF="prog.html#toc8.6">Events</A>
 </H2>
 
 <P>
@@ -553,7 +553,7 @@
 <H3>Description</H3>
 <P>This function calls <B>ev_run()</B> for all events enqueued in the list 
<B>l</B>.
 
-<H2><A NAME="ss8.7">8.7</A> <A HREF="prog.html#toc8.7">Sockets</A>
+<H2><A NAME="sockets"></A> <A NAME="ss8.7">8.7</A> <A 
HREF="prog.html#toc8.7">Sockets</A>
 </H2>
 
 <P>
Binary files old/bird-doc-3.2.0/doc/prog.pdf and 
new/bird-doc-3.2.1/doc/prog.pdf differ

Reply via email to