Zebra

Overview of the Zebra Protocol

The Zebra protocol (or ZAPI) is used by protocol daemons to communicate with the zebra daemon.

Each protocol daemon may request and send information to and from the zebra daemon such as interface states, routing state, nexthop-validation, and so on. Protocol daemons may also install routes with zebra. The zebra daemon manages which routes are installed into the forwarding table with the kernel. Some daemons use more than one ZAPI connection. This is supported: each ZAPI session is identified by a tuple of: {protocol, instance, session_id}. LDPD is an example: it uses a second, synchronous ZAPI session to manage label blocks. The default value for session_id is zero; daemons who use multiple ZAPI sessions must assign unique values to the sessions’ ids.

The Zebra protocol is a streaming protocol, with a common header. Version 0 lacks a version field and is implicitly versioned. Version 1 and all subsequent versions have a version field. Version 0 can be distinguished from all other versions by examining the 3rd byte of the header, which contains a marker value of 255 (in Quagga) or 254 (in FRR) for all versions except version 0. The marker byte corresponds to the command field in version 0, and the marker value is a reserved command in version 0.

Version History

  • Version 0

    Used by all versions of GNU Zebra and all version of Quagga up to and including Quagga 0.98. This version has no version field, and so is implicitly versioned as version 0.

  • Version 1

    Added marker and version fields, increased command field to 16 bits. Used by Quagga versions 0.99.3 through 0.99.20.

  • Version 2

    Used by Quagga versions 0.99.21 through 0.99.23.

  • Version 3

    Added vrf_id field. Used by Quagga versions 0.99.23 until FRR fork.

  • Version 4

    Change marker value to 254 to prevent people mixing and matching Quagga and FRR daemon binaries. Used by FRR versions 2.0 through 3.0.3.

  • Version 5

    Increased VRF identifier field from 16 to 32 bits. Used by FRR versions 4.0 through 5.0.1.

  • Version 6

    Removed the following commands:

    • ZEBRA_IPV4_ROUTE_ADD

    • ZEBRA_IPV4_ROUTE_DELETE

    • ZEBRA_IPV6_ROUTE_ADD

    • ZEBRA_IPV6_ROUTE_DELETE

    Used since FRR version 6.0.

Zebra Protocol Definition

Zebra Protocol Header Field Definitions

Length

Total packet length including this header.

Marker

Static marker. The marker value, when it exists, is 255 in all versions of Quagga. It is 254 in all versions of FRR. This is to allow version 0 headers (which do not include version explicitly) to be distinguished from versioned headers.

Version

Zebra protocol version number. Clients should not continue processing messages past the version field for versions they do not recognise.

Command

The Zebra protocol command.

Current Version

Version 5, 6

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Length            |     Marker    |    Version    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             VRF ID                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Command            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Past Versions

Version 0

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Length            |    Command    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Version 1, 2

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Length            |     Marker    |    Version    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Command            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Version 3, 4

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Length            |     Marker    |    Version    |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             VRF ID            |            Command            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Zebra Protocol Commands

The definitions of zebra protocol commands can be found at lib/zclient.h.

Dataplane batching

Dataplane batching is an optimization feature that reduces the processing time involved in the user space to kernel space transition for every message we want to send.

Design

With our dataplane abstraction, we create a queue of dataplane context objects for the messages we want to send to the kernel. In a separate pthread, we loop over this queue and send the context objects to the appropriate dataplane. A batching enhancement tightly integrates with the dataplane context objects so they are able to be batch sent to dataplanes that support it.

There is one main change in the dataplane code. It does not call kernel-dependent functions one-by-one, but instead it hands a list of work down to the kernel level for processing.