Skip to content

RIOT: make use of log.h for dsrv_log() #177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 21, 2023

Conversation

benpicco
Copy link
Contributor

tinydtls allows to switch log levels at run-time.
This means that all debug log strings and formaters are included in the binary, which comes at a significant ROM cost.

On RIOT we can define a tinydtls_debug pseudo-module that enables the debug facilities, but in it's absence we can just skip building dtls_debug.c and turn log functions into no-ops.

We can still make use of RIOT's log facilities, but there the log level is set at build time so the compiler will turn everything below that into a no-op.

@boaks
Copy link
Contributor

boaks commented Nov 15, 2022

Your contribution is very welcome, I considered to investigate for such a solution to improve the support of zephyr.

Did you spend some time into analyze other ports, e.g. zephyr?

Maybe you split this in logical "without logging" and the select that for RIOT? That would make it easier to adapt and use it for zephyr.

@benpicco
Copy link
Contributor Author

This mostly just makes use of the pre-existing NDEBUG flag and ensures that the code still works if dtls_debug.c is not being build (when NDEBUG is set).

dtls_debug.c is modified so that dsrv_log() is not being compiled on RIOT even for the !NDEBUG case (because the RIOT log module is used instead).

But maybe it's better to do it the way it's done for the Zephyr port and provide custom log macros and not touch dtls_debug.c at all.

Makefile.riot Outdated

SRC := ccm.c crypto.c dtls.c dtls_debug.c dtls_time.c hmac.c netq.c peer.c session.c dtls_prng.c
ifneq (,$(filter tinydtls_debug, $(USEMODULE)))
SRC += dtls_debug.c
Copy link
Contributor

@boaks boaks Dec 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are functions declared in dtls_debug.h, which are removed by this.

const char *dtls_package_name(void);
const char *dtls_package_version(void);
log_t dtls_get_log_level(void);
void dtls_set_log_level(log_t level);
void dtls_set_log_handler(dtls_log_handler_t app_handler);
void dsrv_log(log_t level, const char *format, ...);

I would consider to keep the dtls_package_name and dtls_package_version. If agreed, then the dtls_debug.c should not be excluded.

The "log" functions may then be added to the empty inlines.
And the excluded section in "dtls_debig.c" (NDEBUG) must be adjusted.

@boaks
Copy link
Contributor

boaks commented Dec 1, 2022

I tested the approach, and generally that works independent from the platform.

FMPOV, it's needed to be more careful about the declared functions, not to result on linker errors.

Please check, which of the declared function you think should be removed with NDEBUG, and which should be kept.

@mrdeep1
Copy link
Contributor

mrdeep1 commented Dec 1, 2022

I am a bit concerned about the usage of NDEBUG. It is used in <assert.h> to control whether assert() is a no-op or not, and then is also used to control whether there is other debug output or not. Is this the intent? What if you want assert() but no logging or vice versa?

For example, the autoconf AC_HEADER_ASSERT (not currently used in TinyDTLS) controls whether NDEBUG is set or not with the intent of controlling assert() only.

Another thought is that you configure the ability to only retain log entries for a defined logging level and above. For instance, if the configured/built max logging level is set to DTLS_LOG_WARN, then any logging entries that are DTLS_LOG_NOTICE, DTLS_LOG_INFO, DTLS_LOG_DEBUG will not get logged and the appropriate code is not there.

@boaks
Copy link
Contributor

boaks commented Dec 2, 2022

I am a bit concerned about the usage of NDEBUG.

NDEBUG is already used to reduce the code by removing the functions only used in log-level debug (logging of ip-addresses and hexdumps).

For zephyr (and RIOT?) the other log-levels are using the platform specific functions, I guess that ended up in the idea of remove dtls_debug.c in that cases completely. This PR does this only for RIOT.

So, I see two questions:

  • should NDEBUG remove the debug log level extra functions?
  • should NDEBUG remove then also the other obsolete logging functions (e.g. dtls_set_log_level or dtls_set_log_handler)?

Overall, that may require to "consolidate" the "dtls_debug.c" file a little more in order to have it more transparent, when platform logging is used, and when "dtls_debug" is used.

@mrdeep1
Copy link
Contributor

mrdeep1 commented Dec 2, 2022

I think that NDEBUG should be renamed to DTLS_NDEBUG for the TinyDTLS specific stuff so there is no confusion / clashes with the use of NDEBUG in header file <assert.h>. It would help if AC_HEADER_ASSERT is in configure.ac. to give granular control over assert().

I do not think the public API functions should be compiled out when DTLS_NDEBUG is not set - the API must remain consistent for publicly available functions no matter how things are internally compiled. If there are internal functions that are not in the public API, then anything can be done with them as it will not affect any linking for a program.

So, in answer to bullet 2 - No.

@boaks
Copy link
Contributor

boaks commented Dec 2, 2022

I think that NDEBUG should be renamed to DTLS_NDEBUG

OK, but I guess in an other PR.

I do not think the public API functions should be compiled out when DTLS_NDEBUG is not set

This PR doesn't "compile them out", it replaces the function by empty inline ones (I remember a discussion about backwards compatibility. Removing renegotiation breaks that anyway. So if at all, I think it should be done before the 1.0).

And using the platform's logging functions, some of the public API functions are without or limited effect (e.g. dtls_set_log_level or dtls_set_log_handler).

FMPOV:
If a platform offers logging, I prefer to use that.
If someone wants more sophisticated general logging (e.g. the dtls_set_log_handler), I don't want to block that just because some platform's logging doesn't support it.
That results in some diffs/conflicts, but for me, that's unfortunately the price, if we want both.

@mrdeep1
Copy link
Contributor

mrdeep1 commented Dec 2, 2022

This PR doesn't "compile them out", it replaces the function by empty inline ones

So this relies on the higher level code using the same compiler flags that the library was built with when using the public header files to get the inline function version as opposed to getting a linking error because a function is defined in the header files, but there is no code. I really don't like that error prone route and have been burnt by it elsewhere.

The public API must be consistent in how functions are provided no matter what the definitions used to compile the actual library.

@boaks
Copy link
Contributor

boaks commented Dec 2, 2022

I really don't like that error prone route and have been burnt by it elsewhere.

OK, so my conclusion:

  • don't remove dtls_debug.c when linking
  • introduce a new macro DTLS_NDEBUG (or DTLS_DEBUG?)
  • the code inside the dtls_debug.c may be disabled with DTLS_NDEBUG / enabled with DTLS_DEBUG

(I guess, this will still save 19.5 of the 20 k bytes. Zephyr usually drops unused function when linking so there my saving using the approach of this PR was less, I guess mainly the other effects of the NDEBUG.)

@benpicco

Are you OK, if we go that way?

@benpicco
Copy link
Contributor Author

benpicco commented Dec 13, 2022

Sounds good to me. But should the existing occurences of NDEBUG in dtls_debug.c on the main branch also be replaced by DTLS_NDEBUG?
Having two similar macros there is kind of awkward.

@boaks
Copy link
Contributor

boaks commented Dec 13, 2022

If all agree, we will revise all usage of the NDEBUG macro.

@benpicco benpicco changed the title RIOT: only include dtls_debug.c when tinydtls_debug is enabled RIOT: make use of log.h for dsrv_log() Dec 13, 2022
@benpicco
Copy link
Contributor Author

Removing the static inline leaves dtls_debug.c as is. So this PR now only hooks up tinydtls log functions with RIOT's log.h

Signed-off-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
Those flags are already configured by the RIOT package.

Signed-off-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
@boaks
Copy link
Contributor

boaks commented Dec 18, 2022

LGTM

@benpicco
Copy link
Contributor Author

What's the status on this?

@boaks
Copy link
Contributor

boaks commented Jan 19, 2023

@obgm

OK from your side? Or should I merge it to develop?

@obgm
Copy link
Contributor

obgm commented Jan 20, 2023

@boaks Yes, please merge (= LGTM).

My 2 cents on NDEBUG: The use of this pre-processor symbol was deliberate for exactly what it does. But if you see reasons for separating this from the debug code I am good with a prefixed version as proposed.

@boaks boaks merged commit 4cb6adc into eclipse-tinydtls:main Jan 21, 2023
@benpicco benpicco deleted the riot-debug branch January 21, 2023 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants