bwctld.limits(5)

๐Ÿ“ฆ version 1.5.4, in ubuntu jammy

๐ŸŽ€ bwctld.limits ๐ŸŽ€ โ€” the bwctld.limits(5) file formats manual, bestie edition

okay so you're here because of bwctld.limits โ€” that's the Bandwidth Control daemon policy configuration file, and yes it lives in the File Formats Manual section (section 5, iykyk). Pull up a chair, we're doing policy config and we're doing it together. ๐Ÿ’…


โœจ NAME โœจ

bwctld.limits โ€” the Bandwidth Control daemon policy configuration file. that's it, that's the name. ๐Ÿซถ


๐Ÿ’– DESCRIPTION ๐Ÿ’–

So. The bwctld.limits file is literally where you define the policy configuration for the bwctld program. It's the whole vibe-setter: it lets the system administrator allocate resources in a variety of ways. however you wanna slice it, this file is the blueprint. ๐ŸŒˆ

There are two parts to the policy configuration, and honestly they're giving main-character energy each:

  • Authentication โ€” Who is making the request? This can be very specific to an individual user, or it can be more general in that the connection is coming from some particular network. like, "who even are you" energy.
  • Authorization โ€” Now that the connection has been generally identified, what will bwctld allow it to do? the "okay cool, but what are your permissions" part. ๐Ÿ”ฅ

The authentication is done by assigning a userclass to each new connection as it comes in. Each userclass has a set of limits associated with it. And here's the tea: the userclasses are hierarchical, so a connection must pass the limit restrictions of the given userclass as well as all parent classes. no skipping levels, bestie. ๐Ÿ’€

Within the bwcltd.limits file, assign lines are used to assign a userclass to a given connection. limit lines are used to define a userclass and set the limits associated with that userclass. The file is read sequentially, and it is not permitted to use a classname before it is defined using a limit line. order matters, no cap. ๐Ÿฆ‹

The format of this file is:

  • Comment lines are any line where the first non-whitespace character is #. These lines are counted to return line numbers in error messages but are otherwise ignored by bwctld.
  • Lines may be continued using the semi-standard \ character followed immediately by a newline. This is the only valid place for the \ character. If it is found elsewhere a syntax error is reported. ๐Ÿšจ
  • Blank lines are treated as comment lines.
  • All other lines must conform to the syntax of a limit line or an assign line.

๐ŸŒŸ CONFIGURATION OPTIONS ๐ŸŒŸ

๐Ÿ’œ limit

This directive is used to define the userclass hierarchy. It defines the classname as well as the limits associated with that class. A classname may only be defined once. The format of the limit directive is:

limit classname with limtype=value[,limtype=value]*

classname defines the name of the class with the given limits. Whitespace is used as a separator but is otherwise ignored. classname may be used as a directory name component within bwctld, so take care not to use characters that would be invalid. (i.e. '*' or '/' would be particularly bad.) ๐Ÿ˜ญ please don't do that.

limtype and value indicate the particular type of limit and value to apply to this userclass. The available settings for limtype are:

  • allow_open_mode โ€” valid values: on/off โ€” default: on
  • allow_tcp โ€” valid values: on/off โ€” default: on
  • allow_udp โ€” valid values: on/off โ€” default: off
  • bandwidth โ€” valid values: integer (b/s) โ€” default: 0 (unlimited)
  • duration โ€” valid values: integer (seconds) โ€” default: 0 (unlimited)
  • event_horizon โ€” valid values: integer (seconds) โ€” default: 0 (unlimited)
  • max_time_error โ€” valid values: integer (seconds) โ€” default: 0 (unlimited)
  • parent โ€” valid values: previously defined classname โ€” default: null
  • pending โ€” valid values: integer โ€” default: 0 (unlimited)

okay now the glow-up explanations for each one, bestie:

๐Ÿฉต allow_open_mode

This limit is only useful if the class is assigned to a netmask. It is used to limit specific IP/netmask identities to only encrypted or authenticated mode transactions, or to allow open mode.

๐Ÿฉต allow_tcp

Allow TCP Iperf tests for userclass. that's the whole thing. slay. โœจ

๐Ÿฉต allow_udp

Allow UDP Iperf tests for userclass.

๐Ÿฉต bandwidth

Maximum amount of bandwidth to allow userclass to use in a UDP Iperf test. 0 indicates unlimited by policy, but remember this is checked all the way to the root of the hierarchy. (If you want an unlimited userclass, your root must be unlimited, and the whole path down to the given userclass.) so likeโ€ฆ the whole chain has to be chill, not just you. ๐Ÿ‘‘

๐Ÿฉต duration

Maximum duration of a single Iperf test for this userclass.

๐Ÿฉต event_horizon

Maximum window into the future to look when trying to schedule a test for this userclass. ๐Ÿ”ฎ

๐Ÿฉต max_time_error

Maximum amount of time error to allow for tests in this class. The time error is the sum of the errors reported by NTP on the two involved systems. The larger the time error, the larger the duration of the reservation, because the time error is used to ensure tests don't overlap. There is a limit on this to defend against DOS attacks, where a client could report large errors to ensure other clients can not allocate test reservations. so yeah, this one's the security guard at the door. ๐Ÿšง

๐Ÿฉต parent

The first limit line cannot have a parent since none have been defined yet. As such, the first line defines the root of your class hierarchy. All remaining limit lines MUST assign a parent. (It is hierarchical, after all.) ๐ŸŒณ no orphan classes here.

๐Ÿฉต pending

Maximum number of pending reservations for this userclass.


๐Ÿ’œ assign

The assign directive is used to assign a userclass to a given connection. Basically, it authenticates the connection. The format of the assign directive is:

assign authtype [args] classname

authtype identifies the type of authentication being used. Whitespace is used as a separator but is otherwise ignored. classname must have been previously defined with the limit directive earlier in the file. ๐Ÿ‘€ (yes, earlier. we talked about this.)

The available settings for authtype are:

๐Ÿ“ default

Used if no other assignment matches. It takes no args. the fallback bestie. ๐Ÿ’•

๐Ÿ“ net subnet

Assign a specific subnet to a given userclass. subnet must be specified using VLSM notation (IP/nbits). The only arg is the subnet. For example:

  • 127.0.0.1/32 โ€” would match only the loopback IPv4 address.
  • ::1/128 โ€” would match only the loopback IPv6 address.
  • 192.168.1.0/24 โ€” would match all hosts on the 192.168.1.XXX network.

There must be no set bits in the non-masked portion of the address part of the subnet specification. i.e., 192.168.1.1/24 would be an invalid subnet due to the bit set in the fourth octet. ๐Ÿ™ˆ don't do it, it's not the vibe.

๐Ÿ“ user user

Assign a specific user to a given userclass. The user must be defined in the bwctld.keys file. ๐Ÿ”‘


๐Ÿ” AUTHENTICATION PROCESS ๐Ÿ”

bwctld determines if it should allow a connection from the client based upon the authentication mode of the request and the source IP address of the connection. Here's how the vibes break down:

If the client connection is in authenticated or encrypted mode, the daemon does not do any filtering based upon the source address of the connection. (See the -A option to bwctl and the authmode option in bwctld.conf.) In these modes, bwctld simply uses the identity of the connection to determine the userclass limits. โœจ

If the connection is made in open mode, then bwctld first uses the source address to determine if bwctld should allow an open mode connection from that subnet at all. (This is the purpose of the allow_open_mode limtype described above.) If open mode is allowed from this subnet, then the userclass is determined by the closest subnet match defined by the assign net lines in the bwctld.limits file. ๐ŸŽฏ closest match wins, that's the rule.


โœจ EXAMPLES โœจ

okay bestie, this is the part where it all comes together ๐Ÿ’– so like, an initial limit line might look like:

limit root with \
       bandwidth=900m, \
       duration=0, \
       allow_udp=on, \
       allow_tcp=on, \
       allow_open_mode=off

so what did we just do?? we made a userclass named root ๐ŸŽ€ and because there's no parent specified, this has to be the first userclass defined in the file. no skipping the line, babes. this userclass is living its most generous life โ€” very liberal limits, UDP enabled, 900m โ€” but listen: allow_open_mode is off for this one, so any connection that wants these limits has to actually authenticate with an AES key. no key, no vibes ๐Ÿ’…


now, if an administrator also wants a userclass that just says "no โค๏ธ" to literally everything, they might add:

limit jail with \
       parent=root, \
       allow_udp=off, \
       allow_tcp=off, \
       allow_open_mode=off

boom ๐Ÿ’€ userclass named jail. and since both the UDP and TCP tests have been denied, no tests will be allowed, periodt. also allow_open_mode is off, so initial connections that aren't in authenticated or encrypted mode get dropped immediately anyway. (and lowkey, assigning a user identity to this userclass wouldn't make much sense. if you don't want connections from a particular user, the best thing to do is just remove that user from the bwctld.keys file. cleaner, fr fr.)


but say the administrator wanted to allow a limited amount of open tests โ€” then they could define a userclass like:

limit open with \
       parent=root, \
       allow_open_mode=on, \
       allow_udp=off, \
       allow_tcp=on, \
       duration=30, \
       event_horizon=300, \
       pending=5

okay THIS one is fun โœจ it could be used to let random connections run TCP throughput tests. it caps those tests at 30 seconds of duration, and they can only be scheduled within the next 5 minutes (event_horizon=300). and on top of that, this userclass can only have 5 currently pending reservations. which means โ€” do the math bestie ๐Ÿง  โ€” this userclass can only schedule 50% of the next 5 minutes. the whole point of this setup? the administrator can define other userclasses with a larger event_horizon, which gives them priority over this class. it's giving VIP line energy ๐Ÿ‘‘

(and if you have suggestions for other methods of priority scheduling, send them to bwctl-users@internet2.edu โ€” they want to hear from you ๐Ÿซถ)


so now, these three userclasses might get assigned to specific connections like this:

# default open
assign default open

# badguys subnet
assign net 192.168.1.0/24 jail

# network admins
assign user joe root
assign user jim root
assign user bob root

look at the way this set of assign lines works ๐Ÿ˜ญ it specifically denies access from any open mode connection coming from the badguys subnet (192.168.1.0/24 โ†’ jail, bye ๐Ÿ’€). and it specifically allows access to authenticated or encrypted mode transactions that can authenticate as the identities joe, jim or bob โ€” yes, even from the badguys subnet, iconic behavior honestly ๐ŸŒธ and every other connection? they match the assign default rule and get the limits from the open userclass. slay.


๐ŸŒˆ SEE ALSO ๐ŸŒˆ


๐Ÿ’œ ACKNOWLEDGMENTS ๐Ÿ’œ

this material is based in part on work supported by the National Science Foundation (NSF) under Grant No. ANI-0314723. any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the NSF. (the NSF is not responsible for my emoji usage, that's all me ๐ŸŽ€)


and that's a wrap on bwctld.limits(5), bestie ๐Ÿฆ‹ this page is from $Date$, so like, timestamped and everything. go forth and limit responsibly ๐Ÿ’…โœจ
๐Ÿ“ฆ where this page comes from