Files
ferrix/slides/sections/03-bgp-update.md
T
Rayhaan JaufeerallyandClaude Fable 5.1 2910a2a800 slides: light theme, final edits, single-file bundle
As presented. The palette is light on request of the reviewer; code blocks
and byte dumps keep a dark ground so the byte colours still work. The OPEN
walk lights the hovered bytes as an inverted block and its table cells are
dark text on a tint of their group colour.

build.py inlines reveal.js, the stylesheets, scripts and Markdown sections
into slides/dist/hands-on-bgp.html for uploading.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-01 20:40:55 +02:00

330 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BGP in detail
Notes:
We're going to look at some implementation details of the protocol
---
##
- Runs over TCP, port `179`, and is exchanged typically between peering routers
- Each side tells the other its best route per prefix
- Only _changes_ are sent: no periodic refresh
- If the session drops, after a timeout the routes learned over that session are dropped
Notes:
BGP is a very old protocol, and a lot of it's design predates the internet being something with adversarial participants.
Security and extensions have had to be bolted on, in perhaps strange ways.
---
## The four message types
| Type | Name | Says |
| ---- | ------------ | ------------------------------------------------------- |
| 1 | OPEN | AS number, router ID, capabilities |
| 2 | **UPDATE** | these prefixes are reachable, those no longer are |
| 3 | NOTIFICATION | errors and informational messages: e.g. rebooting |
| 4 | KEEPALIVE | Heartbeat to keep the session up when there's no update |
OPEN, OPEN, KEEPALIVE, KEEPALIVE, and then a stream of UPDATEs.
<!-- .element: class="note" -->
Notes:
There is actually a fifth type, ROUTE-REFRESH: "send me everything again, my policy changed".
---
## OPEN: a handshake between peers.
<svg class="diagram" viewBox="0 0 1000 340" role="img" aria-label="An OPEN message: the common header, then version, AS number, hold time, BGP identifier, and optional parameters that carry the capabilities">
<text x="20" y="22" class="left small pkt-title">header, the same on every message: 19 bytes</text>
<g class="pkt hh"><rect x="20" y="30" width="470" height="64" rx="6"/></g>
<text x="255" y="59" class="pkt-name">marker</text>
<text x="255" y="81" class="pkt-size">16 bytes, all ff</text>
<g class="pkt hh"><rect x="494" y="30" width="240" height="64" rx="6"/></g>
<text x="614" y="59" class="pkt-name">length</text>
<text x="614" y="81" class="pkt-size">2 bytes</text>
<g class="pkt hh"><rect x="738" y="30" width="242" height="64" rx="6"/></g>
<text x="859" y="59" class="pkt-name">type</text>
<text x="859" y="81" class="pkt-size">1 byte</text>
<text x="20" y="132" class="left small pkt-title">OPEN: the fixed part</text>
<g class="pkt hl"><rect x="20" y="140" width="150" height="64" rx="6"/></g>
<text x="95" y="169" class="pkt-name">version</text>
<text x="95" y="191" class="pkt-size">1 byte: 4</text>
<g class="pkt hl"><rect x="174" y="140" width="200" height="64" rx="6"/></g>
<text x="274" y="169" class="pkt-name">my AS</text>
<text x="274" y="191" class="pkt-size">2 bytes, or 23456</text>
<g class="pkt hl"><rect x="378" y="140" width="200" height="64" rx="6"/></g>
<text x="478" y="169" class="pkt-name">hold time</text>
<text x="478" y="191" class="pkt-size">2 bytes, seconds</text>
<g class="pkt hl"><rect x="582" y="140" width="240" height="64" rx="6"/></g>
<text x="702" y="169" class="pkt-name">BGP identifier</text>
<text x="702" y="191" class="pkt-size">4 bytes, the router ID</text>
<g class="pkt hl"><rect x="826" y="140" width="154" height="64" rx="6"/></g>
<text x="903" y="169" class="pkt-name">opt. length</text>
<text x="903" y="191" class="pkt-size">1 byte</text>
<path class="pkt-expand" d="M 826 204 L 20 250"/>
<path class="pkt-expand" d="M 980 204 L 980 250"/>
<text x="20" y="250" class="left small pkt-title">optional parameters: today always one, of type 2 = capabilities, each a (code, length, value)</text>
<g class="pkt ha"><rect x="20" y="258" width="120" height="64" rx="6"/></g>
<text x="80" y="287" class="pkt-name">type 2</text>
<text x="80" y="309" class="pkt-size">capabilities</text>
<g class="pkt ha"><rect x="144" y="258" width="110" height="64" rx="6"/></g>
<text x="199" y="287" class="pkt-name">length</text>
<text x="199" y="309" class="pkt-size">1 byte</text>
<g class="pkt ha2"><rect x="258" y="258" width="200" height="64" rx="6"/></g>
<text x="358" y="287" class="pkt-name">IPv6 unicast</text>
<text x="358" y="309" class="pkt-size">code 1: AFI 2, SAFI 1</text>
<g class="pkt ha2"><rect x="462" y="258" width="190" height="64" rx="6"/></g>
<text x="557" y="287" class="pkt-name">4-byte AS</text>
<text x="557" y="309" class="pkt-size">code 65: 210036</text>
<g class="pkt ha2"><rect x="656" y="258" width="170" height="64" rx="6"/></g>
<text x="741" y="287" class="pkt-name">route refresh</text>
<text x="741" y="309" class="pkt-size">code 2, empty</text>
<g class="pkt ha2"><rect x="830" y="258" width="150" height="64" rx="6"/></g>
<text x="905" y="287" class="pkt-name">…</text>
<text x="905" y="309" class="pkt-size">more capabilities</text>
</svg>
Notes:
Sent once, by each side, as soon as the TCP connection is up. The two sides
must agree: the AS must be the one configured for the neighbour, the hold
time becomes the smaller of the two, and only capabilities both announced are
used. A 4-byte AS does not fit in "my AS", so that field carries 23456 and the
real number rides in a capability, which is how our AS210036 arrives.
---
## BGP Open message
<div class="bytewalk">
<pre class="bytes bw-dump"><span class="hh" data-i="0">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh" data-i="1">00 37</span> <span class="hh" data-i="2">01</span> <span class="hl" data-i="3">04</span> <span class="hl" data-i="4">5b a0</span> <span class="hl" data-i="5">00 f0</span> <span class="hl" data-i="6">0a ff 00 01</span> <span class="hl" data-i="7">1a</span> <span class="ha" data-i="8">02</span> <span class="ha" data-i="9">18</span> <span class="ha2" data-i="10">01</span> <span class="ha2" data-i="11">04</span> <span class="ha2" data-i="12">00 02</span> <span class="ha2" data-i="13">00</span> <span class="ha2" data-i="14">01</span> <span class="ha2" data-i="15">02</span> <span class="ha2" data-i="16">00</span> <span class="ha2" data-i="17">06</span> <span class="ha2" data-i="18">00</span> <span class="ha2" data-i="19">40</span> <span class="ha2" data-i="20">02</span> <span class="ha2" data-i="21">00 00</span> <span class="ha2" data-i="22">41</span> <span class="ha2" data-i="23">04</span> <span class="ha2" data-i="24">00 03 34 74</span> <span class="ha2" data-i="25">46</span> <span class="ha2" data-i="26">00</span> <span class="ha2" data-i="27">47</span> <span class="ha2" data-i="28">00</span></pre>
<div class="bw-rows">
<div class="bw-group">BGP header: 19 bytes, on every message</div>
<div class="bw-row" data-i="0" tabindex="0"><code class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</code><b>marker</b><span>sixteen bytes of ff.</span></div>
<div class="bw-row" data-i="1" tabindex="0"><code class="hh">00 37</code><b>length</b><span>0x0037 = 55 bytes, header included. At most 4096, or 65535 with the extended-message capability</span></div>
<div class="bw-row" data-i="2" tabindex="0"><code class="hh">01</code><b>type</b><span>1 = OPEN (2 UPDATE, 3 NOTIFICATION, 4 KEEPALIVE, 5 ROUTE-REFRESH)</span></div>
<div class="bw-group">OPEN: the fixed part, 10 bytes</div>
<div class="bw-row" data-i="3" tabindex="0"><code class="hl">04</code><b>version</b><span>BGP version 4</span></div>
<div class="bw-row" data-i="4" tabindex="0"><code class="hl">5b a0</code><b>my AS</b><span>0x5ba0 = 23456, AS_TRANS: the ASN is longer than 16 bits so is encoded in a capability instead</span></div>
<div class="bw-row" data-i="5" tabindex="0"><code class="hl">00 f0</code><b>hold time</b><span>0x00f0 = 240 seconds. both peers use the minimum announced; a KEEPALIVE typically is sent every 1/3rd of this duration</span></div>
<div class="bw-row" data-i="6" tabindex="0"><code class="hl">0a ff 00 01</code><b>BGP identifier</b><span>0a ff 00 01 = 10.255.0.1, the router ID. Looks like an IPv4 address, just needs to be a unique identifier.</span></div>
<div class="bw-row" data-i="7" tabindex="0"><code class="hl">1a</code><b>optional parameters length</b><span>0x1a = 26 bytes follow</span></div>
<div class="bw-group">Optional parameter: 2 + 24 bytes</div>
<div class="bw-row" data-i="8" tabindex="0"><code class="ha">02</code><b>parameter type</b><span>2 = capabilities</span></div>
<div class="bw-row" data-i="9" tabindex="0"><code class="ha">18</code><b>parameter length</b><span>0x18 = 24 bytes of capabilities follow, each as type, length, value</span></div>
<div class="bw-group">Capability 1: multiprotocol (RFC 4760)</div>
<div class="bw-row" data-i="10" tabindex="0"><code class="ha2">01</code><b>code</b><span>1 = multiprotocol extensions</span></div>
<div class="bw-row" data-i="11" tabindex="0"><code class="ha2">04</code><b>length</b><span>4</span></div>
<div class="bw-row" data-i="12" tabindex="0"><code class="ha2">00 02</code><b>AFI</b><span>0x0002 = IPv6. Address Family Identifier</span></div>
<div class="bw-row" data-i="13" tabindex="0"><code class="ha2">00</code><b>reserved</b><span>0</span></div>
<div class="bw-row" data-i="14" tabindex="0"><code class="ha2">01</code><b>SAFI</b><span>1 = unicast. Subsequent Address Family Identifier.</span></div>
<div class="bw-group">Capability 2: route refresh (RFC 2918)</div>
<div class="bw-row" data-i="15" tabindex="0"><code class="ha2">02</code><b>code</b><span>2 = route refresh: “you may ask me to resend everything”</span></div>
<div class="bw-row" data-i="16" tabindex="0"><code class="ha2">00</code><b>length</b><span>0</span></div>
<div class="bw-group">Capability 6: extended message (RFC 8654)</div>
<div class="bw-row" data-i="17" tabindex="0"><code class="ha2">06</code><b>code</b><span>6 = messages up to 65535 bytes are supported</span></div>
<div class="bw-row" data-i="18" tabindex="0"><code class="ha2">00</code><b>length</b><span>0</span></div>
<div class="bw-group">Capability 64: graceful restart (RFC 4724)</div>
<div class="bw-row" data-i="19" tabindex="0"><code class="ha2">40</code><b>code</b><span>0x40 = 64, graceful restart</span></div>
<div class="bw-row" data-i="20" tabindex="0"><code class="ha2">02</code><b>length</b><span>2</span></div>
<div class="bw-row" data-i="21" tabindex="0"><code class="ha2">00 00</code><b>flags and restart time</b><span>0x0000: not restarting, restart time 0, and no address families listed.</span></div>
<div class="bw-group">Capability 65: four-octet AS (RFC 6793)</div>
<div class="bw-row" data-i="22" tabindex="0"><code class="ha2">41</code><b>code</b><span>0x41 = 65, four-octet AS number</span></div>
<div class="bw-row" data-i="23" tabindex="0"><code class="ha2">04</code><b>length</b><span>4</span></div>
<div class="bw-row" data-i="24" tabindex="0"><code class="ha2">00 03 34 74</code><b>AS number</b><span>00 03 34 74 = 210036: the real AS. Included here since it doesn't fit in the header</span></div>
<div class="bw-group">Capability 70: enhanced route refresh (RFC 7313)</div>
<div class="bw-row" data-i="25" tabindex="0"><code class="ha2">46</code><b>code</b><span>0x46 = 70</span></div>
<div class="bw-row" data-i="26" tabindex="0"><code class="ha2">00</code><b>length</b><span>0</span></div>
<div class="bw-group">Capability 71: long-lived graceful restart</div>
<div class="bw-row" data-i="27" tabindex="0"><code class="ha2">47</code><b>code</b><span>0x47 = 71</span></div>
<div class="bw-row" data-i="28" tabindex="0"><code class="ha2">00</code><b>length</b><span>0, no address families listed</span></div>
</div>
</div>
Notes:
What BIRD on our upstream router sends the lab daemon, byte for byte. Hold
time 240 is BIRD's default; keepalives go every third of it.
---
## Update message format
<svg class="diagram" viewBox="0 0 1000 460" role="img" aria-label="An UPDATE message: the common header, then withdrawn routes, path attributes and NLRI, with one attribute and one prefix expanded">
<text x="20" y="22" class="left small pkt-title">header: 19 bytes</text>
<g class="pkt hh"><rect x="20" y="30" width="470" height="64" rx="6"/></g>
<text x="255" y="59" class="pkt-name">marker</text>
<text x="255" y="81" class="pkt-size">16 bytes, all ff</text>
<g class="pkt hh"><rect x="494" y="30" width="240" height="64" rx="6"/></g>
<text x="614" y="59" class="pkt-name">length</text>
<text x="614" y="81" class="pkt-size">2 bytes</text>
<g class="pkt hh"><rect x="738" y="30" width="242" height="64" rx="6"/></g>
<text x="859" y="59" class="pkt-name">type</text>
<text x="859" y="81" class="pkt-size">1 byte</text>
<text x="20" y="132" class="left small pkt-title">UPDATE body: two lengths, three variable parts</text>
<g class="pkt hl"><rect x="20" y="140" width="170" height="64" rx="6"/></g>
<text x="105" y="169" class="pkt-name">withdrawn length</text>
<text x="105" y="191" class="pkt-size">2 bytes</text>
<g class="pkt hn"><rect x="194" y="140" width="200" height="64" rx="6"/></g>
<text x="294" y="169" class="pkt-name">withdrawn routes</text>
<text x="294" y="191" class="pkt-size">IPv4 prefixes gone</text>
<g class="pkt hl"><rect x="398" y="140" width="170" height="64" rx="6"/></g>
<text x="483" y="169" class="pkt-name">attributes length</text>
<text x="483" y="191" class="pkt-size">2 bytes</text>
<g class="pkt ha"><rect x="572" y="140" width="240" height="64" rx="6"/></g>
<text x="692" y="169" class="pkt-name">path attributes</text>
<text x="692" y="191" class="pkt-size">everything about the route</text>
<g class="pkt hn"><rect x="816" y="140" width="172" height="64" rx="6"/></g>
<text x="902" y="169" class="pkt-name">NLRI</text>
<text x="902" y="191" class="pkt-size">IPv4 prefixes, new</text>
<path class="pkt-expand" d="M 572 204 L 20 250"/>
<path class="pkt-expand" d="M 812 204 L 980 250"/>
<text x="20" y="250" class="left small pkt-title">one path attribute; repeated for multiple</text>
<g class="pkt ha"><rect x="20" y="258" width="150" height="64" rx="6"/></g>
<text x="95" y="287" class="pkt-name">flags</text>
<text x="95" y="309" class="pkt-size">1 byte</text>
<g class="pkt ha"><rect x="174" y="258" width="330" height="64" rx="6"/></g>
<text x="339" y="287" class="pkt-name">type</text>
<text x="339" y="309" class="pkt-size">1 byte: ORIGIN = 1, AS_PATH = 2 …</text>
<g class="pkt ha"><rect x="508" y="258" width="180" height="64" rx="6"/></g>
<text x="598" y="287" class="pkt-name">length</text>
<text x="598" y="309" class="pkt-size">1 or 2 bytes</text>
<g class="pkt ha2"><rect x="692" y="258" width="292" height="64" rx="6"/></g>
<text x="838" y="287" class="pkt-name">value</text>
<text x="838" y="309" class="pkt-size">as many bytes as it said</text>
<path class="pkt-expand" d="M 979 204 L 979 376"/>
<text x="20" y="368" class="left small pkt-title">one prefix, in NLRI and in withdrawn routes: a bit count, then only the bytes that count needs</text>
<g class="pkt hn"><rect x="20" y="376" width="300" height="64" rx="6"/></g>
<text x="170" y="405" class="pkt-name">length</text>
<text x="170" y="427" class="pkt-size">1 byte: 24 for a /24</text>
<g class="pkt hn"><rect x="324" y="376" width="656" height="64" rx="6"/></g>
<text x="652" y="405" class="pkt-name">prefix</text>
<text x="652" y="427" class="pkt-size">3 bytes for a /24, 6 for a /48 …</text>
</svg>
Notes:
One UPDATE carries one set of attributes, and every prefix that shares them.
The withdrawn and NLRI fields can only hold IPv4; the next slides show where
IPv6 goes. Lengths everywhere: a receiver can walk the message without
understanding any of it, which is what lets unknown attributes pass through.
---
## An example BGP update
<div class="legend"><span class="hh">header</span><span class="hl">lengths</span><span class="ha">path attributes</span><span class="hn">NLRI</span></div>
<pre class="bytes"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
`2a0d:d740::/48`, as AS210036 announces it to the SwissIX route servers.
<!-- .element: class="note" -->
Notes:
Built with the lab daemon's own encoder and checked by parsing it back, with
the attributes pr01 puts on routes it exports to peers. Press down to walk
through it part by part. Note there is nothing yellow: the NLRI field is
empty. Hold that thought.
---
## Header
<pre class="bytes focus"><span class="hh on">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh on">00 59</span> <span class="hh on">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>ff × 16</td><td>Start of message marker.</td></tr><tr><td>00 59</td><td>length of the whole message: 89 bytes (maximum 4096)</td></tr><tr><td>02</td><td>type 2 = UPDATE</td></tr></table>
---
## Two lengths
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl on">00 00</span> <span class="hl on">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>00 00</td><td>0 bytes of withdrawn routes: nothing is being taken back</td></tr><tr><td>00 42</td><td>66 bytes of path attributes follow</td></tr><tr><td></td><td>89 − 19 − 2 − 2 − 66 = 0 bytes left over for NLRI</td></tr></table>
---
## ORIGIN
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha on">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>40</td><td>flags: well-known, transitive</td></tr><tr><td>01</td><td>type 1 = ORIGIN</td></tr><tr><td>01</td><td>1 byte of value</td></tr><tr><td>00</td><td>IGP: the route was originated inside this AS</td></tr></table>
Every attribute is _flags, type, length, value_.
<!-- .element: class="note" -->
---
## AS_PATH
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2 on">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>40 02 06</td><td>well-known, transitive; type 2; 6 bytes</td></tr><tr><td>02</td><td>an AS_SEQUENCE, order matters</td></tr><tr><td>01</td><td>of 1 AS number</td></tr><tr><td>00 03 34 74</td><td>210036, the origin. Four bytes each (RFC 6793)</td></tr></table>
Every BGP router prepends its own AS number before announcing a route to an external peer, creating a map of which networks the announcement travelled through. This allows selecting the shortest path.
<!-- .element: class="note" -->
Notes:
One entry, because SwissIX is one hop from the origin and the route server
does not add itself. Seen from further away it reads e.g. 6939 210036.
---
## MULTI_EXIT_DISC
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha on">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>80 04 04</td><td>optional, non-transitive; type 4; 4 bytes</td></tr><tr><td>00 00 00 00</td><td>MED 0. Lower is preferred, among routes from the same neighbour AS</td></tr></table>
A hint to a neighbour about which path you prefer traffic to come in on. Non-transitive: it goes one hop and no further.
<!-- .element: class="note" -->
---
## MP_REACH_NLRI: announcing paths for non-IPv4 protocols
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2 on">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>80 0e 1c</td><td>optional, non-transitive; type 14; 28 bytes</td></tr><tr><td>00 02 · 01</td><td>address family IPv6, unicast</td></tr><tr><td>10 · 2001 07f8 0024 … 00c9</td><td>next hop, 16 bytes: 2001:7f8:24::c9, our port on the SwissIX peering LAN</td></tr><tr><td>00</td><td>reserved</td></tr><tr><td>30 · 2a 0d d7 40 00 00</td><td>48 bits of prefix: 2a0d:d740::/48</td></tr></table>
Notes:
BGP-4 was built for IPv4: its NLRI field cannot carry anything else. RFC 4760
bolts other address families on as an attribute, each with its own next hop.
A prefix is sent as a bit count plus only as many bytes as the count needs.
The next hop is an address on the exchange's shared LAN: whoever receives this
route sends packets straight to that address across the switch. Remember ::c9
for the exchange diagram in the next section.
Routers may also append their link-local address here, making it 32 bytes.
---
## LARGE_COMMUNITIES
<pre class="bytes focus"><span class="hh">ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff</span> <span class="hh">00 59</span> <span class="hh">02</span> <span class="hl">00 00</span> <span class="hl">00 42</span> <span class="ha">40 01 01 00</span> <span class="ha2">40 02 06 02 01 00 03 34 74</span> <span class="ha">80 04 04 00 00 00 00</span> <span class="ha2">80 0e 1c 00 02 01 10 20 01 07 f8 00 24 00 00 00 00 00 00 00 00 00 c9 00 30 2a 0d d7 40 00 00</span> <span class="ha on">c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02</span></pre>
<table class="decode"><tr><td>c0 20 0c</td><td>optional, transitive; type 32; 12 bytes = one community</td></tr><tr><td>00033474 · 0000000a · 00000002</td><td>210036:10:2, a tag our router puts on everything it exports to peers</td></tr></table>
Three 32-bit numbers. They mean whatever the network named in the first one says they mean.
<!-- .element: class="note" -->
---
## The flags byte
| Bit | Set means | Clear means |
| ------ | ------------------------------------------------- | ------------------------------------------------ |
| `0x80` | optional | well-known: every BGP speaker must understand it |
| `0x40` | transitive: pass it on, even if not understood | drop it at the next hop |
| `0x20` | partial: someone on the way did not understand it | |
| `0x10` | length field is 2 bytes | 1 byte |
Path attribute transitivity allows adding instructions for networks far away from direct neighbours.
<!-- .element: class="note" -->