- Removed every fragment and stepped code highlight: a slide now shows everything at once. Two code blocks keep a static highlight on one line. - Dropped "What stands between you and an outage". - The UPDATE walked through in section 3 is now 2a0d:d740::/48 as AS210036 announces it to the SwissIX route servers: next hop 2001:7f8:24::c9 (pr01's port on the peering LAN), AS path 210036, MED 0 and 210036:10:2, matching what pr01's export filter puts on routes to peers. Encoded with the packet crate and parsed back to the identical message; the slide generator asserted every quoted number, including the next hop, against the bytes. Adds a MULTI_EXIT_DISC slide to the walkthrough. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
9.8 KiB
BGP, down to the bytes
Notes: Section 3. The aim: by the end, the bytes view on the lab page reads like text.
BGP in one slide
- Runs over TCP, port
179, between neighbours you configure by hand - Each side tells the other its best route per prefix
- Only changes are sent: no periodic refresh
- If the session drops, every route learned over it is gone
Notes: No discovery, no authentication of content, no notion of truth. A neighbour says "I can reach X" and you believe it, subject to your filters.
Four kinds of message
| Type | Name | Says |
|---|---|---|
| 1 | OPEN | who I am: AS number, router ID, capabilities |
| 2 | UPDATE | these prefixes are reachable, those no longer are |
| 3 | NOTIFICATION | something is wrong, I am closing the session |
| 4 | KEEPALIVE | still here |
OPEN, OPEN, KEEPALIVE, KEEPALIVE, and then it is all UPDATEs.
Notes: There is a fifth, ROUTE-REFRESH: "send me everything again, my policy changed".
The shape of an UPDATE
| Bytes | Field |
|---|---|
| 19 | header: marker, length, type |
| 2 + n | withdrawn routes: prefixes that are no longer reachable |
| 2 + n | path attributes: everything about the route |
| the rest | NLRI: the IPv4 prefixes being announced |
One UPDATE carries one set of attributes, and every prefix that shares them.
A real one: 89 bytes
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
2a0d:d740::/48, as AS210036 announces it to the SwissIX route servers.
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
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| ff × 16 | marker. Once carried authentication, now just filler to find message boundaries |
| 00 59 | length of the whole message: 89 bytes (maximum 4096) |
| 02 | type 2 = UPDATE |
Two lengths
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| 00 00 | 0 bytes of withdrawn routes: nothing is being taken back |
| 00 42 | 66 bytes of path attributes follow |
| 89 − 19 − 2 − 2 − 66 = 0 bytes left over for NLRI |
ORIGIN
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| 40 | flags: well-known, transitive |
| 01 | type 1 = ORIGIN |
| 01 | 1 byte of value |
| 00 | IGP: the route was originated inside this AS |
Every attribute is flags, type, length, value.
AS_PATH
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| 40 02 06 | well-known, transitive; type 2; 6 bytes |
| 02 | an AS_SEQUENCE, order matters |
| 01 | of 1 AS number |
| 00 03 34 74 | 210036, the origin. Four bytes each (RFC 6793) |
Each network prepends itself on the way out. The length of this list is what best-path selection compares.
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
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| 80 04 04 | optional, non-transitive; type 4; 4 bytes |
| 00 00 00 00 | MED 0. Lower is preferred, among routes from the same neighbour AS |
A hint to a neighbour about which of your entrances to use. Non-transitive: it goes one hop and no further.
MP_REACH_NLRI: where IPv6 lives
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| 80 0e 1c | optional, non-transitive; type 14; 28 bytes |
| 00 02 · 01 | address family IPv6, unicast |
| 10 · 2001 07f8 0024 … 00c9 | next hop, 16 bytes: 2001:7f8:24::c9, our port on the SwissIX peering LAN |
| 00 | reserved |
| 30 · 2a 0d d7 40 00 00 | 48 bits of prefix: 2a0d:d740::/48 |
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
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 59 02 00 00 00 42 40 01 01 00 40 02 06 02 01 00 03 34 74 80 04 04 00 00 00 00 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 c0 20 0c 00 03 34 74 00 00 00 0a 00 00 00 02
| c0 20 0c | optional, transitive; type 32; 12 bytes = one community |
| 00033474 · 0000000a · 00000002 | 210036:10:2, a tag our router puts on everything it exports to peers |
Three 32-bit numbers. They mean whatever the network named in the first one says they mean.
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 |
Transitive is why a community you set can act three networks away.