Changes between Version 18 and Version 19 of DhcpOptionDefinition


Ignore:
Timestamp:
Oct 17, 2012, 1:41:33 PM (5 years ago)
Author:
stephen
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • DhcpOptionDefinition

    v18 v19  
    178178=== Design ===
    179179==== Introduction ====
    180 The design is based around the idea of an OptionDefinition object.  The configuration is first read for user-defined options, and for each option an OptionDefinition object is created. A user-defined option overrides standard option if its vendor space is undefined and its code belongs to the set of IANA-defined options. In order to allow the overriding of standard options, the program will create OptionDefinition objects only for those standard options which are not already defined in user options space. On receipt of the option in a DHCP message, all OptionDefinition objects are inspected. Should local match be found, the OptionDefinition object is queried for corresponding '''option factory''' function to parse the received option.
     180The design is based around the idea of an !OptionDefinition object.  The configuration is first read for user-defined options, and for each option an !OptionDefinition object is created. A user-defined option overrides standard option if its vendor space is undefined and its code belongs to the set of IANA-defined options. In order to allow the overriding of standard options, the program will create !OptionDefinition objects only for those standard options which are not already defined in user options space. On receipt of the option in a DHCP message, all !OptionDefinition objects are inspected. Should local match be found, the !OptionDefinition object is queried for corresponding '''option factory''' function to parse the received option.
    181181
    182182==== Option Definition (outline design) ====
    183 The OptionDefinition object is be created from the definition in the configuration for user configurable definitions. For standard option the definition is not configurable thus OptionDefinition object is created using hard coded data. This object has the following data structure:
     183The !OptionDefinition object is be created from the definition in the configuration for user configurable definitions. For standard option the definition is not configurable thus !OptionDefinition object is created using hard coded data. This object has the following data structure:
    184184
    185185* '''Name'''
     
    190190* '''Suboptions''' - holds the list of suboptions being encapsulated by this option. This list is obtained by querying the list of all options belonging to the custom defined space specified in the Configuration Manager.
    191191
    192 When option (not a sub-option) has been received in the packet its '''code''' is used to identify appropriate OptionDefinition object. This object can be queried for '''Namespace''' object it encapsulates. This object can be then queried for the list of sub-options (actually their OptionDefinition objects). The received sub-option code can be then matched with one of these OptionDefinition object's codes, which is used to unpack the sub-option. Such design implies that additional information (Namespace) has to be passed to the function which unpacks encapsulated options. Obviously this parameter may be optional.
     192When option (not a sub-option) has been received in the packet its '''code''' is used to identify appropriate !OptionDefinition object. This object can be queried for '''Namespace''' object it encapsulates. This object can be then queried for the list of sub-options (actually their !OptionDefinition objects). The received sub-option code can be then matched with one of these !OptionDefinition object's codes, which is used to unpack the sub-option. Such design implies that additional information (Namespace) has to be passed to the function which unpacks encapsulated options. Obviously this parameter may be optional.
    193193
    194194TBD: What should we do if the received sub-option code is not found among encapsulated options?
    195195
    196 When appropriate OptionDefinition object has been identified for option or sub-option it is used to get the corresponding '''factory''' function. The array of bytes representing the option is passed to the factory function, which creates the the object of the type Option or of the type derived from Option. The actual type of the object being created depends on the structure of the option described by the OptionDefinition. For typical option formats there are dedicated classes derived from Option class (e.g. Option6IA, Option6IAAddr etc). These objects expose accessors and mutators to access and modify data in the option. If the option format does not match any typical format that has specialized factory function associated with it, the OptionDefinition returns a generic factory function. When the buffer containing received option is passed to this factory function, it iterates through the vector of codes and uses each code to identify the meaning of the next set of bytes; the array indication is used to determine whether it should repeatedly run through the code vector until the byte stream is exhausted.  An error indication is returned if the length of the data does not match the length inferred from the option definition. As the result, the CustomOption object is created with the following data structure:
     196When appropriate !OptionDefinition object has been identified for option or sub-option it is used to get the corresponding '''factory''' function. The array of bytes representing the option is passed to the factory function, which creates the the object of the type Option or of the type derived from Option. The actual type of the object being created depends on the structure of the option described by the !OptionDefinition. For typical option formats there are dedicated classes derived from Option class (e.g. Option6IA, Option6IAAddr etc). These objects expose accessors and mutators to access and modify data in the option. If the option format does not match any typical format that has specialized factory function associated with it, the !OptionDefinition returns a generic factory function. When the buffer containing received option is passed to this factory function, it iterates through the vector of codes and uses each code to identify the meaning of the next set of bytes; the array indication is used to determine whether it should repeatedly run through the code vector until the byte stream is exhausted.  An error indication is returned if the length of the data does not match the length inferred from the option definition. As the result, the !CustomOption object is created with the following data structure:
    197197
    198198* Vector with the array of data records. This array always contains one element if "array indicator" is set to false. Otherwise it may contain one or more elements. Each data record is represented as:
     
    202202    * '''Data''' - vector of bytes (buffer) representing field data.
    203203
    204 The 'Type' and 'Data' fields provide sufficient information to cast the information in 'Data' to appropriate type, bool, uint8_t, IOAddress. Also CustomOption has all required utility functions to cast the data behind the scenes.
    205 
    206 The CustomOption object has a generic structure that can be used to store any option format. Also, the CustomOption organizes data in the structure that reflects its definition in the configuration .spec file so it is possible to access data fields as shown above:
     204The 'Type' and 'Data' fields provide sufficient information to cast the information in 'Data' to appropriate type, bool, uint8_t, IOAddress. Also !CustomOption has all required utility functions to cast the data behind the scenes.
     205
     206The !CustomOption object has a generic structure that can be used to store any option format. Also, the !CustomOption organizes data in the structure that reflects its definition in the configuration .spec file so it is possible to access data fields as shown above:
    207207{{{
    208208isc.dns-name[0].server
    209209}}}
    210210
    211 However, this generic approach to storing options has performance implications and should not be used to all options. For some standard options there are dedicated classes derived from Option class that have specialized pack()/unpack() functions and keep data in the specialized structures to optimize performance. Such options do not provide interface to access data fields by their name right now but they may be extended to support it.
    212 
    213 If the server has to add user-defined options to its responses, it is assumed that elsewhere in the configuration will be the values of the parameters to be used. These values can be passed to OptionDefinition object as a set of tokens. The OptionDefinition object is capable to validate if provided set of tokens matches the specified option format. The stream of tokens should be validated every time the option data set is added or changed in the Configuration Manager.
    214 
    215 When OptionDefinition object is created it tries to match the specified format with common factory functions implemented in it. The common factory functions are those that are used to create instances of typical options, e.g. carrying list of addresses, single string value etc. The factory function instance returned by the OptionDefinition object can be "registered" and used when option associated with it is to be created. In the current implementation of libdhcp++ factory functions are searched using option code only. This is not sufficient because option codes may overlap: vendor options may have the same codes as standard options. For this reason there is a need to extend factory functions search mechanism to allow searching for factory functions using combination of option codes and fully qualified option names. Perhaps std::multimap or boost::multi_index_container (http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html) could be used to achieve it.
    216 
    217 Once factory functions are registered and can be accessed using the option code and name, they are used to create instances of all options that have been configured to be sent by the server. Options instances are grouped by subnets. There may be multiple instances of the same option, as each instance can be associated with different subnet and may convey different data. Each subnet definition has an underlying options container. This container should be indexed by the option name and option code. It can be implemented with one map (to search by option names) and one multimap (to search by option codes). Alternatively, it can be implemented as multi_index_container with these two indexes. The Option pointers are directly used to form the DHCP packets being sent to the client.
     211However, this generic approach to storing options has performance implications and should not be used for all options. For some standard options, there are dedicated classes derived from Option class that have specialized pack()/unpack() functions, and keep data in the specialized structures to optimize performance. Such options do not provide an interface to access the data fields by their name right now, but they may be extended to support it.
     212
     213If the server has to add user-defined options to its responses, it is assumed that elsewhere in the configuration will be the values of the parameters to be used. These values can be passed to an !OptionDefinition object as a set of tokens. The !OptionDefinition object is validates if the provided set of tokens matches the specified option format. The stream of tokens should be validated every time the option data set is added or changed in the Configuration Manager.
     214
     215When an !OptionDefinition object is created, it tries to match the specified format with the common factory functions implemented in it. These functions are those used to create instances of typical options, e.g. carrying list of addresses, single string value etc. The factory function instance returned by the !OptionDefinition object can be "registered" and used when the option associated with it is to be created. In the current implementation of libdhcp++, factory functions are sought using the option code only. This is not sufficient because option codes may overlap: vendor options may have the same codes as standard options. For this reason there is a need to extend the factory function search mechanism to allow searching for factory functions using combination of option codes and fully qualified option names. It is possible that [http://www.cplusplus.com/reference/stl/multimap std::multimap] or [http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html boost::multi_index_container] could be used to achieve it.
     216
     217Once the factory functions are registered and are accessible using the option code and name, they are used to create instances of all options configured to be sent by the server. Options instances are grouped by subnets. There may be multiple instances of the same option, as each instance can be associated with different subnet and may convey different data. Each subnet definition has an underlying options container. This container should be indexed by the option name and option code. It can be implemented with one map (to search by option names) and one multimap (to search by option codes). Alternatively, it can be implemented as multi_index_container with these two indexes. The Option pointers are directly used to form the DHCP packets being sent to the client.
    218218
    219219=== Option Data (outline design) ===
    220 Many DHCP options, either standard or custom-defined, can be configured to carry predefined data. This data is selected on per-subnet basis. The configuration structures for subnets has been created as part of ticket #2269. It is planned to use these data structures hold the options for different subnets. The Subnet class will be extended with !OptionCollection, which will be the container for all options that can be sent for the particular subnet. These options are represented by Option (or derived from Option) objects and can be directly added to the outgoing DHCP packet. It is desired that elements of this collection can be searched using option name (alternatively, using scope) or option code. Each option instance is created using the appropriate factory function returned by OptionDefinition object and data "tokens" from the configuration database.
    221 
    222 TBD: should the predefined options in !OptionCollection have sub-options included or sub-options should be added on case by case basis? It should be easy to get the list of sub-options using OptionDefinition object as it has the list of sub-options belonging to the scope that option encapsulates.
     220Many DHCP options, either standard or custom-defined, can be configured to carry predefined data. This data is selected on per-subnet basis. The configuration structures for subnets have been created as part of ticket #2269. It is planned to use these data structures hold the options for different subnets. The Subnet class will be extended with an !OptionCollection, which will be the container for all options that can be sent for the particular subnet. These options are represented by Option (or derived from Option) objects and can be directly added to the outgoing DHCP packet. It is desired that elements of this collection can be searched using option name (alternatively, using scope) or option code. Each option instance is created using the appropriate factory function returned by !OptionDefinition object and data "tokens" from the configuration database.
     221
     222''TBD: should the predefined options in !OptionCollection have sub-options included or sub-options should be added on case by case basis? It should be easy to get the list of sub-options using an !OptionDefinition object, as it has the list of sub-options belonging to the scope that option encapsulates.''
    223223
    224224
     
    229229 * We should emphasize somehow that vendor space definitions are not strictly for vendor specific options (option 43 in DHCPv4 and option 17 in DHCPv6), but also for defining custom options that may appear in suboptions.
    230230   * Marcin: Vendor space is similar to the scope. There will be one data structure that holds scopes and vendor spaces. For each element in this data structure there will be a boolean field indicating that the element is a vendor space or scope.
    231  * Currently this proposal defines a way to define custom suboptions. However, it does not define a way to convey them, i.e. there is no way to define that custom option should appear as sub-option within other option. Here's a life example: there is [http://tools.ietf.org/html/draft-ietf-mif-dhcpv6-route-option-03 route-option-03] draft that defines NEXT_HOP option that contains one or more RTPREFIX option. We need a way to define that.
     231 * Currently this proposal defines a way to define custom suboptions. However, it does not define a way to convey them, i.e. there is no way to define that custom option should appear as sub-option within other option. Here's a life example: there is [http://tools.ietf.org/html/draft-ietf-mif-dhcpv6-route-option route option] draft that defines NEXT_HOP option that contains one or more RTPREFIX option. We need a way to define that.
    232232   * Marcin: Each option definition comprises the optional ''suboptions'' which takes string parameter indicating the sub-options scope. This scope aggregates options that the particular option encapsulates. In the first stage of implementation we may use the scope to get the list of sub-options to be included in the particular option. In the future we may want to create the conditional decisions whether to include the particular option or not and possibly some extra configuration will be required through the .spec file.
    233233 * Do we want to control cardinality in any way? "at most one option may appear", "at least one must appear", "there may be one or more of such options", etc. Again, that is more of a policy discussion, rather than option format definition.