Skip to content

net: added ng_udp implementation#2430

Merged
miri64 merged 3 commits intoRIOT-OS:masterfrom
haukepetersen:ng_udp
Apr 26, 2015
Merged

net: added ng_udp implementation#2430
miri64 merged 3 commits intoRIOT-OS:masterfrom
haukepetersen:ng_udp

Conversation

@haukepetersen
Copy link
Copy Markdown
Contributor

this PR depends on many other ng_ PRs, will detail them out once this PR gets in a state of being testable/reviewable. I will try to provide a first approach for a socket implementation to make this code better understandable.

While writing this code, I came across some issues we should think about:
1. how do we handle the checksum calculation when sending data and the src address is still unknown?
2. where do we get the source port from, if not using sockets but talking directly to UDP via NETAPI?

UPDATE: This implementation is now ready for testing

UPDATE 2: rebased on #2801

@haukepetersen haukepetersen added State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet Area: network Area: Networking NSTF State: waiting for other PR State: The PR requires another PR to be merged first labels Feb 10, 2015
@miri64 miri64 mentioned this pull request Feb 10, 2015
36 tasks
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since there should only be one UDP thread it might be worth thinking about making this public.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Feb 11, 2015

  1. how do we handle the checksum calculation when sending data and the src address is still unknown?

I'm still not 100% sure, but thinking about it I came to 2 different solutions:

  1. as we already discussed: Implementing callbacks that are called after the IPv6 module found the corresponding source address to a given destination address.
  2. a netreg_build_header(nettype_t type, void *src, size_t src_len, void* dest, size_t dest_len, size_t payload_len) where if src == NULL || src_len == 0 the source address will be selected by the corresponding type function. If this is called before the next header calculates its checksum, there is no problem, because everything needed for the Internet checksum is there
  1. where do we get the source port from, if not using sockets but talking directly to UDP via NETAPI?

I more or less assumed the user application is setting this in the UDP header, also using some netreg_build_header-function.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since port 0 is reserved, we maybe should use uint32_t as demux type and go to 0x10000 for ALL.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think exactly because it is reserved, we can use the 0 internally for "everyone who is interested in UDP general"...
And the pkt->type in the line above would be IP...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And the pkt->type in the line above would be IP...

Ah, sure… but in context of #2430 (comment): can we be sure of this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think exactly because it is reserved, we can use the 0 internally for "everyone who is interested in UDP general"...

Aren't we then exceptionally vulnerable against port 0 attacks?

@LudwigKnuepfer
Copy link
Copy Markdown
Member

Usually the network layer decides the source port. As the network layer in question is IP, it should be the decision of the IP module how to enable this (I suggest a uint16_t ip_get_free_source_port() function).

Usually the transport layer decides the source port. As the transport layer in question is UDP, it should be the decision of the UDP module how to enable this (I suggest a uint16_t udp_get_free_source_port() function).

@miri64
Copy link
Copy Markdown
Member

miri64 commented Feb 11, 2015

Why does the network layer does this oO?

@LudwigKnuepfer
Copy link
Copy Markdown
Member

Because I'm stupid ;) (comment updated)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shouldn't the next header be set here somewhere? At least that's what the beginning of this function implies, where you start searching for the UDP header and stop if you don't find it. If yes, how do we get the length and the type of the next header?
Or do we pre-parse the packet in the link-layer/driver? If yes: why? The link-layer/driver then has to have knowledge of all header types, or it must be stored somewhere so the driver can handle it. And I'm wondering why we do it so complicated.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Feb 11, 2015

Usually the transport layer decides the source port. As the transport layer in question is UDP, it should be the decision of the UDP module how to enable this (I suggest a uint16_t udp_get_free_source_port() function).

Can the UDP port change in "one transmission"? (since one transmission in UDP is normally exactly one packet, I think I know the answer :D)

@LudwigKnuepfer
Copy link
Copy Markdown
Member

What do you mean with "one transmission"? At least for IPv4 you can have several fragmented IP packets for the same UDP datagram.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Feb 11, 2015

I'm not sure either. I guess I meant a stream of data (yes I know there are streams in UDP)… Was more or less a brainfart.

@cgundogan
Copy link
Copy Markdown
Member

Can the UDP port change in "one transmission"? (since one transmission in UDP is normally exactly one packet, I think I know the answer :D)

Since the Src[Port:IP]-Dst[Port:IP] tuple is an End-To-End connection, the port cannot change for "one transmission". However, after this transmission, a new Src[Port:IP]-Dst[Port:IP] tuple can be generated aka a new Socket can be created to serve as the new communication endpoint :)

@cgundogan
Copy link
Copy Markdown
Member

What do you mean with "one transmission"? At least for IPv4 you can have several fragmented IP packets for the same UDP datagram.

Since the fragmentation is below UDP, the port is fixed

@LudwigKnuepfer
Copy link
Copy Markdown
Member

Sure, but can it be reused for a new "connection" to the same destination in parallel?

@cgundogan
Copy link
Copy Markdown
Member

Sure, but can it be reused for a new "connection" to the same destination in parallel?

No, once fixed to a socket a port cannot be reused if the respective socket was not closed. And a good implementation should not take the port immediatly after closing, but choose a random one thereafter

@LudwigKnuepfer
Copy link
Copy Markdown
Member

That is why we need to keep track of the (source) ports in use. I thought the respective layer was a good point to do so.

@cgundogan
Copy link
Copy Markdown
Member

That is why we need to keep track of the source ports in use. I thought the respective layer was a good point to do so.

👍

@OlegHahm
Copy link
Copy Markdown
Member

how do we handle the checksum calculation when sending data and the src address is still unknown?

I recently thought about this and came to the conclusion that it seems actually the most sensible to me to do the upper layer checksum calculation directly in IP itself. IP has to know about the upper layer anyway and it knows the correct source address, so there's no advantage of doing it in the upper layer (and having a probability that is has to be done again in IP).

@miri64
Copy link
Copy Markdown
Member

miri64 commented Feb 13, 2015

I recently thought about this and came to the conclusion that it seems actually the most sensible to me to do the upper layer checksum calculation directly in IP itself.

So we do the callback solution. Will find something in my IPv6 implementation :-)

@OlegHahm
Copy link
Copy Markdown
Member

Actually, I was not talking about callbacks. Seems overkill to me, if the same function is called for every upper layer anyway.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I always think these macros are kind of redundant. The same value can be retrieved with sizeof(ng_udp_hdr_t) (and it is more portable).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm staying with my redundancy argument. :D

@haukepetersen haukepetersen removed the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Apr 24, 2015
@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 24, 2015

ACK if travis is happy.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

lets merge this as is (otherwise it gets a neverending story) and then feel free to PR that change. Sound reasonable?

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 24, 2015

👍

@sgso
Copy link
Copy Markdown
Contributor

sgso commented Apr 24, 2015

Sure, I didn't intend to stall anything. I have been using ng_udp for about a week now in mostly this form and it worked very well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doxygen has a problem finding the reference to NG_NETTYPE_UDP, since MODULE_NG_UDP in its scope is not defined.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 24, 2015

ERROR: The following new files generate doxygen warnings:
sys/include/net/ng_udp.h

Solutions for that:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

#ifdef __cplusplus
}
#endif

missing

@haukepetersen
Copy link
Copy Markdown
Contributor Author

fixed issues (doxygen, indention, cplusplus closing bracket, param checking when sending) and rebased.

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 26, 2015

Re-ACK

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 26, 2015

(please SQUASH)

@haukepetersen
Copy link
Copy Markdown
Contributor Author

squashed

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

cppcheck is complaining about len not being used for the #ifndef MODULE_NG_IPV6 build-path.

sys/net/transport_layer/ng_udp/ng_udp.c:71: style (unreadVariable): Variable 'len' is assigned a value that is never used.

we can fix this after merge, or you add a (void)len to this case and squash.

@haukepetersen
Copy link
Copy Markdown
Contributor Author

now cppcheck shouldn't complain anymore

@miri64
Copy link
Copy Markdown
Member

miri64 commented Apr 26, 2015

It doesn't => finally go!

miri64 added a commit that referenced this pull request Apr 26, 2015
net: added ng_udp implementation
@miri64 miri64 merged commit 07de380 into RIOT-OS:master Apr 26, 2015
@haukepetersen
Copy link
Copy Markdown
Contributor Author

this was an easy one :-)

@haukepetersen haukepetersen deleted the ng_udp branch April 27, 2015 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: network Area: Networking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants