PERFDHCP(8)

โœจ perfdhcp โ€” the DHCP benchmarking tool, but make it a group chat โœจ

okay so bestie, you found the perfdhcp(8) page from the Kea manual and honestly? it's a whole vibe. it's section 8, it's a benchmarking tool, and it's about to make you the main character of network performance testing. let's get into it ๐Ÿ’…


๐Ÿ’– NAME ๐Ÿ’–

perfdhcp โ€” the DHCP benchmarking tool. that's it, that's the name, slay ๐ŸŽ€


๐ŸŒธ SYNOPSIS ๐ŸŒธ

no cap, this synopsis is long, but every single flag matters so here it is, character for character:

perfdhcp [-1] [-4 | -6] [-A encapsulation-level] [-b base] [-B] [-c] [-C
separator] [-d drop-time] [-D max-drop] [-e lease-type] [-E time-offset]
[-f renew-rate] [-F release-rate] [-g thread-mode] [-h] [-i] [-I
ip-offset] [-J remote-address-list-file] [-l local-address|interface]
[-L local-port] [-M mac-list-file] [-n num-request] [-N remote-port] [-O
random-offset] [-o code,hexstring] [--or
encapsulation-level:code,hexstring] [-p test-period] [-P preload] [-r
rate] [-R num-clients] [-s seed] [-S srvid-offset] [--scenario name] [-t
report] [-T template-file] [-u] [-v] [-W exit-wait-time] [-w
script_name] [-x diagnostic-selector] [-X xid-offset] [server]

and yes there's a trailing [server] โ€” you can name the server, it's optional, we love a low-pressure invite ๐Ÿซถ


๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

so perfdhcp is a DHCP benchmarking tool. what does that even mean? it means it lets you measure how well a DHCP server performs by generating large amounts of traffic from multiple simulated clients. it's literally a fake client army. it can test both IPv4 and IPv6 servers, and it gives you stats about response times and the number of requests that get dropped. the receipts are built in, periodt ๐Ÿ’…

the tool supports two different scenarios, each offering certain behaviors to be tested. by default โ€” that's the basic scenario โ€” tests run using the full four-packet exchange sequence: DORA for DHCPv4, SARR for DHCPv6 ๐ŸŒˆ. and there's an option that lets you run tests using the initial two-packet exchange (DO and SA) instead, if you're feeling minimal. you can also configure perfdhcp to send DHCPv6 RENEW and RELEASE messages at a specified rate, in parallel with the DHCPv6 four-way exchanges โ€” multitasking queen ๐Ÿ‘‘. and by default, if there is no response received within one second, that response is considered lost and perfdhcp just moves on to other transactions. it does not wait around for anyone, and honestly, respect ๐Ÿ™ˆ

there's a second scenario, and it's called avalanche, selected via --scenario avalanche. the way it works: it first sends the number of Discovery or Solicit messages specified by the -R option, then a retransmission (with an exponential back-off mechanism) is used for each simulated client, until all requests are answered. it generates a report when all clients receive their addresses, or when it is manually stopped. this scenario is trying to replicate the case where the server is not able to handle the traffic swiftly enough โ€” because real clients will assume the packet or response was lost and will retransmit, which further increases DHCP traffic. it's a whole feedback loop, sometimes called an avalanche effect, hence the scenario name. iconic naming tbh ๐ŸŽ€

heads up bestie: option -p is ignored in the avalanche scenario. don't fight it, it's just how she is ๐Ÿ’€

when running a performance test, perfdhcp exchanges packets with the server under test as quickly as possible โ€” unless the -r parameter is used to limit the request rate. the length of the test can be limited by setting a threshold on any or all of these three things: the number of requests made by perfdhcp, the elapsed time, or the number of requests dropped by the server. three levers, one queen ๐Ÿซถ


๐ŸŽ€ TEMPLATES ๐ŸŽ€

so to allow the contents of packets sent to the server to be customized, perfdhcp lets you specify template files that determine the contents of the packets. for example, the customized packet may contain a DHCPv6 ORO to request a set of options to be returned by the server, or it may contain the Client FQDN option to request that the server perform DNS updates. this is lowkey the move for discovering performance bottlenecks across different server configurations (e.g. DDNS enabled or disabled) โ€” vibe check your server setups ๐Ÿ’…

up to two template files can be specified on the command line, with each file representing the contents of a particular type of packet, and the type being determined by the test being carried out. for example, if testing DHCPv6:

  • with no template files specified on the command line, perfdhcp generates both Solicit and Request packets.
  • with one template file specified, that file is used as the pattern for Solicit packets: perfdhcp generates the Request packets.
  • with two template files given on the command line, the first is used as the pattern for Solicit packets, and the second as the pattern for Request packets.

(a similar determination applies to DHCPv4's DHCPDISCOVER and DHCPREQUEST packets.) see, consistent queen behavior across both protocols โœจ

the template file holds the DHCP packet, represented as a stream of ASCII hexadecimal digits; it excludes any IP/UDP stack headers. and the file must not contain any characters other than hexadecimal digits and spaces. spaces are discarded when the template file is parsed โ€” so in the file, 12B4 is the same as 12 B4, which is the same as 1 2 B 4. spaces are decorative, the hex is the moment ๐Ÿ’œ

the template files should be used in conjunction with the command-line parameters which specify offsets of the data fields being modified in outbound packets. for example, the -E time-offset switch specifies the offset of the DHCPv6 Elapsed Time option in the packet template. if the offset is specified, perfdhcp injects the current elapsed-time value into this field before sending the packet to the server. it's giving โœจprecisionโœจ

in many scenarios, perfdhcp needs to simulate multiple clients, each having a unique client identifier. and since packets for each client are generated from the same template file, it's necessary to randomize the client identifier (or HW address in DHCPv4) in the packet created from it. the -O random-offset option lets you specify the offset in the template where randomization should be performed. and here's the important part bestie, do not skip this:

it's important to note that this offset points to the end (not the beginning) of the client identifier (or HW address field). ๐Ÿ™ˆ

the number of bytes being randomized depends on the number of simulated clients:

  • if the number of simulated clients is between 1 and 255, only one byte (the one the randomization offset points to) is randomized.
  • if the number of simulated clients is between 256 and 65535, two bytes are randomized. note that the last two bytes of the client identifier are randomized in this case: the byte which the randomization offset parameter points to, and the one which precedes it (random-offset - 1).
  • if the number of simulated clients exceeds 65535, three bytes are randomized, and so on.

perfdhcp can also simulate traffic from multiple subnets by enabling option -J and passing a path to a file that contains v4 or v6 addresses to be used as relays in generated messages. that enables testing of vast numbers of Kea shared networks ๐ŸŒˆ. while testing DHCPv4, Kea should be started with the KEA_TEST_SEND_RESPONSES_TO_SOURCE environment variable, to force Kea to send generated messages to the source address of the incoming packet. write that one down, iykyk ๐Ÿซถ

and one lil caveat to close this section: templates may currently be used to generate packets being sent to the server in 4-way exchanges, i.e. Solicit, Request (DHCPv6) and DHCPDISCOVER, DHCPREQUEST (DHCPv4). they cannot be used when Renew or DHCPRELEASE packets are being sent. that's just the rules, no cap ๐Ÿ’€


โœจ OPTIONS โœจ

okay bestie, buckle up, because this is where the flags live and there are so many of them ๐Ÿ’… you're gonna eat this list up, i promise. every single one, no skipping, fr fr.

  • -1 โ€” grabs the server-id option straight out of the first message you receive. like, first one in, that's the one we trust ๐Ÿซถ
  • -4 โ€” turns on DHCPv4 mode, and ngl this one is the default. it is incompatible with -6, so don't even try to run them together ๐Ÿ™…โ€โ™€๏ธ
  • -6 โ€” turns on DHCPv6 mode. also incompatible with -4. pick a lane, bestie โœจ
  • -b basetype=value โ€” this sets the base MAC or DUID used to simulate all your different clients. the basetype can be mac or duid (and btw the keyword ether is also allowed as a stand-in for MAC ๐Ÿ‘€). you can stack -b multiple times, so go off. the MAC address has to be six octets separated by single (:) or double (::) colons, like: mac=00:0c:01:02:03:04. the DUID value is a hexadecimal string, and it must be at least six octets long, not longer than 64 bytes, and the length has to be less than 128 hexadecimal digits. for example: duid=0101010101010101010110111F14. got it? iconic ๐Ÿ’–
  • -d drop-time โ€” the amount of time after which a request is treated as lost. value is in seconds and may have a fractional component, so yes you can be precise about it. the default is 1.
  • -e lease-type โ€” tells the server what kind of lease you're asking for. it's giving picky (respectfully). it can be one of these:
    • address-only โ€” only regular addresses (v4 or v6) get requested. simple, clean.
    • prefix-only โ€” only IPv6 prefixes get requested.
    • address-and-prefix โ€” both IPv6 addresses and prefixes get requested. greedy in a cute way.

heads up: the -e prefix-only and -e address-and-prefix forms may not be used with the -4 option. v4 doesn't do prefixes, babes ๐Ÿ˜ญ

  • -F release-rate โ€” sets the rate at which DHCPv4 DHCPRELEASE or DHCPv6 Release requests get sent to a server. this value is only valid when you're also using the exchange rate (that's -r rate). and listen: the sum of this value plus the renew-rate (-f rate) must be equal to or less than the exchange rate. math is math ๐Ÿงฎ
  • -f renew-rate โ€” sets the rate at which DHCPv4 DHCPREQUEST or DHCPv6 Renew requests get sent. same deal: only valid alongside the exchange rate (-r rate), and the sum of this plus the release-rate (-F rate) must be equal to or less than the exchange rate. periodt.
  • -g thread-mode โ€” lets you pick the thread mode, which is either single or multi. in multi-thread mode, packets get received in a separate thread, which uses your CPUs way better ๐Ÿ”ฅ. but on a single-CPU system, it's better to run in one thread so the threads don't block each other. if your system has more than one CPU, multi-thread is the default; otherwise single-thread is the default. no cap.
  • -h โ€” prints help and exits. the "just tell me what to do" button ๐Ÿซถ
  • -i โ€” only does the initial part of the exchange: DISCOVER-OFFER if -4 is selected, Solicit-Advertise if -6 is chosen.
okay so -i is picky too: it is incompatible with the following options: -1, -d, -D, -E, -S, -I and -F. on top of that, it cannot be used with multiple instances of -O, -T, and -X. don't fight it ๐Ÿ’…
  • -J remote-address-list-file โ€” points to a text file with a bunch of addresses in it, and it's designed to test shared networks. if you give it one, perfdhcp randomly picks one of those addresses for every exchange, generating traffic from multiple subnets ๐ŸŒˆ. when you're testing DHCPv4, you should start it with the KEA_TEST_SEND_RESPONSES_TO_SOURCE=ENABLE environment variable โ€” otherwise perfdhcp literally won't be able to receive responses. it's giving ghosted ๐Ÿ’€
  • -l local-addr|interface โ€” for DHCPv4 operation, this specifies the local hostname/address to use when talking to the server. by default, the interface address that traffic would normally be routed through to reach the server gets used. for DHCPv6 operation, it specifies the name of the network interface through which exchanges are initiated. different vibe per protocol, iykyk.
  • -L local-port โ€” the local port to use. must be zero or a positive integer up to 65535. a value of 0 (the default) lets perfdhcp pick its own port. main character energy, it chooses for itself โœจ
  • -M mac-list-file โ€” a text file with a list of MAC addresses, one per line. if you give it one, a MAC address gets chosen randomly from the list for every new exchange ๐ŸŽฒ. in DHCPv6, those MAC addresses are used to generate DUID-LLs. and bestie, this parameter must not be used together with the -b parameter. they do not coexist ๐Ÿ™…โ€โ™€๏ธ
  • -N remote-port โ€” the remote port to use. must be zero or a positive integer up to 65535. a value of 0 (the default) lets perfdhcp choose the standard service port.
  • -o code,hexstring โ€” forces perfdhcp to insert the extra option (or options, if you use it multiple times) you specify into the packets being transmitted. the code is the option code, and the hexstring is a hexadecimal string that defines the content of the option. โš ๏ธ careful though, because perfdhcp offers no logic behind these options โ€” they just get inserted into packets and sent exactly as-is. and don't be out here duplicating options that are already inserted, that's messy. for example, to insert the client-class identifier (option code 60) with the string "docsis", you'd use -o 60,646f63736973. -o may be used multiple times. and psst: the protocol family (-4 or -6) must be specified before using -o.
  • -P preload โ€” kicks off preload exchanges back-to-back at startup. must be 0 (the default) or a positive integer.
  • -r rate โ€” sets the rate of DORA/SARR exchanges per second (or, if -i is given, DO/SA). a periodic report gets generated showing how many exchanges were not completed, plus the average response latency ๐Ÿ“Š. the program keeps going until you interrupt it, and at that point a final report is generated. it's giving "i could do this all day" ๐Ÿ’…
  • -R num-clients โ€” how many different clients to use. with a value of 1 (the default), all requests appear to come from the same client. must be a positive number. clone army vibes when you raise it ๐Ÿ‘‘
  • -s seed โ€” the seed for randomization, which makes runs of perfdhcp repeatable. must be 0 or a positive integer. the value 0 means a seed is not used, and that's the default.
  • --scenario name โ€” the type of scenario, which can be basic (the default) or avalanche. yes, avalanche, as dramatic as it sounds ๐ŸŒจ๏ธ
  • -T template-file โ€” a file containing the template to use, as a stream of hexadecimal digits. this may be specified up to two times, and it controls the contents of the packets sent (go read the "Templates" section above, bestie ๐Ÿ“–).
  • -u โ€” enables checks for address uniqueness. heads up: the lease valid-lifetime should not be shorter than the test duration, and clients should not request an address more than once without releasing it. be responsible with this one ๐Ÿ™
  • -v โ€” displays the Kea version. quick lil flex.
  • -V โ€” displays the extended Kea version. extra details, extra slay ๐Ÿ’…
  • -W exit-wait-time โ€” the exit-wait-time parameter, which makes perfdhcp wait a certain amount of time after an exit condition has been met, so it can receive all the packets without sending any new ones. expressed in microseconds. if you don't specify it, 0 is used โ€” meaning it exits immediately after the exit conditions are met. bye bestie ๐Ÿ‘‹
  • -w script_name โ€” the name of the script to run before/after perfdhcp. when it's called, the script gets passed a single parameter, either "start" or "stop", telling it whether it's running before or after perfdhcp. cute lil handoff ๐ŸŽ€
  • -x diagnostic-selector โ€” includes extended diagnostics in the output. it's a string of single keywords specifying which operations you want verbose output for. the selector key letters are:
    • a โ€” prints the decoded command-line arguments.
    • e โ€” prints the exit reason.
    • i โ€” prints the rate-processing details.
    • l โ€” prints the received leases.
    • s โ€” prints the first server ID.
    • t โ€” when finished, prints timers of all successful exchanges.
    • T โ€” when finished, prints templates.
  • -Y seconds โ€” the time in seconds after which perfdhcp starts simulating the client waiting longer for server responses. this increases the secs field in DHCPv4 and sends increased values in the Elapsed Time option in DHCPv6. must be used with -y. they're a package deal ๐Ÿซ‚
  • -y seconds โ€” the time in seconds during which perfdhcp simulates the client waiting longer for server responses. this increases the secs field in DHCPv4 and sends increased values in the Elapsed Time option in DHCPv6. must be used with -Y. same package, other half ๐Ÿ’–

๐Ÿ’– DHCPV4-ONLY OPTIONS ๐Ÿ’–

the following options only apply for DHCPv4 (i.e. when -4 is given). v4 girlies, this section is for you.

  • -B โ€” forces broadcast handling. loud and proud, no cap ๐Ÿ“ข

๐ŸŒธ DHCPV6-ONLY OPTIONS ๐ŸŒธ

the following options only apply for DHCPv6 (i.e. when -6 is given). v6 besties, come get your food.

  • -c โ€” adds a rapid-commit option (and the exchanges are Solicit-Advertise). fast and efficient, we love her โšก
  • -A encapsulation-level โ€” says that relayed traffic must be generated. the argument specifies the level of encapsulation, i.e. how many relay agents are being simulated. currently the only supported encapsulation-level value is 1, which means the generated traffic is equivalent to the amount of traffic passing through a single relay agent. one relay, one vibe ๐Ÿฆ‹
  • --or encapsulation-level:code,hexstring โ€” forces perfdhcp to insert the extra option (or options, if used multiple times) you specify into a relayed DHCPv6 message at the given level of encapsulation; currently the only supported encapsulation-level value is 1. this one is very similar to -o: the code is the option code, and the hexstring is a hexadecimal string defining the option's content. โš ๏ธ again, careful, because perfdhcp has no logic behind the options โ€” they're simply inserted into packets and sent as-is. encapsulation-level: is optional; if you leave it out, the default encapsulation-level value 1 gets used. for example, to insert the Subscriber identifier (option code 38) with a value 1234 at the first level of encapsulation, use --or 38,31323334 or --or 1:38,31323334. --or may be used multiple times, and it must be used in conjunction with -A. no -A, no --or, that's the rule ๐Ÿ’…

Okay bestie, these ones are the template glow-up squad โ€” they only work alongside -T, and they decide how perfdhcp remixes your template. And the way that you can pass them more than once on the command line? Each occurrence pokes the corresponding template file (peep the "Templates" section above, iykyk). ๐Ÿ’…

  • -E time-offset โ€” Sets the offset of the secs field (DHCPv4) or the Elapsed Time option (DHCPv6) inside the second template, aka the Request one. Gotta be 0 or a positive integer, and 0 just turns the whole thing off. ๐Ÿ™ˆ
  • -I ip-offset โ€” Sets the offset of the IP address (DHCPv4, in the requested-ip option) or the IA_NA option (DHCPv6), inside that same second (Request) template. ๐Ÿ“
  • -O random-offset โ€” Sets the offset of the last octet to randomize in the template. Has to be an integer greater than 3, and fr fr you must also pass the -T switch to use this one. ๐ŸŽฒ
  • -S srvid-offset โ€” Sets the offset of the server-id option in the second (Request) template. Must be a positive integer, and this switch only works when the template option (-T) is also given. ๐Ÿ†”
  • -X xid-offset โ€” Sets the offset of the transaction ID (xid) in the template. Positive integer only, and again: this switch can only be used when the template option (-T) is also given. ๐ŸŽ€

๐Ÿงช OPTIONS CONTROLLING A TEST ๐Ÿงช

These are the ones that actually drive the chaos. ๐Ÿ’ฅ

  • -D max-drop โ€” Aborts the test immediately if max-drop requests have been dropped. Want it to bail on even a single drop? -D 1, iconic. max-drop must be a positive integer. But if max-drop has the % suffix, it means the max percentage of requests that may be dropped before aborting โ€” and in that case, testing of the threshold doesn't even start until 10 requests are expected to have been received. Math queen behavior. ๐Ÿ‘‘
  • -n num-requests โ€” Kicks off num-request transactions. No report until all the transactions have been initiated/waited-for, and then you get your report and the program peaces out. ๐Ÿ“Š
  • -p test-period โ€” Sends requests for test-period, specified the exact same way as -d. This can be an alternative to -n, or you can give both โ€” in which case the testing wraps up as soon as either limit is hit. Two limits, one finish line. ๐Ÿ
  • -t interval โ€” Sets the delay, in seconds, between two successive reports. โฑ๏ธ
  • -C separator โ€” Suppresses the preliminary output and makes the interim data contain only the values delimited by separator. Use it with -t to produce super easily parsable reports at -t intervals. Parser girlies, this one's for you. ๐Ÿซถ

๐Ÿ“ฅ ARGUMENTS ๐Ÿ“ฅ

  • server โ€” The server to test, given as an IP address. For the DHCPv6 case, the special name all can be used to refer to All_DHCP_Relay_Agents_and_Servers (the multicast address FF02::1:2), or the special name servers to refer to All_DHCP_Servers (the multicast address FF05::1:3). The server is mandatory โ€” unless you gave -l to specify an interface, in which case it just defaults to all. ๐ŸŒ

๐Ÿ’€ ERRORS ๐Ÿ’€

perfdhcp can report these lil' errors during the packet exchange, and honestly? Not the vibe.

  • tooshort โ€” A message was received that was too short. smol. ๐Ÿ“
  • orphans โ€” A message was received that doesn't match one sent to the server โ€” meaning it's a duplicate message, a message that showed up after an excessive delay, or one that's just straight up not recognized. No thoughts, no matching parent. ๐Ÿ˜ญ
  • locallimit โ€” Local system limits have been reached when sending a message. We hit the ceiling, bestie. ๐Ÿงฑ

๐Ÿšช EXIT STATUS ๐Ÿšช

perfdhcp dips out with one of these codes:

  • 0 โ€” Success. Slay. โœจ
  • 1 โ€” General error.
  • 2 โ€” Error in command-line arguments. (typo era, we've all been there ๐Ÿ™ˆ)
  • 3 โ€” No general failures in operation, but one or more exchanges were unsuccessful. So close, yet so far. ๐Ÿ’”

๐ŸŒธ USAGE EXAMPLES ๐ŸŒธ

Okay here's the fun part. ๐ŸŽ€

This one simulates regular DHCPv4 traffic from 100 DHCPv4 devices (-R 100), 10 packets per second (-r 10), shows the query/response rate details (-xi), shows a report every 2 seconds (-t 2), and sends the packets to the IP 192.0.2.1:

sudo perfdhcp -xi -t 2 -r 10 -R 100 192.0.2.1

Now a similar situation but for DHCPv6. Note that the DHCPv6 protocol uses link-local addresses, so you must specify the interface (eth0 in this example) to send the traffic on. And all is a convenience alias for All_DHCP_Relay_Agents_and_Servers (the multicast address FF02::1:2). You can also use the servers alias to refer to All_DHCP_Servers (the multicast address FF05::1:3). The default is all. ๐Ÿฆ‹

sudo perfdhcp -6 -xi -t 1 -r 1 -R 10 -l eth0 all

The next two examples simulate normal DHCPv4 and DHCPv6 traffic that, after 3 seconds, starts pretending not to receive any responses from the server for 10 seconds. The DHCPv4 protocol signals this with an increased secs field, while DHCPv6 uses the Elapsed Time option. In real networks, this means clients aren't getting responses in a timely matter. It can be used to simulate some HA scenarios, since Kea uses the secs field and the Elapsed Time option value as one of the indicators that the HA partner is not responding. When you enable it with -y and -Y, the secs and Elapsed Time values increase steadily. ๐Ÿ“ˆ

sudo perfdhcp -xi -t 1 -r 1 -y 10 -Y 3 192.0.2.1
sudo perfdhcp -6 -xi -t 1 -r 1 -y 10 -Y 3 2001:db8::1

๐Ÿ“š DOCUMENTATION ๐Ÿ“š

Kea comes with an extensive Kea Administrator Reference Manual that covers literally every aspect of running the Kea software โ€” compilation, installation, configuration, configuration examples, and so much more. Kea also features a Kea Messages Manual, which lists all possible messages Kea can print with a brief description for each of them. Both documents are available in various formats (.txt, .html, .pdf) with the Kea distribution. The Kea documentation lives at โ€ https://kea.readthedocs.io. ๐Ÿ“–

Kea source code is documented in the Kea Developer's Guide, available at https://reports.kea.isc.org/dev_guide/. ๐Ÿค“

The Kea project website is available at https://kea.isc.org. ๐ŸŒˆ


๐Ÿ’Œ MAILING LISTS AND SUPPORT ๐Ÿ’Œ

There are two public mailing lists for the Kea project. kea-users (kea-users at lists.isc.org) is for Kea users, while kea-dev (kea-dev at lists.isc.org) is for Kea developers, prospective contributors, and other advanced users. Both lists are available at https://lists.isc.org. The community provides best-effort support on both of those lists. ๐Ÿซ‚

ISC provides professional support for Kea services. See โ€ https://www.isc.org/kea/ for details. ๐Ÿ’ผ


๐Ÿ•ฐ๏ธ HISTORY ๐Ÿ•ฐ๏ธ

The perfdhcp tool was initially coded in October 2011 by John DuBois, Francis Dupont, and Marcin Siodelski of ISC. Kea 1.0.0, which included perfdhcp, was released in December 2015. Vintage but still ate. ๐Ÿ‘‘


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€


โœ๏ธ AUTHOR โœ๏ธ

Internet Systems Consortium


2019-2025, Internet Systems Consortium


And that's a wrap on the whole page, bestie!! ๐ŸŽ‰ This was Kea version 3.0.4, dated Oct 05, 2026 โ€” go forth, perfdhcp responsibly, and remember: no dropped packets, only dropped drama. ๐Ÿ’–โœจ๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from