Skip to content
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

modem: fixes and improvements #68651

Conversation

tomi-font
Copy link
Collaborator

See details in commit messages.

This makes the modem backends use the log level
set for the modem modules instead of the default one.

Signed-off-by: Tomi Fontanilles <[email protected]>
modem_pipe_attach() can send events before returning, which could
provoke a crash as ppp->pipe, still NULL at that time, could be
used either in receiving (if the pipe had some data pending) or
in sending (if the PPP module had already been attached and had
some data to send in its transmit buffer).

ppp->pipe is now set before modem_pipe_attach().
Also, the ATTACHED_BIT is now set only after having actually attached.
And finally, the send_work is now scheduled on PIPE_EVENT_OPENED
so that data is flushed when the (closed) attached pipe is opened.

Signed-off-by: Tomi Fontanilles <[email protected]>
@tomi-font
Copy link
Collaborator Author

Ping @bjarki-trackunit to make sure this does not fall into oblivion.

Comment on lines 262 to 270

if (was_open) {
/* The UART is temporarily unavailable. Give it some time to recover. */
k_sleep(K_MSEC(100));
if (modem_backend_uart_async_is_open(backend)) {
LOG_DBG("Re-enabling UART.");
modem_pipe_open(&backend->pipe);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

The intended behavior is that the user reacts to the PIPE_CLOSED event, and reopens the pipe is required. This allows the user to do any prerequisite work like resetting whatever the pipe was connected to, or ignoring the event if the closing is either expected or inconsequential (like the modem_cellular.c driver where the pipe is closed when the modem switches from AT to CMUX mode as the UART RX goes low for a period)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I see. However in (at least) the case of the CMUX module being attached to the backend, it is the one to receive the pipe events. Currently it doesn't forward the events to the user nor react to the pipe closed event.

I currently see two different ways out of this:

  1. Let the user pass a callback so that events pertaining to the pipe the module is attached to can be received and reacted to.
  2. Make whether the pipe is automatically re-opened configurable (at build or run time).

What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

CMUX should disconnect if the pipe is closed, which will also close every DLCI channel, propagating the closed event :) So essentially option 1

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I did some more testing to reproduce the issue that I was fixing here, and turns out that I remembered wrong.
It can happen when using the PPP module directly plugged in the UART backend. No CMUX involved.

So it's the same story there, except there is no pipe shared between the PPP module and the user, so what you proposed doesn't apply.

Do you have an opinion on how it should be done there?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nope, I have no clear way to justify adding error handling to the PPP module that could not be applied to the CMUX module. I will review the addition of the auto recovery here:

We can not use

k_sleep(K_MSEC(100));

in a work item, as this blocks the work queue. We will need to add an additional delayable work item which waits for those 100ms.

When that work item is started, it must use modem_pipe_open_async() as modem_pipe_open() can block the system workqueue, which becomes a problem if the UART driver also uses it, as this will deadlock the workqueue until modem_pipe_open() times out

This will mean that we can end up in a race condition where the user wants to close the pipe, while we are waiting to try and reopen it, so make sure to cancel the work item in the modem_pipe_close implementation :)

Copy link
Collaborator

@bjarki-andreasen bjarki-andreasen Feb 13, 2024

Choose a reason for hiding this comment

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

Of course, we also have the option op implementing the reopening in the modules using the pipes, so CMUX would reopen if it is connected, and L2 PPP would reopen if it is started, this would scale to all backends (UART ISR, TTY, UART ASYNC etc.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the explanation regarding the work item and the synchronous opening.

I will leave the automatic recovery out of this PR so that the other changes can get in, but I am still planning to do something about it. Just have to agree on how exactly.

Nope, I have no clear way to justify adding error handling to the PPP module that could not be applied to the CMUX module.

I am not sure I quite understood this. Did you imply that the solution should apply to both the PPP and CMUX modules, so it shouldn't be specific to the PPP module? Although in what you propose further down, if I understand correctly each module would handle the reopening itself, so in that sense it would be specific to each module.

Of course, we also have the option op implementing the reopening in the modules using the pipes, so CMUX would reopen if it is connected, and L2 would reconnect if it is started, this would scale to all backends (UART ISR, TTY, UART ASYNC etc.)

Here what are you referring to exactly with L2?

Copy link
Collaborator

Choose a reason for hiding this comment

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

If we extend the modem PPP (L2) module to always automatically reopen the pipe, we should extend the same logic to the modem CMUX as well.

We can make the backends "volatile", simply closing if they encounter an internal error, and make the user reopen it if that is desired. If this is all we are doing internally within the backend's anyway, we might as well just propagate the issue to the user with the closed event.

We can also make the backends "stronger", allowing them to do whatever they need internally to recover. This will be simpler from a user's perspective. The pipes would not close themselves, they would simply try to recover until it either succeeds or the pipe is closed due to some higher level timeout.

Comment on lines 198 to 199
if (byte == expected_byte) {
ppp->receive_state++;
return true;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would prefer this approach:

static bool modem_ppp_process_is_byte_expected(uint8_t byte, uint8_t expected_byte)
        if (byte == expected_byte) {
	        return true;
        }

        LOG_DBG("Dropping byte 0x%2hhx because 0x%2hhx was expected.", byte, expected_byte);
	return false;
}

...

{
	switch (ppp->receive_state) {
	case MODEM_PPP_RECEIVE_STATE_HDR_SOF:
                if (modem_ppp_process_is_byte_expected(byte, MODEM_PPP_CODE_DELIMITER)) {
                        ppp->receive_state = MODEM_PPP_RECEIVE_STATE_HDR_FF;
                }
		break;

As this is easier to follow than hiding the new state within the helper, and using ++ instead of setting it directly. It will take up a few more bytes of ROM, but in this case the readability is more important IMO.

The SOF delimiter byte may be omitted when a frame follows another
that just ended with that byte.
The parsing used to expect that second delimiter anyway,
which resulted in PPP frames going missing.

As an additional improvement, dropped bytes as well as the length
of received frames are now (debug) logged.

Signed-off-by: Tomi Fontanilles <[email protected]>
Only log if the abort is not self-triggered,
and also print the number of bytes sent.

Signed-off-by: Tomi Fontanilles <[email protected]>
@tomi-font tomi-font force-pushed the modem_subsys_fixes_and_improvements branch from 3d55ca6 to c61a219 Compare February 14, 2024 03:43
This allows to properly drop single CMUX frames that are
too big to fit in the receive buffer, keeping track of
where they end so that following frames are received
correctly regardless of the data contents.

Signed-off-by: Tomi Fontanilles <[email protected]>
Use the proper variable.

Signed-off-by: Tomi Fontanilles <[email protected]>
This might be useful to those not familiar with how they work.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This makes the modem backends use the log level
set for the modem modules instead of the default one.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

modem_pipe_attach() can send events before returning, which could
provoke a crash as ppp->pipe, still NULL at that time, could be
used either in receiving (if the pipe had some data pending) or
in sending (if the PPP module had already been attached and had
some data to send in its transmit buffer).

ppp->pipe is now set before modem_pipe_attach().
Also, the ATTACHED_BIT is now set only after having actually attached.
And finally, the send_work is now scheduled on PIPE_EVENT_OPENED
so that data is flushed when the (closed) attached pipe is opened.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
…e 0x7E is omitted

Upstream PR: zephyrproject-rtos/zephyr#68651

The SOF delimiter byte may be omitted when a frame follows another
that just ended with that byte.
The parsing used to expect that second delimiter anyway,
which resulted in PPP frames going missing.

As an additional improvement, dropped bytes as well as the length
of received frames are now (debug) logged.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
…_ABORTED

Upstream PR: zephyrproject-rtos/zephyr#68651

Only log if the abort is not self-triggered,
and also print the number of bytes sent.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This allows to properly drop single CMUX frames that are
too big to fit in the receive buffer, keeping track of
where they end so that following frames are received
correctly regardless of the data contents.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

Use the proper variable.

Signed-off-by: Tomi Fontanilles <[email protected]>
tomi-font added a commit to tomi-font/ncs-zephyr that referenced this pull request Feb 16, 2024
…e functions

Upstream PR: zephyrproject-rtos/zephyr#68651

This might be useful to those not familiar with how they work.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This makes the modem backends use the log level
set for the modem modules instead of the default one.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

modem_pipe_attach() can send events before returning, which could
provoke a crash as ppp->pipe, still NULL at that time, could be
used either in receiving (if the pipe had some data pending) or
in sending (if the PPP module had already been attached and had
some data to send in its transmit buffer).

ppp->pipe is now set before modem_pipe_attach().
Also, the ATTACHED_BIT is now set only after having actually attached.
And finally, the send_work is now scheduled on PIPE_EVENT_OPENED
so that data is flushed when the (closed) attached pipe is opened.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
…e 0x7E is omitted

Upstream PR: zephyrproject-rtos/zephyr#68651

The SOF delimiter byte may be omitted when a frame follows another
that just ended with that byte.
The parsing used to expect that second delimiter anyway,
which resulted in PPP frames going missing.

As an additional improvement, dropped bytes as well as the length
of received frames are now (debug) logged.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
…_ABORTED

Upstream PR: zephyrproject-rtos/zephyr#68651

Only log if the abort is not self-triggered,
and also print the number of bytes sent.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This allows to properly drop single CMUX frames that are
too big to fit in the receive buffer, keeping track of
where they end so that following frames are received
correctly regardless of the data contents.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

Use the proper variable.

Signed-off-by: Tomi Fontanilles <[email protected]>
rlubos pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Feb 19, 2024
…e functions

Upstream PR: zephyrproject-rtos/zephyr#68651

This might be useful to those not familiar with how they work.

Signed-off-by: Tomi Fontanilles <[email protected]>
@tomi-font
Copy link
Collaborator Author

ping @bjarki-trackunit @ycsin @rerickson1 @fabiobaltieri @bbilas

@fabiobaltieri fabiobaltieri merged commit c7c4c80 into zephyrproject-rtos:main Feb 28, 2024
18 checks passed
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This makes the modem backends use the log level
set for the modem modules instead of the default one.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 8017cad)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

modem_pipe_attach() can send events before returning, which could
provoke a crash as ppp->pipe, still NULL at that time, could be
used either in receiving (if the pipe had some data pending) or
in sending (if the PPP module had already been attached and had
some data to send in its transmit buffer).

ppp->pipe is now set before modem_pipe_attach().
Also, the ATTACHED_BIT is now set only after having actually attached.
And finally, the send_work is now scheduled on PIPE_EVENT_OPENED
so that data is flushed when the (closed) attached pipe is opened.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 8b32ec3)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
…e 0x7E is omitted

Upstream PR: zephyrproject-rtos/zephyr#68651

The SOF delimiter byte may be omitted when a frame follows another
that just ended with that byte.
The parsing used to expect that second delimiter anyway,
which resulted in PPP frames going missing.

As an additional improvement, dropped bytes as well as the length
of received frames are now (debug) logged.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 6fa0378)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
…_ABORTED

Upstream PR: zephyrproject-rtos/zephyr#68651

Only log if the abort is not self-triggered,
and also print the number of bytes sent.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 6ae16aa)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

This allows to properly drop single CMUX frames that are
too big to fit in the receive buffer, keeping track of
where they end so that following frames are received
correctly regardless of the data contents.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 8b3d940)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
Upstream PR: zephyrproject-rtos/zephyr#68651

Use the proper variable.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 6e0bea1)
jfischer-no pushed a commit to nrfconnect/sdk-zephyr that referenced this pull request Mar 8, 2024
…e functions

Upstream PR: zephyrproject-rtos/zephyr#68651

This might be useful to those not familiar with how they work.

Signed-off-by: Tomi Fontanilles <[email protected]>
(cherry picked from commit 82f7e23)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants