Ongoing re-architecture

Arran Cudbard-Bell a.cudbardb at
Mon Nov 16 17:39:50 CET 2015

> On 16 Nov 2015, at 08:55, Alan DeKok <aland at> wrote:
>  For people watching github... there's been a flurry of changes to the code in the last few weeks.  This is all necessary for future expansion of the server.
>  Arran has updated the way the dictionary API handles attributes.   Previously, it assumed that all attributes could be packet into a 32-bit integer... via a terrible packing scheme.  The idea at the time was that you could address any attribute at compile-time via a magic number.

Now they're all in a very large tree structure.

>  That functionality was never used.  Worse, it prevented us from having TLVs nested more than 4 layers, and made other work harder.  So it's been removed.

Users of the internal APIs should no longer use fr_dict_attr_by_num, except for top level VSA and RFC attributes.

If you need to access a TLV navigate the relationships from the dictionary root.

fr_dict_attr_t const *da;

da = fr_dict_attr_child_by_num(fr_dict_root(fr_main_dict), PW_VENDOR_SPECIFIC);
da = fr_dict_attr_child_by_num(da, MY_FAVOURITE_VENDOR);
da = fr_dict_attr_child_by_num(da, 1);
da = fr_dict_attr_child_by_num(da, 2);

Or use fr_dict_attr_by_name() which works as before (all attribute names are in the same namespace).

Removing the packing allows parent/child relationships between attribute numbers of greater than 8bits.

>  Attributes can now be nested to almost any depth.  After about 20, though, it starts getting silly.

This allows us to represent nested tree structure from other protocols using dictionary attributes, you can map SNMP OIDs to RADIUS TLVs for example.   For the current RADIUS MIBs that requires a nesting level of 14.

There is a hard limit of 24.  This is mostly for sanity.  The maximum in RADIUS is 162, but you won't be able to fit many attributes in a packet with that level of nesting :)

If the limit needs to be changed in future, it's now just a one line change instead of a 10,000 line change *ugh*.

>  As a result of the previous change, the RADIUS encoder / decoder was updated.  The decoder didn't change much, as it was already well abstracted.  The encoder was almost completely re-written.  It's now *much* simpler and easier to understand.

The DHCPv4 option Encoder/Decoder were also rewritten in the style of the RADIUS Encoder/Decoder to make maintenance easier.  The two protocols are very similar in the way attributes are packed, the major differences are the length field in DHCP does not include the option header, DHCP supports the concept of value coalescing in single options, DHCP doesn't need to deal with WiMAX crap, and DHCP's vendor specific options are buried inside a TLV structure.

They both use 8bit attribute space, 8bit lengths, support VSAs (ish in the case of DHCP), support TLVs, and use the same packing for TLVs.

>  What made this possible was the tests in src/tests.  And the Coverity / clang scans.  So we're sure that the new code works, and has minimal problems.

Yes, the testing framework made this far far easier.  WiMAX must die.

>  I've been working on cleaning up the architecture of the server.  Previously, the initialization code was scattered across multiple files, and wasn't very clear.  If you now read radiusd.c, it's pretty clear what gets initialized, and in what order.
>  There is more to do, of course.  But the goal is a better structure which is easier to maintain, and easier to extend.

The listener registry which is possibly the next part of Alan's work may also allow proper hupping of all modules at some point in the future.


Arran Cudbard-Bell <a.cudbardb at>
FreeRADIUS development team

FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 872 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <>

More information about the Freeradius-Devel mailing list