Re: RFC: BSD Socket (like) API

Paul Sokolovsky

Hello Gil,

Thanks for the reply, please let me both agree and not agree to some

On Mon, 27 Mar 2017 16:40:30 -0700
Gil Pitney <> wrote:

I think application developers would prefer to see ONE simple,
standard API for networking on which to build all higher level
networking protocols and applications.
I'm on their side, but such application developers will quickly see
that they can't use "ONE simple, standard API" on the smallest of
devices. I guess small footprint and resource usage is a distinctive
trait of Zephyr, and we should not compromise it. So, let there be
layering, and let different application developers choose what they

However, I understand the Zephyr IP stack needs to target highly
memory constrained systems, and the decision has been made that the
standard POSIX APIs are just not suitable.
Ack, we in agreement here, per above.

So, now the concern is that we are left with two "BSD-like" APIs doing
essentially the same thing, one purporting to use less data space,
though shifting more complexity and code-space up to the application,
and allowing applications to be written one of two (or both?) ways.
Let me start with the latter - I may imagine a particular application
will want to use either "BSD Socket like API" or "native Zephyr API",
but not both at the same time. If this idea is sound, it may help us
to better structure additions for new API (make them less (least)

Now about terminology - I avoid "BSD-like" term, and specifically call
new API to be developed "BSD Socket like API", that's long but as much
unambiguous as I could come up with. "like" part is to set the
expectations right, so nobody would get an idea that one will be able
to build Chromium against Zephyr 1.8, or something like that ;-). I
wouldn't call current native API "BSD Sockets like API" at all, because
the definitive trait of BSD Sockets is pull-stile API, which native API

That all still may be too subtle and too much word-playing, especially
for someone who's not in all of this context, so ideas for better naming
are welcome, but the basic idea is that current API is "native", while
one to be developed is "BSD Sockets like".

So, then, a couple recommendations:

1) Let's start with the standard POSIX APIs:

and devolve from there with a list of exceptions with rationale for
why Zephyr cannot or should not comply with the standard.

For example, APIs dealing with file descriptors are reasonable
exceptions, because Zephyr does not support a POSIX file system.
So, you propose top-bottom approach, whereas I explicitly proposed
bottom-top approach: let's start with finding the most divergent
feature from the current native API, let's try to implement it in terms
of existing API, and see what it takes to do that. Then select next
feature, rinse and repeat. IMHO, that's much better for initial
prototyping phase and matches current development model of Zephyr,
where we extensively grow featureset. We certainly will need to pause
at some point and match what we have against spec some time later.

I'd avoid terms like "BSD-like", as the current Zephyr APIs are
arguably "BSD-like" to some degree - just not standard.
Per above, and per my outlook, it's not, and can be as well called
"native". I'll be happy to adopt any other naming, as long as it makes
matters less confusing.

2) Enable TCP/IP offload from the socket layer.

The TI CC3220 completely offloads the TCP/IP stack onto a
co-processor, by marshalling BSD socket API calls over SPI to the
network coprocessor.

The current NET_OFFLOAD support in the Zephyr IP stack provides a hook
to call an offload engine. For the TI CC3220, this mapping of
net_context APIs to BSD socket APIs adds some overhead and code

However, now that we're talking about adding a BSD socket layer to
Zephyr, offloading directly from the socket layer would be more
natural (something similar to the MyNewt solution, as pointed out by

Otherwise, we have to map BSD sockets -> net_context -> BSD sockets,
with all the required extra overhead of data structures, sync
primitives, and server thread(s) to handle mapping between the two
different networking API usage models.

By doing so, I understand we could potentially bypass the (TBD)
routing table. But that is a use case, AFAIK, not really needed for
the CC3220 typical client IoT node devices.

Then again, the POSIX socket standard specifies that sockets shall
support routing, so maybe we can just make that work somehow?

On 27 March 2017 at 06:27, Paul Sokolovsky
<> wrote:
Hello Jukka,

On Mon, 27 Mar 2017 12:37:40 +0300
Jukka Rissanen <> wrote:

The current approach is that we value lightweight nature of
Zephyr, and
looking towards finding a minimal set of changes (additions) to
BSD Sockets *like* API to Zephyr.
The definition of what is BSD Socket *like* system seems to differ
from person to person.
That's true, and the reason why I informally proposed the
"process-wise" definition above: "minimal set of changes
(additions) to provide BSD Sockets *like* API to Zephyr."

For me the current net_context API in Zephyr
is quite BSD socket like, meaning that the API provides similar
functions that are found in BSD socket API like open, close, bind,
connect, accept etc. So it is quite easy to port the application in
this respect.
That's also true, and I right from the start got a habit to call
net_context "a socket". The API calls you mention are all indeed
work (likely almost) the same. The big difference comes with recv()
call - whereas BSD Sockets API has it conventionally pull-style, in
Zephyr it's push-style, where data gets delivered to an app via a
callback. That's one single feature which makes porting 3rd-party
applications complicated and cumbersome.

The bigger difference between BSD socket API and Zephyr net_context
API is:
* net_context API uses net_buf to pass data. The net_buf does not
provide linear memory but data needs to be partitioned when sending
and read in chunks when receiving. We have helpers defined in
nbuf.h for handling reading/writing data in this case. The issue
with linear memory case is that it uses much more memory as we
need to be prepared to receive at least 1280 byte size chunks of
data (IPv6 min data packet size).
Right. And that part is covered by BSD Sockets' own API - the data
is passed via app-owned buffers, not system-owned buffers. That
means that by definition, BSD Sockets don't support zero-copy
operation. While an obvious drawback, it has its positive sides to,
like it offers possibility for better system vs app separation for

* The net_context is asynchronous and caller needs to have
callbacks defined. The BSD socket API is synchronous. The
net_context can be used in synchronous way so this is a smaller
issue imho.
As you may already noticed, I prefer to call this distinction
"push-style vs pull-style", because it pinpoints the problem
better. The net_context used "in synchronous way" doesn't provide
BSD Sockets behavior for receives. For that to work, incoming (but
unprocessed) data needs to be queue *per socket*, until an app
requests it. And indeed, that's the one big initial change I would
need to make.

Having a BSD socket API on top of net_context will use more memory
so if one is concerned about memory consumption, then using native
API should be preferred.
+100, BSD Sockets like API is not a replacement for native API,
only a helper to port existing applications (mostly libraries in the
real-world cases, I may imagine, but only practice will tell how
people will use it).


Best Regards,
Paul | Open source software for ARM SoCs
Follow Linaro:!/linaroorg -
Zephyr-devel mailing list

Best Regards,
Paul | Open source software for ARM SoCs
Follow Linaro:!/linaroorg -

Join to automatically receive all group messages.