OVSDB(5)

✨ NAME ✨

OVSDB(5) β€” okay bestie, this is the page for ovsdb, aka Open vSwitch Database (File Formats). Ngl, it's the file-format manual, and we're getting into it. πŸ’–

🌈 DESCRIPTION 🌈

So OVSDB, the Open vSwitch Database, is a database system whose network protocol is specified by RFC 7047. The RFC does not specify an on-disk storage format. The OVSDB implementation in Open vSwitch implements two storage formats: one for standalone (and active-backup) databases, and the other for clustered databases. This manpage documents both of these formats. No cap.

Most users do not need to be concerned with this specification. Instead, to manipulate OVSDB files, refer to ovsdb-tool(1). For an introduction to OVSDB as a whole, read ovsdb(7). That's your vibe check.

OVSDB files explicitly record changes that are implied by the database schema. Example time: the OVSDB β€œgarbage collection” feature means that when a client removes the last reference to a garbage-collected row, the database server automatically removes that row. The database file explicitly records the deletion of the garbage-collected row, so that the reader does not need to infer it. It's giving receipts, not vibes. 🧾

OVSDB files do not include the values of ephemeral columns. Iykyk.

Standalone and clustered database files share the common structure described here. They are text files encoded in UTF-8 with LF (U+000A) line ends, organized as append-only series of records. Each record consists of 2 lines of text.

The first line in each record has the format OVSDB <magic> <length> <hash>, where <magic> is JSON for standalone databases or CLUSTER for clustered databases, <length> is a positive decimal integer, and <hash> is a SHA-1 checksum expressed as 40 hexadecimal digits. Words in the first line must be separated by exactly one space. Periodt.

The second line must be exactly length bytes long (including the LF) and its SHA-1 checksum (including the LF) must match hash exactly. The line’s contents must be a valid JSON object as specified by RFC 4627. Strings in the JSON object must be valid UTF-8. To ensure that the second line is exactly one line of text, the OVSDB implementation expresses any LF characters within a JSON string as \n. For the same reason, and to save space, the OVSDB implementation does not β€œpretty print” the JSON object with spaces and LFs. (The OVSDB implementation tolerates LFs when reading an OVSDB database file, as long as length and hash are correct.) This checksum requirement ate, fr fr. πŸ’…

πŸŽ€ JSON Notation πŸŽ€

We use notation from RFC 7047 here to describe the JSON data in records. In addition to the notation defined there, we add the following:

  • <raw-uuid> β€” A 36-character JSON string that contains a UUID in the format described by RFC 4122, e.g. "550e8400-e29b-41d4-a716-446655440000". Iconic UUID behavior, honestly.

πŸ“ Standalone Format πŸ“

The first record in a standalone database contains the JSON schema for the database, as specified in RFC 7047. Only this record is mandatory (a standalone file that contains only a schema represents an empty database). Main character record.

The second and subsequent records in a standalone database are transaction records. Each record may have the following optional special members, which do not have any semantics but are often useful to administrators looking through a database log with ovsdb-tool show-log:

  • "_date": <integer> β€” The time at which the transaction was committed, as an integer number of milliseconds since the Unix epoch. Early versions of OVSDB counted seconds instead of milliseconds; these can be detected by noticing that their values are less than 2**32.

OVSDB always writes a _date member.

  • "_comment": <string> β€” A JSON string that specifies the comment provided in a transaction comment operation. If a transaction has multiple comment operations, OVSDB concatenates them into a single _comment member, separated by a new-line.

OVSDB only writes a _comment member if it would be a nonempty string.

Each of these records also has one or more additional members, each of which maps from the name of a database table to a <table-txn>:

  • <table-txn> β€” A JSON object that describes the effects of a transaction on a database table. Its names are <raw-uuid>s for rows in the table and its values are <row-txn>s.
  • <row-txn> β€” Either null, which indicates that the transaction deleted this row, or a JSON object that describes how the transaction inserted or modified the row, whose names are the names of columns and whose values are <value>s that give the column’s new value.

For new rows, the OVSDB implementation omits columns whose values have the default values for their types defined in RFC 7047 section 5.2.1; for modified rows, the OVSDB implementation omits columns whose values are unchanged.

πŸ¦‹ Clustered Format πŸ¦‹

The clustered format has the following additional notation:

  • <uint64> β€” A JSON integer that represents a 64-bit unsigned integer. The OVS JSON implementation only supports integers in the range -2**63 through 2**63-1, so 64-bit unsigned integer values from 2**63 through 2**64-1 are expressed as negative numbers.
  • <address> β€” A JSON string that represents a network address to support clustering, in the <protocol>:<ip>:<port> syntax described in ovsdb-tool(1).
  • <servers> β€” A JSON object whose names are <raw-uuid>s that identify servers and whose values are <address>es that specify those servers’ addresses.
  • <cluster-txn> β€” A JSON array with two elements:
    1. The first element is either a <database-schema> or null. A <database-schema> element is always present in the first record of a clustered database to indicate the database’s initial schema. If it is not null in a later record, it indicates a change of schema for the database.
    2. The second element is either a transaction record in the format described under Standalone Format above, or null.

When a schema is present, the transaction record is relative to an empty database. That is, a schema change effectively resets the database to empty and the transaction record represents the full database contents. This allows readers to be ignorant of the full semantics of schema change. Lowkey genius.

The first record in a clustered database contains the following members, all of which are required, except prev_election_timer:

  • "server_id": <raw-uuid> β€” The server’s own UUID, which must be unique within the cluster.
  • "local_address": <address> β€” The address on which the server listens for connections from other servers in the cluster.
  • "name": <id> β€” The database schema name. It is only important when a server is in the process of joining a cluster: a server will only join a cluster if the name matches. (If the database schema name were unique, then we would not also need a cluster ID.)
  • "cluster_id": <raw-uuid> β€” The cluster’s UUID. The all-zeros UUID is not a valid cluster ID.
  • "prev_term": <uint64> and "prev_index": <uint64> β€” The Raft term and index just before the beginning of the log.
  • "prev_servers": <servers> β€” The set of one or more servers in the cluster at index β€œprev_index” and term β€œprev_term”. It might not include this server, if it was not the initial server in the cluster.
  • "prev_election_timer": <uint64> β€” The election base time before the beginning of the log. If it does not exist, the default value 1000 ms is used as if it exists in this record.
  • "prev_data": <json-value> and "prev_eid": <raw-uuid> β€” A snapshot of the data in the database at index β€œprev_index” and term β€œprev_term”, and the entry ID for that data. The snapshot must contain a schema.

The second and subsequent records, if present, in a clustered database represent changes to the database, to the cluster state, or both. There are several types of these records. The most important types of records directly represent persistent state described in the Raft specification:

  • Entry β€” A Raft log entry.
  • Term β€” The start of a new term.
  • Vote β€” The server’s vote for a leader in the current term.

The following additional types of records aid debugging and troubleshooting, but they do not affect correctness.

  • Leader β€” Identifies a newly elected leader for the current term.
  • Commit Index β€” An update to the server’s commit_index.
  • Note β€” A human-readable description of some event.

So real talk β€” the table below is THE cheat sheet for which members live in which record type. Legend time, bestie: yes = required, ? = optional, blank = straight-up forbidden (do not pass go), and [1] = data and eid must be either both present or both absent, no mix-and-match. πŸ’…

Since tables are so not it in a terminal, here's the same tea, member by member:

  • comment β€” ? in Entry, ? in Term, ? in Vote, ? in Leader, ? in Commit Index, ? in Note. Optional everywhere, the social butterfly of members. πŸ¦‹
  • term β€” yes in Entry, yes in Term, yes in Vote, yes in Leader, blank in Commit Index, blank in Note.
  • index β€” yes in Entry, blank in Term, blank in Vote, blank in Leader, blank in Commit Index, blank in Note.
  • servers β€” ? in Entry, blank everywhere else.
  • election_timer β€” ? in Entry, blank everywhere else.
  • data β€” [1] in Entry, blank everywhere else.
  • eid β€” [1] in Entry, blank everywhere else.
  • vote β€” blank in Entry, blank in Term, yes in Vote, blank in Leader, blank in Commit Index, blank in Note.
  • leader β€” blank in Entry, blank in Term, blank in Vote, yes in Leader, blank in Commit Index, blank in Note.
  • commit_index β€” blank in Entry, blank in Term, blank in Vote, blank in Leader, yes in Commit Index, blank in Note.
  • note β€” blank in Entry, blank in Term, blank in Vote, blank in Leader, blank in Commit Index, yes in Note.

Here's what each member actually is, no cap:

  • "comment": <string> β€” a human-readable string so an admin can figure out why a record got emitted. It's giving "notes app apology", but make it operational. πŸ“
  • "term": <uint64> β€” the term during which the activity happened.
  • "index": <uint64> β€” the index of a log entry.
  • "servers": <servers> β€” server configuration in a log entry.
  • "election_timer": <uint64> β€” leader election timeout base value in a log entry.
  • "data": <json-value> β€” the data in a log entry.
  • "eid": <raw-uuid> β€” entry ID in a log entry.
  • "vote": <raw-uuid> β€” the server ID that this server voted for.
  • "leader": <raw-uuid> β€” the server ID of the server. Emitted by both leaders and followers when a leader is elected. Everyone gets an invite to this announcement, bestie. πŸ‘‘
  • "commit_index": <uint64> β€” the updated commit_index value.
  • "note": <string> β€” one of a few special strings flagging important events. The currently defined strings are:
    • "transfer leadership" β€” this server transferred leadership to a different server (with the deets tucked into comment).
    • "left" β€” this server finished leaving the cluster. Lowkey a big deal: this lets subsequent readers know the server is not part of the cluster and they should not attempt to connect to it. πŸ™ˆ

Joining a Cluster 🫢

Okay so beyond the general format for a clustered database, there's one special case you gotta know about: a database file created by ovsdb-tool join-cluster. That file contains exactly one record, and that record carries the info that got passed to the join-cluster command. It has these members:

  • "server_id": <raw-uuid> and "local_address": <address> and "name": <id> β€” same semantics as described above in the general description of the format. Same vibes, different context.
  • "cluster_id": <raw-uuid> β€” provided only if the user gave the --cid option to join-cluster. Same semantics as described above.
  • "remote_addresses"; [<address>*] β€” one or more remote servers to contact for joining the cluster.
Heads up: when the server successfully joins the cluster, that database file gets replaced by one described in Clustered Format. So the glow-up is real β€” the file you started with is not the file you end up with. ✨

AUTHOR πŸ’œ

The Open vSwitch Development Community

2016-2024, The Open vSwitch Development Community


And that's the whole page, bestie β€” you ate. πŸ“ This one's OVSDB(5), version 3.6, dated Feb 13, 2026, and it's a wrap, periodt. πŸ’…βœ¨

πŸ“¦ where this page comes from