Skip to main content
RunBook Academy

VyOSXXXIV · Route RedistributionKernel redistribution

Redistributing kernel routes — what `redistribute kernel` really carries, and why it is rarely the right answer

Advanced⏱ ~18 minvyosvtyship route showshow ip route kernelshow ip bgpset protocols bgp address-family ipv4-unicast redistribute kernelshow policy route-map

What you'll learn

  • Configure `redistribute kernel` with a route-map under the BGP address family on VyOS 1.5
  • Explain what zebra classifies as a kernel route, and how that differs from static and connected
  • Choose the VyOS-native alternative — static, blackhole, RTBH community — when it exists
  • Recognise the production risk of a route nobody configured being advertised to a peer

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling) · 2026-08-19

Not yet marked complete on this device.

redistribute kernel takes routes that zebra learned from the Linux kernel and originates them into BGP. It is the only redistribution source on a VyOS router whose contents are not described anywhere in the configuration tree — which is exactly what makes it useful in the two or three cases where it is justified, and dangerous everywhere else.

This lesson establishes what a kernel route actually is on a 1.5 router, when redistributing one is defensible, what VyOS gives you instead in the cases where it is not, and the failure mode where a router advertises a prefix that nobody configured.

What zebra calls a kernel route

Two route tables are in play and they are not the same thing.

  • The kernel FIB is what forwards packets. ip route show reads it.
  • Zebra’s RIB is FRR’s view: every route it has learned, from every source, whether or not it won selection. show ip route reads it, through vtysh.

Zebra installs routes into the kernel FIB and also listens to the kernel over netlink. When a route appears in the kernel that zebra did not put there, zebra records it in its own RIB and tags it K — kernel. That is the whole definition: a kernel route is one zebra learned from the kernel rather than from a routing protocol or from its own configuration. It does not matter which program created it; ip route add from a shell, a container runtime, a VPN client and a bespoke daemon calling netlink all produce the same thing.

Configuration changeadds a route outside the VyOS configuration
vyos@r1:~$ sudo ip route add 192.0.2.0/24 via 198.51.100.1 dev eth0

Look at the two views afterwards. The kernel FIB:

ip route show 192.0.2.0/24

And zebra’s RIB, from operational mode — the route code in the first column is the point:

Read-only / Safe
vyos@r1:~$ show ip route 192.0.2.0/24
K>* 192.0.2.0/24 [0/0] via 198.51.100.1, eth0, 00:00:12

Illustrative output

K is kernel. S would be a static route configured under set protocols static route ..., C connected, B BGP, O OSPF. The > means zebra selected this route and the * means it is installed in the FIB. A VyOS-configured static route and a shell-added route are visibly different in this output, and that distinction is the one the redistribution acts on.

When redistributing kernel routes is defensible

The honest list is short:

  • A control system outside VyOS installs routes by design. A telemetry-driven daemon, a scrubbing-centre controller, or an SDN agent that programs the FIB via netlink. Its routes are meant to be advertised, and there is no VyOS node that represents them because they change faster than a commit cycle.
  • You are integrating something that only speaks netlink, and a wrapper that converts its output into VyOS set commands is genuinely not available.

That is close to the whole list. In particular, note two cases that are commonly cited and are not on it, because VyOS already has a first-class answer.

A blackhole for DDoS mitigation. VyOS originates a blackhole route natively:

set protocols static route 203.0.113.0/24 blackhole

That is a configured object: it survives a reboot, appears in compare, is in the config archive, and is redistributable with redistribute static — where the filter and the community tagging are the ordinary, reviewable ones. To signal remote triggered black hole to an upstream, tag it on the way out rather than trusting the route’s origin:

set policy route-map RTBH-OUT rule 10 action 'permit'
set policy route-map RTBH-OUT rule 10 match ip address prefix-list 'RTBH-PFX'
set policy route-map RTBH-OUT rule 10 set community add '65535:666'

The community your upstream honours comes from their documentation, not from this lesson — check it, because sending the wrong one achieves nothing and sending the right one to the wrong peer blackholes traffic you wanted.

An operator’s temporary route. If it is worth having, it is worth a set protocols static route ... and a commit. If it is not worth a commit, it is not worth advertising to a peer.

flowchart TB
  SH["ip route add<br/>(shell, ad hoc)"] --> FIB["Linux kernel FIB"]
  DAEMON["external controller<br/>via netlink"] --> FIB
  FIB -->|netlink notification| Z["zebra RIB<br/>tagged K"]
  Z -->|"redistribute kernel<br/>+ route-map"| BGP["BGP Loc-RIB"]
  CFG["set protocols static route"] --> Z2["zebra RIB<br/>tagged S"]
  Z2 -->|"redistribute static<br/>+ route-map"| BGP
  BGP --> PEER["Peer"]

Both paths reach the peer. Only the lower one is described by the configuration, and that is the entire argument for preferring it.

The configuration

The redistribution lives under the BGP address family in 1.5, not directly under protocols bgp:

set policy prefix-list KERNEL-OK rule 10 action 'permit'
set policy prefix-list KERNEL-OK rule 10 prefix '192.0.2.0/24'

set policy route-map KERNEL-TO-BGP rule 10 action 'permit'
set policy route-map KERNEL-TO-BGP rule 10 match ip address prefix-list 'KERNEL-OK'
set policy route-map KERNEL-TO-BGP rule 10 set metric '100'
set policy route-map KERNEL-TO-BGP rule 10 set community add '64512:600'

set policy route-map KERNEL-TO-BGP rule 999 action 'deny'

set protocols bgp system-as 64512
set protocols bgp address-family ipv4-unicast redistribute kernel route-map 'KERNEL-TO-BGP'

Four things worth reading carefully:

  • The route-map is not optional in practice. Without it, redistribute kernel advertises every kernel route zebra knows about — including ones added by software you did not think about.
  • Rule 999 is a deny with no match, so it denies everything that did not match rule 10. A route-map already ends in an implicit deny; writing it out means the next person does not have to remember that, and it gives the deny a counter.
  • set community add is the 1.4+ spelling of what older documentation writes as set community X additive. The bare set community replace form discards whatever the route already carried, which on a redistributed route is usually harmless and on a re-advertised one is not.
  • The prefix-list is an allow-list of specific prefixes, not a range. redistribute kernel with a permissive filter is barely better than no filter at all.

Kernel, static and connected

All three end up in the kernel FIB, and they are three different redistribution sources:

Zebra codeSourcePersists a rebootIn show configuration commands
CAn address configured on an up interfaceYes, via the interface configYes
Sset protocols static route ...Yes, once savedYes
KThe kernel, from anything zebra did not installNoNo

Read them apart with the operational commands:

show ip route kernel
show ip route static
show ip route connected

show ip route kernel is the audit command for this feature. Any prefix in that output is a prefix whose existence is recorded nowhere but in a running kernel — and if redistribute kernel is configured, potentially in a peer’s routing table too.

Failure modes

A route nobody configured is being advertised

The characteristic incident: a peer reports receiving a prefix that appears in no configuration, no change record and no backup.

Diagnostic, in order:

  1. show ip bgp neighbors 10.0.0.2 advertised-routes — confirm the router really is the source rather than a downstream one.
  2. show ip bgp 10.99.0.0/16 — the BGP table entry names the origin. A redistributed route shows as locally originated.
  3. show ip route 10.99.0.0/16 — the route code says which redistribution is responsible. K points at this feature; S, C or O points somewhere else entirely.
  4. show configuration commands | match redistribute — list every redistribution the router is doing, not just the one you were thinking about.

Only step 3 actually identifies the source. Steps 1 and 2 confirm the symptom and step 4 tells you what else could have caused it — which matters, because “we have redistribute kernel configured” is a hypothesis, not a diagnosis.

Fix:

# Remove the stray route from the kernel.
sudo ip route del 10.99.0.0/16

Then tighten the route-map so the next one cannot leak, and tell the peer to expect the withdrawal. Removing the kernel route withdraws the prefix; it does not undo whatever the peer did with it in the meantime.

The kernel route does not reach BGP

The route is present with ip route show and does not appear in show ip bgp.

  • The route-map denied it. show policy route-map KERNEL-TO-BGP to read the map, and vtysh -c 'show ip prefix-list KERNEL-OK 192.0.2.0/24' to test the prefix-list against the exact prefix. An entry for 192.0.2.0/24 does not match 192.0.2.0/25.
  • Wrong address family. The redistribution sits under address-family ipv4-unicast; an IPv6 kernel route needs the statement repeating under address-family ipv6-unicast.
  • Wrong VRF. A route in the kernel table for a VRF is redistributed by the BGP instance for that VRF, not by the default one.
  • Zebra never saw it as K. Check show ip route <prefix> and read the code. If it says S, it is a configured static route and redistribute static is the statement that carries it.

Do not add “wait for the redistribution cycle” to that list. There is no cycle.

The route disappears after a reboot or a config reload

Expected behaviour, not a fault. A kernel route added outside the configuration tree is gone after a reboot, and with it the BGP advertisement. If the prefix needs to survive, it needs to be a configured object — which is the case for choosing set protocols static route ... over ip route add for anything that is not genuinely transient.

Rollback

delete protocols bgp address-family ipv4-unicast redistribute kernel
commit

That stops the advertisement of every kernel route at once, which is the right emergency lever: it is one command, it is in the configuration, and it is reversible with rollback 1. Narrower options:

  • delete protocols bgp address-family ipv4-unicast redistribute kernel route-map removes only the filter — which makes the redistribution wider, not narrower. It is almost never what you want during an incident.
  • set policy route-map KERNEL-TO-BGP rule 999 action deny is already there if you followed the configuration above; tightening rule 10’s prefix-list is the surgical fix.
  • sudo ip route del <prefix> removes the offending route itself, from the shell. It is not a VyOS command, it is not in the configuration, and nothing records that you ran it — note it in the incident log yourself.

Use commit-confirm 10 for any of these on a router you are reaching over the routes in question.

Production discipline

Cross-course references

  • vyos-xxv-03-bgp-redistribute-static covers the same pattern with a configured source, which is the alternative this lesson keeps pointing at.
  • XXXV-VyOS-Summarisation covers blackhole routes and the aggregation context.
  • vyos-xxxiv-06-redist-anti-patterns covers the broader redistribution failure modes, including mutual redistribution loops.
  • vyos-xxxiii-05-route-map-composition covers the route-map and prefix-list mechanics used for the filter here.

Quiz

Knowledge check · 4 questions

  1. Q1. Which routes does `redistribute kernel` actually carry into BGP?

  2. Q2. With `redistribute kernel` enabled, a route added by `ip route add` from the shell can be advertised to a BGP peer even though it appears nowhere in the VyOS configuration.

  3. Q3. An upstream reports that R1 is advertising 10.99.0.0/16, which appears in no configuration. R1 has `redistribute kernel` with a prefix-list allowing only 192.0.2.0/24. Where do you look, and in what order?

    R1 carries `set protocols bgp address-family ipv4-unicast redistribute kernel route-map KERNEL-TO-BGP`, and KERNEL-TO-BGP permits only 192.0.2.0/24 before a terminal deny. The upstream at 10.0.0.2 says it is receiving 10.99.0.0/16 from R1. Nobody recognises the prefix and it is in no change record.

  4. Q4. A monitoring script blackholes a DDoS target by running `ip route add blackhole 203.0.113.0/24` on R1, which has unfiltered `redistribute kernel`. The upstream now drops all traffic to that prefix. Assess the design.

    R1 carries `set protocols bgp address-family ipv4-unicast redistribute kernel` with no route-map. A monitoring script adds a kernel blackhole route for 203.0.113.0/24 during an attack. The blackhole is redistributed and the upstream provider stops delivering traffic to the prefix.

Passing score: 75%. Answers are checked in this browser.