-
Notifications
You must be signed in to change notification settings - Fork 2
Feature_Marking_and_Selection
Many components of Net-SNMP are present to support certain features in the code. But if the code that requires a feature isn't compiled in, the supporting code still is and needlessly adds to the size of the running executable and libraries.
The current SVN trunk contains code that is marked as described in this document. The resulting feature hierarchy can be found on the Features page.
- By default, everything must still be included. 3rd-party developers may be making use of code even if internal Net-SNMP code isn't.
- A configure flag (--with-minimalist) to enable minimal code
- --enable-mini-agent should probably turn it on?
- Flags to request including and excluding of features
- --with-features="foo bar"
- --with-out-features="foo bar"
To start with, include <net-snmp/features.h>
#include <net-snmp/features.h>
If you're implementing code that is only needed in certain locations, declare the feature name using the netsnmp_feature_provide() macro:
netsnmp_feature_provide(foo)
If the feature is dependent on the availability of another feature, use the netsnmp_feature_require() or netsnmp_feature_want() macros:
netsnmp_feature_require(foo)
netsnmp_feature_want(bar)
In this case, if foo is unavailable a hard-error will be triggered. However, if bar is unavailable the compilation will continue.
To mark a child as being a sub-feature of a parent, use the following macro:
netsnmp_feature_child_of(child,parent)
This will:
- if the child is required:
- Will turn on the child
- Will not turn on the parent
- if the parent is required:
- Will turn on the child
- Will turn on the parent
The feature macros are checked in the output of cpp processing, so typical #ifdef macros can be used to conditionally include or provide features.
To provide conditional support of a feature depending on the output of configure checks:
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/features.h>
#ifdef HAVE_FOO_H
netsnmp_feature_provide(netsnmpfoo)
#endif
Many times there might be a function x() (usually in another file) which is only needed if someone has requested function y(). To test for this, use:
#ifdef NETSNMP_FEATURE_REQUIRE_Y
netsnmp_feature_require(x) /* x() is implemented elsewhere, but we need it to implement y() */
#endif /* NETSNMP_FEATURE_REQUIRE_Y */
Sometimes you may wish to advertise support for a feature only if a subordinate feature is also available:
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/features.h>
#ifdef NETSNMP_FEATURE_HAS_BAR
netsnmp_feature_provide(foo)
#endif /* NETSNMP_FEATURE_HAS_BAR */
To mark code as removable if a feature is unneeded, surround it with #ifndef markings:
#ifndef NETSNMP_FEATURE_REMOVE_FOO
/* normal foo code */
#else /* !NETSNMP_FEATURE_REMOVE_FOO */
netsnmp_feature_unused(foo);
#endif /* !NETSNMP_FEATURE_REMOVE_FOO */
A few important notes:
- Always use the #ifndef version of checking. If the features.h fails to define anything, the feature will be included by default.
- Always include the define name in comments after #else and #endif clauses. Later "code-removal" scripts will depend upon it.
- The netsnmp_feature_unused() macro is only needed if there is no code in the file left after the features have been removed.
If you're writing code that depends on features but isn't "required" (ie, you used netsnmp_feature_want(foo)), then you can test for its support:
#include <net-snmp/features.h>
#ifdef NETSNMP_FEATURE_HAS_FOO
/* include foo-specific coding here */
#endif /* NETSNMP_FEATURE_HAS_FOO */
Behind the scenes, this support is implemented using a number of techniques:
- A set of configure flags to enable minimalist mode and for selecting and removing specific features, as mentioned previously.
- When --with-minimalist is turned on, it adds an extra step to the compilation process: features which performs the rest of the steps below:
- Compile-time feature-check and feature-remove scripts that:
- feature-check: examines a code file for
netsnmp_feature_XXX() lines and creates #define
statements based on what it finds.
- Requires that the code be examined in reverse order (eg, agent/mibgroup/ before agent/helpers/ and both before snmplib/).
- feature-remove: examines the results of the feature-check output
and creates .h files specific to individual code sections with
NETSNMP_FEATURE_REMOVE_XXX definitions or
NETSNMP_FEATURE_HAS_XXX definitions.
- Includes a feature if anything requires or wants it
- Removes a feature if nothing requires it
- Removes a feature if something wants it, but --with-out-features requested it to be removed
- Includes a feature if nothing required or wanted it but --with-features requested it
- feature-check: examines a code file for
netsnmp_feature_XXX() lines and creates #define
statements based on what it finds.
- A Net-SNMP/features.h file that "does the right thing".
- During the run of feature-check it includes the definitions being produced by the checking
- During compilation time, it includes the various feature.h files that has the NETSNMP_FEATURE_REMOVE_XXX and NETSNMP_FEATURE_HAS_XXX tokens.
- ./configure ; make ; make install still works
- ./configure --with-minimalist ; make ; make install works
- For developers working on feature specific code, make run from
the top level directory will continue to update the generated
feature header files
- But... running make cleanfeatures first is safer if you're heavily modifying provide/require lines
- Allows for run-time modifications without re-running configure
In the new DTLS and TLS code we require a significant amount of certificate code. Code is needed to manipulate certificate chains, load and unload directories of certificates, etc. This code is contained in snmplib/cert_util.c.
To only include this code support when needed, snmplib/cert_util.c has the following code:
#include <net-snmp/features.h>
netsnmp_feature_provide(cert_util)
#ifndef NETSNMP_FEATURE_REMOVE_CERT_UTIL
/* ... */
#endif /* NETSNMP_FEATURE_REMOVE_CERT_UTIL */
And in the snmplib/transports/snmpTLSTCPDomain.c and snmplib/transports/snmpDTLSUDPDomain.c file:
#include <net-snmp/features.h>
netsnmp_feature_require(cert_util)
The end result is that if a user is not requiring the DTLS or TLS support and they've requested --enable-minimalist then the entire cert_util.c functionality is not included. This is actually a very significant chunk of code.
After building with your favorite set of configure options, you can see how many functions exist in the built .o files using this handy perl script:
perl local/minimalist/find-unused-code -g
Which will produce a list of functions that were compiled but never referenced by another .o file, which indicates they're likely unused. The -g switch will then grep all of the source code for source files that contain calls to those functions. This allows you to know which file contains the function that should be marked as a feature, and which other files need to be modified to netsnmp_feature_require() that function/feature.