Library layering
Problem
The three libraries libnetsnmpmibs, libnetsnmphelpers and libnetsnmpagent have circular dependencies instead of what should be a clean mibs -> helpers -> agent -> main library dependency chain:
- libnetsnmpmibs depends on libnetsnmphelpers
- both of these depend on libnetsnmpagent
- all 3 of these depend on libnetsnmp
There are only a few problematic calls/functions that violate this dependency chain:
Critical dependency | Symbol/function | implementation in ... (under agent/) | caller(s) (under agent/) | Comment |
agent -> mibs | make_tempfile | mibgroup/util_funcs.c | mibgroup/utilities/execute.c:run_shell_command() | fixed in 5.4+ by introducing netsnmp_mktemp |
agent -> helpers | netsnmp_init_helpers | helpers/all_helpers.c | snmp_vars.c:init_agent() | fix by e.g. merging agent and helpers libs (see below) |
agent -> helpers | netsnmp_register_null | helpers/null.c | agent_registry.c:setup_tree() | ditto |
agent -> helpers | netsnmp_register_null_context | helpers/null.c | agent_registry.c:netsnmp_subtree_load() | ditto |
agent -> helpers | netsnmp_register_old_api | helpers/old_api.c | agent_registry.c:register_mib_context() | ditto |
agent -> helpers | netsnmp_bulk_to_next_fix_requests | helpers/bulk_to_next.c | mibgroup/agentx/master.c:agentx_got_response() | ditto |
agent -> helpers | netsnmp_get_bulk_to_next_handler | helpers/bulk_to_next.c | agent_handler.c:netsnmp_register_handler() | ditto |
other strange dependencies | ||||
libnetsnmptrapd -> snmptrapd | extern int dropauth | apps/snmptrapd.c | apps/snmptrapd_handlers.c:print_handler() | Move 'dropauth' from snmptrapd.c to snmptrapd_handlers.c. Done for MAIN. |
libnetsnmptrapd -> snmptrapd | extern int SyslogTrap | apps/snmptrapd.c | apps/snmptrapd_handlers.c:syslog_handler() | Move 'SyslogTrap' from snmptrapd.c to snmptrapd_handlers.c. Done for MAIN. |
libnetsnmptrapd -> snmptrapd | event_input | apps/snmptrapd.c | apps/snmptrapd_handlers.c:event_handler() | Drop "-e"/printEventNumbers support altogether. Done for MAIN. |
Discussion
Most library layering issues have been solved without any drastic changes (see below for details). There's just one issue left: the circular dependency between the agent and helpers lib.
As of May 2010, we seem to have three choices:
- Merge agent and helpers libraries into one libagent library again. Pro: maintain backward-compatibility. Con: agent lib will have increased footprint (+50%). Need to keep empty helpers lib around which is odd.
- Remove the netsnmp_init_helpers() call from init_agent() and require agent developers to add an explicit call to netsnmp_init_helpers() after every call to init_agent(). Pro: keep libraries separate. Small change for developers. Con: backwards-incompatible change.
- Clever compiler constructs to check if helpers lib has been loaded before agent lib. Con: non-portable (gcc-ism)!! Pro: maintain backward-compatibility, keep libraries separate.
The choice under discussion is basically between the first and second approach, unless somebody can come up with a portable third approach.
Status
what? | who? | status? |
rework Makefiles to build libnetsnmp, libnetsnmpagent, libnetsnmphelpers and libnetsnmpmibs in that order | tanders | done for 5.4+ |
duplicate libnetsnmpmibs' make_tempfile as netsnmp_mktemp in libnetsnmp | tanders | done for 5.4+ |
resolve circular dependency between agent and helpers libs (e.g. by merging them) | tbd | TODO (trunk only) |
fix libnetsnmptrapd->snmptrapd dependencies by moving integer variables to the library and dropping the event_input code | dts12, tanders | done for MAIN |
rework Makefiles/configure to fullfil internal and external library dependencies correctly (see below) | tanders | done (5.4+) |
link libperl to libnetsnmpagent instead of snmpd/snmptrapd. How to check at configure time whether linking of libperl to a shared library works? | tanders | forced for 5.5 (w/o additional configure check, r16529); protected by --enable-as-needed in 5.4 (r16569) |
Library linking
Here are the details of what library linking dependencies need to be cleaned up.
shared object/library/binary | currently linked against | dependencies to be added/removed | Comment |
libnetsnmp.so | -lcrypto | ditto | ok |
libnetsnmpagent.so | - | -lnetsnmp -lperl
Linking a shared library against libperl turns out to be tricky since existing PERLLDOPTS reference the static DynaLoader.a which isn't always portable. |
r16529 (5.5) + r16569 (5.4.1.c1) |
libnetsnmphelpers.so | - | -lnetsnmpagent -lnetsnmp | r16419 (5.4+) |
libnetsnmpmibs.so | - | -lnetsnmphelpers -lnetsnmpagent -lnetsnmp | r16419 (5.4+) |
-ldl -lrpm -lrpmio -lpopt -lz ... | r16399 (5.4+) | ||
libnetsnmptrapd.so | - | -lnetsnmpmibs -lnetsnmp -lperl | r16419 (5.4+), r16529 (Perl, 5.5) |
Perl SNMP/SNMP.so | -lnetsnmp -lcrypto (net-snmp-config --libs) | remove "-crypto" in "net-snmp-config --libs" | r16419 (5.4+) |
Perl NetSNMP/ASN/ASN.so | see SNMP.so | see SNMP.so | r16419 (5.4+) |
Perl NetSNMP/OID/OID.so | see SNMP.so | see SNMP.so | r16419 (5.4+) |
Perl NetSNMP/agent/default_store/default_store.so | see SNMP.so | see SNMP.so | r16419 (5.4+) |
Perl NetSNMP/default_store/default_store.so | see SNMP.so | see SNMP.so | r16419 (5.4+) |
Perl NetSNMP/TrapReceiver/TrapReceiver.so | - | -lnetsnmptrapd -lnetsnmpagent -lnetsnmp | r16419 (5.4+) |
Perl NetSNMP/agent/agent.so | almost everything | remove: most external references (dependencies are in libnetsnmpmibs instead) | fixed for 5.4.1.pre3/5.5 |
Python netsnmp/client_intf.so | see SNMP.so | see SNMP.so | r16419 (5.4+) |
agent/snmpd | almost everything | remove: most external references (incl. Perl; dependencies are in libnetsnmpmibs/libnetsnmpagent instead) | fixed for 5.4.1.pre3/5.5 |
apps/snmptrapd | almost everything | remove: most external references (incl. Perl; dependencies are in libnetsnmpmibs/libnetsnmpagent instead) | fixed for 5.4.1.pre3/5.5 |
apps/snmp{get,set,walk,...} | almost everything | remove: most external references (not needed at all) | fixed for 5.4.1.pre2/5.5 |
References
- 2006-10-19 #net-snmp IRC log (starting at 07:12:29)
- Bug #1565496: library layering violation
- Bug #1619827: building with --as-needed is broken
- perl5-porters thread "how to best link libperl to a shared library?"