Skip to content

Conversation

@rbtchc
Copy link
Contributor

@rbtchc rbtchc commented Aug 9, 2017

Implement firmware push and pull functions

  • Add a state machine for handling the firmware update process (both push & pull)
  • Use http_parser to parse URI passed from the server

@jukkar jukkar requested a review from mike-scott August 9, 2017 08:44
@jukkar jukkar added the net label Aug 9, 2017
Copy link
Member

Choose a reason for hiding this comment

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

Please put space before and after the '+'

Copy link
Member

Choose a reason for hiding this comment

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

Please put empty line before the comment, looks a bit better that way.

Copy link
Member

Choose a reason for hiding this comment

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

spaces missing before and after +

Copy link
Member

Choose a reason for hiding this comment

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

same issue here with '+', can you do a search and fix all of these in one go

Copy link
Member

Choose a reason for hiding this comment

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

empty line after }

Copy link
Member

Choose a reason for hiding this comment

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

empty line after }

Copy link
Member

Choose a reason for hiding this comment

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

add spaces before and after '*'

Copy link
Member

Choose a reason for hiding this comment

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

empty line after }

Copy link
Contributor

Choose a reason for hiding this comment

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

which is fine here

Copy link
Member

Choose a reason for hiding this comment

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

empty line after }

Copy link
Member

Choose a reason for hiding this comment

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

I looks like you have extra empty line between variable declarations above.

Copy link
Contributor

Choose a reason for hiding this comment

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

In reality this is just using the url parser, so wonder if we should split that out of the http later.

Size is also increased quite a bit by just building http_parser, which could probably be optimised if we could just split the url parse part of it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will add a patch to separate the URL parsing from header parsing.

Copy link
Contributor

Choose a reason for hiding this comment

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

Easier to read if using "if (!IS_ENABLED(CONFIG_NET_IPV6)" instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Same here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't you also call NOTIFY_OBSERVER(5, 0, 3)?

Copy link
Contributor

Choose a reason for hiding this comment

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

Same, also missing NOTIFY_OBSERVER.

Copy link
Contributor

Choose a reason for hiding this comment

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

Spec: "Writing an empty string to Package Resource or to Package URI Resource, resets the Firmware Update State Machine: the State Resource value is set to Idle and the Update Result Resource value is set to 0."

So we should reset state machine even if state is != DOWNLOADED, by checking for data_len outside the if/else block.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From LwM2M specification figure 29, it looks like it only reset to state idle when it's currently at state downloaded and an empty package URI/resource is written.
That's why I put the state == STATE_DOWNLOADED check here.

If we reset the state machine at any state, then we have to do (1) cancel the firmware download and (2) cancel the firmware update.

I'm not sure which is the correct behavior. But from my point of view, it's simpler if we only accept the state machine reset at DOWNLOADED state.

Copy link
Contributor

Choose a reason for hiding this comment

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

Figure 29 seems to be a possible implementation indeed, but that doesn't cover the cancel update case, which is why my interpretation was more to reset at any point in time, at any state.

Looks like something to ask oma for clarification.

Copy link
Contributor

Choose a reason for hiding this comment

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

Would also be nice to add similar checks to package_uri_write_cb.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm afraid that I did not catch your point.
What kind of checks do I have to add to package_uri_write_cb?

Copy link
Contributor

Choose a reason for hiding this comment

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

At least to reset the state machine if there is an empty write.

Copy link
Contributor

Choose a reason for hiding this comment

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

More natural to read if "state == STATE_DOWNLOADED".

Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably define a set of possible return codes here, as an error is not necessarily integrity failed (another possible value is just simply firmware update failed, but it could also return unsupported package type).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good suggestion.
I will map -EINVAL to RESULT_INTEGRITY_FAILED and others to RESULT_UPDATE_FAILED.
From LwM2M specification figure 29, it seems there are only three acceptable results which are RESULT_SUCCESS, RESULT_INTEGRITY_FAILED and RESULT_UPDATE_FAILED.

Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be RESULT_CONNECTION_LOST instead?

Copy link
Contributor

Choose a reason for hiding this comment

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

add an empty line before the for ()

Copy link
Contributor

Choose a reason for hiding this comment

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

break a line after a } always (unless it's another } etc..)

Copy link
Contributor

Choose a reason for hiding this comment

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

remove that empty line

Copy link
Contributor

Choose a reason for hiding this comment

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

indent seems wrong here, & should be below f

Copy link
Contributor

Choose a reason for hiding this comment

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

which is fine here

Copy link
Contributor

Choose a reason for hiding this comment

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

break a line before for () (see my previous comment about if/for/while etc..)

Copy link
Contributor

Choose a reason for hiding this comment

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

Since you removed the useless else {}, you could do:

if (r) {
goto error;
}

and thus all the code block below could be indented back. Nicer to read, less imbrication of if/else etc...

Copy link
Contributor

Choose a reason for hiding this comment

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

here would be you error label

Copy link
Contributor

Choose a reason for hiding this comment

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

usually, in net stack, we try to have declaration with assignment as first lines, then the rest. So I would reverse the order here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Delete the debug message directly

Copy link
Contributor

Choose a reason for hiding this comment

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

declare inbuf and insize before len

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like we should be grouping all of the variables of the same types on a line. Same with the u16_t below.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's actually ok to do both. No need to enforce grouping

Copy link
Contributor

Choose a reason for hiding this comment

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

Same with grouping up variables of the same type here.

Copy link
Contributor

Choose a reason for hiding this comment

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

These 2 functions are only available if CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT is enabled.

Copy link
Contributor

Choose a reason for hiding this comment

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

Are we sure that we want to assert here (even if CONFIG_ASSERT is enabled)? That seems a bit harsh for passing in an invalid state. Maybe ignore and print an error message? Especially since this is exposed in application code.

Copy link
Contributor

Choose a reason for hiding this comment

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

Once again, I'm not sure an assert is the right behavior here. Consider a strongly worded error message?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will replace assert w/ error messages.

Copy link
Contributor

@mike-scott mike-scott Aug 10, 2017

Choose a reason for hiding this comment

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

I feel like lwm2m_firmware_set_update_state() and lwm2m_firmware_set_update_result() are performing data_validation and then a followup call to set related data. In discussions with @rsalveti we had plans to add a new data_validation_callback for data elements which would be called prior to assigning a value to the data element.

This would clean up several issues that I'm seeing here:

  • You're creating specific data element based functions to control how a data element is set. This doesn't scale well over time.
  • These functions in turn trigger related data element values to be set.

Instead, if we had a data_validation callback which could be assigned to a data element. The validation could be performed there (returning non-zero value when an invalid value is found). And if a valid value was found the follow up assignments of update_state could be handled in a post_write callback of update_result, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup, it looks like a good idea if we could have a data validation callback when application want to update the value of the object resources. (I'm assuming that you are talking about adding callback to lwm2m_engine_set_xxx() functions.)
Do I create a ticker on JIRA for tracking it or ?

@rbtchc rbtchc force-pushed the firmware_update branch 3 times, most recently from 818d04c to 4e35cf1 Compare August 10, 2017 14:54
@rsalveti
Copy link
Contributor

@rbtchc while we get all the firmware update review done, would you mind breaking up the fixes you have in a separated pull request? At least "net: lwm2m: fix registration content format and use plain/text", "net: lwm2m: save accept format in observe_node_data" and "net: lwm2m: fix erroneous TLV write", as they are good fixes that could be merged soon.

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 11, 2017

Here are the summary of the changes I made.

  1. Create separate PRs (net: lwm2m: fix erroneous TLV write #1089, net: lwm2m: fix registration content format and use plain/text #1090, net: lwm2m: save accept format in observe_node_data #1091) for patches independent to firmware push/pull
  2. Correct the coding style
  3. Add b84b6f45a3a92c0aa6ef34b039792bff9ebe5356 for a smaller URL only parser
  4. Add NOTIFY_OBSERVER() call when update_result/update_state is updated. Replace assert w/ error message

TODO

  1. Clarify whether firmware update can be cancelled at any state or DOWNLOADED state only
  2. File a ticket JIRA for implement data_validation callback(?)

@mike-scott
Copy link
Contributor

JIRA for data validation callback is here: https://jira.zephyrproject.org/browse/ZEP-2500

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 11, 2017

Raised firmware update cancellation question on OpenMobileAlliance/OMA_LwM2M_for_Developers#219

Do we need to wait for the clarification before we merge the patches?
Or perhaps I could file a JIRA ticket to track and patch the behavior when clarification is made.

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 18, 2017

@jukkar @tbursztyka @mike-scott @rsalveti
Please take a look at the updated patches and let me know if there are any unaddress issues.
Thanks.

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 20, 2017

Rebase and resolve code conflicts according to the change dcb80f7
Diff: https://hastebin.com/egiliqigiv.hs

@pfalcon
Copy link
Contributor

pfalcon commented Aug 20, 2017

Rebase and resolve code conflicts according to the change dcb80f7

Yep, sorry guys, I meant to ping you about it, seeing that lwm2m code uses, but that slipped. @mike-scott , @rsalveti, @mbolivar FYI

@mike-scott
Copy link
Contributor

@rbtchc Testing this PR again today / tomorrow and I'll respond back. But @jukkar may want to discuss the Kconfig option to enable HTTP parser only.

Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

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

I am ok with the HTTP URL parser only option, I was actually needing something like this myself.

Copy link
Member

Choose a reason for hiding this comment

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

Could add the config option in comment here as there are almost 200 lines inside this define block.
So something like this:
#endif /* !CONFIG_HTTP_PARSER_URL_ONLY */

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps just say here "This option only enables URL parser of the http_parser library."

Copy link
Member

Choose a reason for hiding this comment

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

Add the /* !CONFIG_HTTP_PARSER_URL_ONLY */ here

Copy link
Member

Choose a reason for hiding this comment

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

Same here

Copy link
Member

Choose a reason for hiding this comment

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

And here

Copy link
Member

Choose a reason for hiding this comment

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

And here

Copy link
Member

Choose a reason for hiding this comment

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

And here.

Copy link
Member

Choose a reason for hiding this comment

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

You need to add "select HTTP_PARSER" here too as when doing "select" in Kconfig, it will not recursively select other options.

Copy link
Member

Choose a reason for hiding this comment

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

What about my comment here, is the HTTP_PARSER option selected by some other way? What I mean by this is if you select HTTP_PARSER_URL_ONLY here, it will not select HTTP_PARSER automatically (at least that is how Kconfig worked before) i.e., recursive "select" is not implemented. But it might be that the HTTP_PARSER is selected automatically by some other mean in which case my concern is moot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did add "select HTTP_PARSER" at subsys/net/lib/http/Kconfig#L68 when config HTTP_PARSER_URL_ONLY is selected.
In this way, when LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT is selected, both HTTP_PARSER & HTTP_PARSER_URL_ONLY will be selected as well.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, I missed that.

Copy link
Member

Choose a reason for hiding this comment

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

Isn't there now a compile error if you disable IPv6 as the any_addr6 is only found if IPv6 is enabled?

Copy link
Member

Choose a reason for hiding this comment

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

And same thing for IPv4

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 21, 2017

Update according to @jukkar 's comment. Here's the diff: https://hastebin.com/vovevumeca.cs

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 21, 2017

Update to take care of error handling when failing to add block1 option to the out packet
Diff: https://hastebin.com/upupiguqub.cs

Copy link
Member

Choose a reason for hiding this comment

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

BTW, I just submitted #1198 which provides net_ipaddr_parse() function that converts a IPv{4|6} address string to struct sockaddr. That function could probably be used here in order to save some memory, this is just something that could be considered here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good to know. I will apply those changes to the PR when they are merged.

jukkar
jukkar previously approved these changes Aug 24, 2017
@mike-scott
Copy link
Contributor

@rbtchc I hate to ask, but do you think this PR could be rebased on top of #1255 ?

@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 29, 2017

@mike-scott sure

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if we should always check for data_len == 0 even when state is not downloading. That is just to protect the code flow as the state can be updated via other parts of the code (even when it shouldn't).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just to confirm. Are you suggesting that we always check if "data_len == 0" and reset the state back to default?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, my concern is what would happen when data_len == 0 but state is not what we expect to be (simply because state can be changed independently).

Copy link
Contributor

Choose a reason for hiding this comment

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

Same here (data_len == 0).

Copy link
Contributor

Choose a reason for hiding this comment

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

Mind also adding a error message here in case this gets called when state == DOWNLOADING.

Copy link
Contributor Author

@rbtchc rbtchc Aug 30, 2017

Choose a reason for hiding this comment

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

Will print out an error message here.

rbtchc added 3 commits August 31, 2017 16:16
1. Parse firmware pull URI
2. Add lwm2m_firmware_get/set_update_cb() for applicaiton to register
   callback. This is because we want to check the update_state before
   we pass to the application
3. Add lwm2m_firmware_get/set_update_result() and
   lwm2m_firmware_get/set_update_stat() to manage the state trasnition
   as well as the sanity check

Signed-off-by: Robert Chou <[email protected]>
OPAQUE resource type might/might not have data_ptr/data_len setup
depending on the implementation. This introduces an issue that when
an OPAQUE resource is written from the server side, the one w/ none
setup will not be able to pass data to post_write_cb()

Modify to setup data_ptr/data_len as incoming buffer and buffer size

Signed-off-by: Robert Chou <[email protected]>
1. Add handling block1 option in handle_request(). The basic idea is
   to declare structure block_context at compiled time and use "token"
   as a key to pick up the on-going block cotext. It should be able to
   support multiple blockwise transfer concurrently
2. Use write callback implemented in lwm2m_obj_firmware to deal w/ the
   update state transition and than call the callback registered by the
   application
3. move default_block_size to lwm2m_engine.c to share btw lwm2m_engine
   and lwm2m_obj_firmware_pull

Signed-off-by: Robert Chou <[email protected]>
@rbtchc
Copy link
Contributor Author

rbtchc commented Aug 31, 2017

Update to address @rsalveti 's concerns. Diff: https://hastebin.com/exixuzaxex.cs

  1. Reset update state / result to default when empty string is received by either /5/0/0 or /5/0/1
  2. Remove TODO comment
  3. Response -EPERM (mapped to 4.05) method not allowed when executing 5/0/2 (update) but state is not downloaded
  4. Fix unable to compile when option CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT=n

@mike-scott
Copy link
Contributor

Thanks for the update @rbtchc I'll try and fold these changes into #1255 (using this as a holding PR for 1.10 changes for now)

@mike-scott
Copy link
Contributor

Probably safe to close this PR. I have rebased versions of these patches included in this PR: #4208

@rbtchc
Copy link
Contributor Author

rbtchc commented Oct 7, 2017

Close as @mike-scott mentioned

@rbtchc rbtchc closed this Oct 7, 2017
nagineni pushed a commit to nagineni/zephyr that referenced this pull request Nov 20, 2017
…rproject-rtos#1049)

It was checking the length of the filename against the maximum
JS file length. Native modules can be longer and were failing
because of this.

Signed-off-by: Brian J Jones <[email protected]>
MariuszSkamra added a commit to MariuszSkamra/zephyr that referenced this pull request Jun 8, 2022
This fixes Bluetooth logs that were not sent over RTT.
Minor cleanup has been made to limit the number of ifdefs.

> ACL Data RX: Handle 0 flags 0x02 dlen 11      zephyrproject-rtos#1049 83.117000
      ATT: Handle Value Indication (0x1d) len 6
        Handle: 0x0003
          Data: 0100ffff
= bt: bt_att: Unhandled ATT code 0x1d                 83.117100
> HCI Event: Disconnect Complete (0x05) plen 4  zephyrproject-rtos#1050 84.247700
        Status: Success (0x00)
        Handle: 0
        Reason: Remote User Terminated Connection (0x13)

Signed-off-by: Mariusz Skamra <[email protected]>
MariuszSkamra added a commit to codecoup/zephyr that referenced this pull request Jun 8, 2022
This fixes Bluetooth logs that were not sent over RTT.
Minor cleanup has been made to limit the number of ifdefs.

> ACL Data RX: Handle 0 flags 0x02 dlen 11      zephyrproject-rtos#1049 83.117000
      ATT: Handle Value Indication (0x1d) len 6
        Handle: 0x0003
          Data: 0100ffff
= bt: bt_att: Unhandled ATT code 0x1d                 83.117100
> HCI Event: Disconnect Complete (0x05) plen 4  zephyrproject-rtos#1050 84.247700
        Status: Success (0x00)
        Handle: 0
        Reason: Remote User Terminated Connection (0x13)

Signed-off-by: Mariusz Skamra <[email protected]>
carlescufi pushed a commit that referenced this pull request Jun 9, 2022
This fixes Bluetooth logs that were not sent over RTT.
Minor cleanup has been made to limit the number of ifdefs.

> ACL Data RX: Handle 0 flags 0x02 dlen 11      #1049 83.117000
      ATT: Handle Value Indication (0x1d) len 6
        Handle: 0x0003
          Data: 0100ffff
= bt: bt_att: Unhandled ATT code 0x1d                 83.117100
> HCI Event: Disconnect Complete (0x05) plen 4  #1050 84.247700
        Status: Success (0x00)
        Handle: 0
        Reason: Remote User Terminated Connection (0x13)

Signed-off-by: Mariusz Skamra <[email protected]>
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.

7 participants