<div dir="ltr"><div style="color:rgb(51,51,51);background-color:rgb(245,245,245);font-family:Menlo,Monaco,"Courier New",monospace;font-size:14px;line-height:21px;white-space:pre"><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Title</span></div><br><div>Kernel export does not repair a stale <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">krt_prefsrc</span><span style="color:rgb(119,119,119)">`</span> after an external route attribute mutation</div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Description</span></div><br><div>BIRD keeps its control-plane route and kernel export view consistent with the expected route attributes, but the Linux FIB can remain stale after an externally mutated route is scanned back from the kernel.</div><br><div>In the reproduced case, BIRD exports <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)"><a href="http://198.51.20.0/24">198.51.20.0/24</a></span><span style="color:rgb(119,119,119)">`</span> with <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">krt_metric = 120</span><span style="color:rgb(119,119,119)">`</span> and <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">krt_prefsrc = 10.20.0.1</span><span style="color:rgb(119,119,119)">`</span>. An external <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">ip route replace</span><span style="color:rgb(119,119,119)">`</span> changes only the kernel route preferred source to <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">10.20.0.2</span><span style="color:rgb(119,119,119)">`</span>, while keeping the same prefix, next hop, protocol, and metric. After an unrelated interface flap and a kernel scan, BIRD still reports that the exported route should use <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">Kernel.prefsrc: 10.20.0.1</span><span style="color:rgb(119,119,119)">`</span>, but the Linux FIB remains installed with <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">src 10.20.0.2</span><span style="color:rgb(119,119,119)">`</span>.</div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Version</span></div><br><div>Reproduced with:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div>BIRD 2.18+branch.master.f0f859c26cf9</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">How to reproduce</span></div><br><div><span style="color:rgb(119,119,119)">1.</span><span style="color:rgb(75,105,198)"> Create a single-router Linux namespace or VM with two interfaces. Only </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">eth0</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> carries the tested route; </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">eth1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> is used only to trigger an unrelated interface event.</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">text</span></div><div><span style="color:rgb(75,105,198)">                     10.20.0.254</span></div><div><span style="color:rgb(75,105,198)">                         |</span></div><div><span style="color:rgb(75,105,198)">                  <a href="http://10.20.0.1/24">10.20.0.1/24</a></span></div><div><span style="color:rgb(75,105,198)">                +-------------+</span></div><div><span style="color:rgb(75,105,198)">                |     r1      |</span></div><div><span style="color:rgb(75,105,198)">                |             |</span></div><div><span style="color:rgb(75,105,198)">                | eth0   eth1 |</span></div><div><span style="color:rgb(75,105,198)">                +-------------+</span></div><div><span style="color:rgb(75,105,198)">                         |</span></div><div><span style="color:rgb(75,105,198)">                  unrelated link</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">2.</span><span style="color:rgb(75,105,198)"> Configure BIRD on </span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">r1</span><span style="color:rgb(119,119,119)">`</span><span style="color:rgb(75,105,198)"> with a static source route:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bird</span></div><div><span style="color:rgb(75,105,198)">   protocol static static_src {</span></div><div><span style="color:rgb(75,105,198)">       ipv4;</span></div><div><span style="color:rgb(75,105,198)">       route <a href="http://198.51.20.0/24">198.51.20.0/24</a> via 10.20.0.254;</span></div><div><span style="color:rgb(75,105,198)">   }</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">3.</span><span style="color:rgb(75,105,198)"> Export the route to the kernel with a fixed metric and preferred source:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bird</span></div><div><span style="color:rgb(75,105,198)">   protocol kernel krt_export {</span></div><div><span style="color:rgb(75,105,198)">       ipv4 {</span></div><div><span style="color:rgb(75,105,198)">           export filter {</span></div><div><span style="color:rgb(75,105,198)">               krt_metric = 120;</span></div><div><span style="color:rgb(75,105,198)">               krt_prefsrc = 10.20.0.1;</span></div><div><span style="color:rgb(75,105,198)">               accept;</span></div><div><span style="color:rgb(75,105,198)">           };</span></div><div><span style="color:rgb(75,105,198)">       };</span></div><div><span style="color:rgb(75,105,198)">       scan time 2;</span></div><div><span style="color:rgb(75,105,198)">   }</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">4.</span><span style="color:rgb(75,105,198)"> Confirm BIRD initially installs the expected Linux route:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bash</span></div><div><span style="color:rgb(75,105,198)">   </span>ip route show <a href="http://198.51.20.0/24">198.51.20.0/24</a></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(75,105,198)">   Expected initial route:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">text</span></div><div><span style="color:rgb(75,105,198)">   <a href="http://198.51.20.0/24">198.51.20.0/24</a> via 10.20.0.254 dev eth0 proto bird src 10.20.0.1 metric 120</span></div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">5.</span><span style="color:rgb(75,105,198)"> Externally mutate the same kernel route to a different preferred source while keeping the same destination, next hop, protocol, and metric:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bash</span></div><div><span style="color:rgb(75,105,198)">   </span>ip route replace <a href="http://198.51.20.0/24">198.51.20.0/24</a> via 10.20.0.254 dev eth0 proto bird src 10.20.0.2 metric 120</div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">6.</span><span style="color:rgb(75,105,198)"> Flap the unrelated interface and wait longer than the kernel protocol scan interval:</span></div><br><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span><span style="color:rgb(75,105,198)">bash</span></div><div><span style="color:rgb(75,105,198)">   </span>ip link set eth1 down</div><div><span style="color:rgb(75,105,198)">   </span>ip link set eth1 up</div><div><span style="color:rgb(75,105,198)">   </span>sleep 3</div><div><span style="color:rgb(75,105,198)">   </span><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">7.</span><span style="color:rgb(75,105,198)"> Compare BIRD's source/exported route view with the Linux FIB.</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Expected behavior</span></div><br><div>After the kernel scan, BIRD should notice that the kernel route attributes no longer match the route it exports and should repair the Linux FIB back to:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div><a href="http://198.51.20.0/24">198.51.20.0/24</a> via 10.20.0.254 dev eth0 proto bird src 10.20.0.1 metric 120</div><div><span style="color:rgb(119,119,119)">```</span></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Actual behavior</span></div><br><div>BIRD's source route and export view still indicate the expected route with <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">Kernel.prefsrc: 10.20.0.1</span><span style="color:rgb(119,119,119)">`</span>, but the Linux FIB remains stale:</div><br><div><span style="color:rgb(119,119,119)">```</span>text</div><div><a href="http://198.51.20.0/24">198.51.20.0/24</a> via 10.20.0.254 dev eth0 proto bird src 10.20.0.2 metric 120</div><div><span style="color:rgb(119,119,119)">```</span></div><div><br></div><br><div><span style="color:rgb(119,119,119)">#</span><span style="color:rgb(170,55,49)"> </span><span style="color:rgb(170,55,49);font-weight:bold">Additional context</span></div><br><div>The suspected source path is <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">sysdep/unix/krt.c:krt_got_route()</span><span style="color:rgb(119,119,119)">`</span>. The scan-side comparison checks <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">sync_map</span><span style="color:rgb(119,119,119)">`</span> and <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">krt_same_dest()</span><span style="color:rgb(119,119,119)">`</span>, but it does not compare exported route eattrs such as <span style="color:rgb(119,119,119)">`</span><span style="color:rgb(156,93,39)">krt_prefsrc</span><span style="color:rgb(119,119,119)">`</span>. As a result, a route with the same destination and kernel key can be treated as synchronized even though its exported attributes differ from BIRD's intended route.</div><br></div></div>