Skip to content

Network traffic classfication support #6076

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 11 commits into from
Mar 27, 2018

Conversation

jukkar
Copy link
Member

@jukkar jukkar commented Feb 9, 2018

This adds simple traffic classification support in TX and RX. This means that when packet is sent or received, it can be placed to different TX or RX queue depending on priority of the packet. This PR tries to keep things simple at this stage so no fancy queueing discipline implementation.

@jukkar jukkar added area: Networking RFC Request For Comments: want input from the community labels Feb 9, 2018
@jukkar jukkar requested a review from tbursztyka February 9, 2018 13:04
Copy link
Collaborator

@tbursztyka tbursztyka left a comment

Choose a reason for hiding this comment

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

Make the traffic class whole support Kconfig based, so either we can use the current tx logic or the TC based one.

@@ -332,8 +352,10 @@ struct net_if_dev {
/** The hardware link address */
struct net_linkaddr link_addr;

/** Queue for outgoing packets from apps */
struct k_fifo tx_queue;
Copy link
Collaborator

Choose a reason for hiding this comment

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

you don't want to get rid of that, no. It should be either/or.

On 1 tx queue (the common use-case currently) k_work_queue is going to bring an overhead as soon as you'll have 2+ ifaces. I actually centralized all in 1 unique tx thread last year exactly because of that: we were having 1 thread per-iface and that was really greedy on memory constrained system for 2+ ifaces being present. It's a regression on that aspect.

Copy link
Member Author

Choose a reason for hiding this comment

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

you don't want to get rid of that, no. It should be either/or.

I disagree here, we should not have any ifdef's regarding this.

On 1 tx queue (the common use-case currently) k_work_queue is going to bring an overhead as soon as you'll have 2+ ifaces. I actually centralized all in 1 unique tx thread last year exactly because of that: we were having 1 thread per-iface and that was really greedy on memory constrained system for 2+ ifaces being present. It's a regression on that aspect.

There should be no regression in this respect by this PR. There will be only one work queue / network device so same thing as before. Note that there can be multiple network interfaces / network device, this was introduced by VLAN in #5688. Please re-review the code, imho this works quite nicely even if we have only 1 traffic class.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Check net_if.c: net_if_tx_thread is unique. It runs for all net_if arounds (so all net devices).
k_work_queue here is going to break that (for instance if you have one net_if for bt ipsp, and one for 15.4.).

Not sure how to tackle this however. Having ifdefs all around is not nice indeed.

Copy link
Collaborator

Choose a reason for hiding this comment

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

separating the traffic struct place holder as you did for ip configuration could be one solution.

@pfalcon pfalcon self-requested a review February 9, 2018 16:22
Copy link
Contributor

@dbkinder dbkinder left a comment

Choose a reason for hiding this comment

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

some recommended edits

Overview
********

The TC sample application for Zephyr will setup two virtual LAN networks and
Copy link
Contributor

Choose a reason for hiding this comment

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

s/will setup/sets up/

********

The TC sample application for Zephyr will setup two virtual LAN networks and
starts to send prioritised UDP packets to peer. The use of VLAN network is
Copy link
Contributor

Choose a reason for hiding this comment

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

prioritized (American spelling)

It might be clearer to say:

send prioritized UDP packets from one VLAN network to the other.

Building and Running
********************

A good way to run this sample is to run this TC application inside QEMU
Copy link
Contributor

Choose a reason for hiding this comment

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

How about:

 A good way to run this TC application is with QEMU

A good way to run this sample is to run this TC application inside QEMU
as described in :ref:`networking_with_qemu`.
Currently only one VLAN network (tag) is supported when Zephyr is run inside
QEMU. If using FRDM-K64F board, then multiple VLAN networks can be configured.
Copy link
Contributor

Choose a reason for hiding this comment

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

If you're using a FRDM-K64F board

routes to Zephyr.

If everything is configured correctly, you will be able to successfully execute
following commands on the Linux host.
Copy link
Contributor

Choose a reason for hiding this comment

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

the following commands

Building and Running
********************

A good way to run this sample is to run this VLAN application inside QEMU
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment:

A good way to run this VLAN application is with QEMU

routes to Zephyr.

If everything is configured correctly, you will be able to successfully execute
following commands on the Linux host.
Copy link
Contributor

Choose a reason for hiding this comment

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

the following commands

@pfalcon
Copy link
Collaborator

pfalcon commented Feb 12, 2018

Taking a look "net: core: Add array support to stack info helpers" commit. The description is:

Allow caller to create stack of arrays using NET_STACK_ARRAY_DEFINE() macro.

Nice. But why would one want to create "stack of arrays" using NET_STACK_ARRAY_DEFINE() macro? What usecase does it address? Especially that it's defined as:

+#define NET_STACK_ARRAY_DEFINE(pretty_name, name, orig, size, nmemb)	\
 +	K_THREAD_STACK_ARRAY_DEFINE(name, nmemb, size)

I.e. just renames existing functionality, duplicating macros.

The whole terminology is rather ambiguous too. Reading "stack of arrays", I can imagine anything from an abstract stack (i.e. LIFO) data structure which allows to push similarly abstract array objects on it, to a specialized IP stack which deals with networking arrays (no idea what the latter would be, but if we have storage arrays, we've got to have networking arrays too, right?). I could even imagine there's a typo and it's "array of stacks", but given the overall confusion, I wouldn't be sure.

@pfalcon
Copy link
Collaborator

pfalcon commented Feb 13, 2018

Can this be marked with explicit "Milestone" setting please, to allow for better resource allocation for the 1.11 release preparation as happening now? Thanks.

@SebastianBoe SebastianBoe removed their request for review February 13, 2018 14:04
@jukkar
Copy link
Member Author

jukkar commented Feb 13, 2018

Can this be marked with explicit "Milestone" setting please, to allow for better resource allocation for the 1.11 release preparation as happening now? Thanks.

This is definitely not for 1.11 but I do not think you really need to care about what release this PR is targeted at. Anas will assign it a milestone according to release plan.

@jukkar
Copy link
Member Author

jukkar commented Feb 13, 2018

I.e. just renames existing functionality, duplicating macros.

No exactly. If you look more carefully the code, the macro is adding some extra stuff if net-shell is enabled. Then "net stacks" command will print more information about the created work queue stacks.

@pfalcon
Copy link
Collaborator

pfalcon commented Feb 13, 2018

I.e. just renames existing functionality, duplicating macros.
No exactly. If you look more carefully the code, the macro is adding some extra stuff if net-shell is enabled. Then "net stacks" command will print more information about the created work queue stacks.

Right, and my suggestion was to add that information to the commit message. Even "it's done similarly to other functionality wrapped by net subsystem (e.g. <example1>, <example2>)" would give good insight that at least it's consistent with existing state of affairs, and "Then "net stacks" command will print more information" is even more useful.

(Otherwise yeah, I love these Monday's morning reviews (like when I posted that), it allows to emulate newcomer's perceptions more or less faithfully ;-) ).

@pfalcon
Copy link
Collaborator

pfalcon commented Feb 13, 2018

This is definitely not for 1.11 but I do not think you really need to care about what release this PR is targeted at. Anas will assign it a milestone according to release plan.

Well, I don't know, #5721 wasn't marked as 1.11, contained quite big refactors and new features, and was merged after the feature freeze date, according to https://github.com/zephyrproject-rtos/zephyr/wiki/Program-Management (there was no announcement on the mailing list, but apparently that would mean that the dates in the doc prevail). So, one may wonder about the plans re: this PR. I'm sure that Anas does the right thing, but as we have technical features to improve the visibility, would be nice to use them.

@jukkar
Copy link
Member Author

jukkar commented Feb 15, 2018

Updated according to comments.

@codecov-io
Copy link

codecov-io commented Feb 15, 2018

Codecov Report

Merging #6076 into master will increase coverage by 0.25%.
The diff coverage is 70.71%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #6076      +/-   ##
==========================================
+ Coverage   54.64%   54.89%   +0.25%     
==========================================
  Files         447      449       +2     
  Lines       42587    43317     +730     
  Branches     8040     8153     +113     
==========================================
+ Hits        23272    23780     +508     
- Misses      16084    16239     +155     
- Partials     3231     3298      +67
Impacted Files Coverage Δ
include/net/net_context.h 93.02% <ø> (ø) ⬆️
include/net/net_ip.h 62.5% <ø> (ø) ⬆️
subsys/net/lib/app/net_app.c 20.52% <ø> (ø) ⬆️
subsys/net/ip/net_private.h 35.71% <ø> (ø) ⬆️
subsys/net/ip/icmpv4.c 42.95% <0%> (-0.89%) ⬇️
subsys/net/ip/l2/ieee802154/ieee802154.c 48.14% <0%> (ø) ⬆️
subsys/net/lib/app/client.c 48.49% <0%> (-0.21%) ⬇️
subsys/net/ip/tcp.c 43.04% <0%> (ø) ⬆️
tests/net/app/src/main.c 93.25% <100%> (+0.02%) ⬆️
tests/net/iface/src/main.c 78.89% <100%> (+0.19%) ⬆️
... and 38 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f77469a...1b627ed. Read the comment docs.

@jukkar
Copy link
Member Author

jukkar commented Feb 19, 2018

Rebased because of changes in master.

@jukkar
Copy link
Member Author

jukkar commented Feb 20, 2018

Fixing merge conflicts and sanitycheck errors.

@jukkar
Copy link
Member Author

jukkar commented Feb 21, 2018

Fixing again sanity issues.

@jukkar
Copy link
Member Author

jukkar commented Mar 16, 2018

sanity fixes

@jukkar
Copy link
Member Author

jukkar commented Mar 16, 2018

more sanity fixes

@jukkar
Copy link
Member Author

jukkar commented Mar 19, 2018

rebase against master

This was referenced Mar 19, 2018
@jukkar
Copy link
Member Author

jukkar commented Mar 23, 2018

Rebase against master. Fixed various sanity issues and couple of patches removed from this PR as they were no longer needed.


/** T1 (Renewal) timer */
struct k_delayed_work t1_timer;
} __net_if_align;
Copy link
Collaborator

Choose a reason for hiding this comment

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

is it still needed though the struct is way much smaller now?

Copy link
Member Author

Choose a reason for hiding this comment

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

It seems we can leave this alignment away, at least the unit test runs fine without the huge alignment.

*
* @return 0 if ok, <0 if error
*/
int net_context_set_option(struct net_context *context,
Copy link
Collaborator

Choose a reason for hiding this comment

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

So that's basically like set_sockopt(), ok.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I made it look similar so it is easy to map to setsockopt() if needed.

@@ -170,14 +170,6 @@
__net_if_dev_end = .;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems fine to me.

However, to de-clutter net_core and net_if and avoid scattering TC stuff: maybe centralizing most of TC functions into net_tc.c would be nice

@@ -163,7 +164,7 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)

net_pkt_unref(pkt);
} else {
net_stats_update_bytes_sent(pkt_len);
net_stats_update_bytes_sent(pkt->total_pkt_len);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am missing something here but where is pkt->total_pkt_len set?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is set in net_if_queue_tx() in line 201

Copy link
Collaborator

Choose a reason for hiding this comment

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

in next patch right, not this one?

Copy link
Member Author

Choose a reason for hiding this comment

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

in next patch right, not this one?

Yes, I merged the two statistics patches to one.

@@ -228,6 +228,27 @@ struct net_stats_ipv6_mld {
net_stats_t drop;
};

#if !defined(NET_TC_COUNT)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't this be always set to, at least, 1?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is set to 1 in net_core.h, but I had some issues with this earlier. I will check if this check can be removed from net_stats.h

size_t pkt_len = net_pkt_get_len(pkt);
size_t pkt_len;
#if defined(CONFIG_NET_STATISTICS)
pkt_len = pkt->total_pkt_len;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, I guess you'll need to merge previous patch into this one. Then it's clearer.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, makes sense

@jukkar
Copy link
Member Author

jukkar commented Mar 23, 2018

New version according to comments. Also moved traffic class functionality to net_tc.c although there is not much stuff there but it is probably more easier to review now.

jukkar added 11 commits March 26, 2018 10:31
Move IP address settings from net_if to separate structs.
This is needed for VLAN support.

Signed-off-by: Jukka Rissanen <[email protected]>
Instead of always allocating both IPv6 and IPv4 address information
to every network interface, allow more fine grained address
configuration. So it is possible to have IPv6 or IPv4 only network
interfaces.

This commit introduces two new config options:
CONFIG_NET_IF_MAX_IPV4_COUNT and CONFIG_NET_IF_MAX_IPV6_COUNT
which tell how many IP address information structs are allocated
statically. At runtime when network interface is setup, it is then
possible to attach this IP address info struct to a specific
network interface. This can save considerable amount of memory
as the IP address information struct can be quite large (depends
on how many IP addresses user configures in the system).

Note that the value of CONFIG_NET_IF_MAX_IPV4_COUNT and
CONFIG_NET_IF_MAX_IPV6_COUNT should reflect the estimated number of
network interfaces in the system. So if if CONFIG_NET_IF_MAX_IPV6_COUNT
is set to 1 and there are two network interfaces that need IPv6
addresses, then the system will not be able to setup IPv6 addresses to
the second network interface in this case. This scenario might be
just fine if the second network interface is IPv4 only. The net_if.c
will print a warning during startup if mismatch about the counts and
the actual number of network interface is detected.

Signed-off-by: Jukka Rissanen <[email protected]>
Add context option support and implement PRIORITY option that
can be used to classify the network traffic to different trafic
classes according to said priority value.

Signed-off-by: Jukka Rissanen <[email protected]>
Allow caller to create array of thread stacks using
NET_STACK_ARRAY_DEFINE() macro. This allows more debug information
to be printed by "net stacks" command.

Signed-off-by: Jukka Rissanen <[email protected]>
With this commit it is possible to add priority to sent or received
network packets. So user is able to send or receive higher priority
packets faster than lower level packets.
The traffic class support is activated by CONFIG_NET_TC_COUNT option.
The TC support uses work queues to separate the traffic. The
priority of the work queue thread specifies the ordering of the
network traffic. Each work queue thread handles traffic to one specific
work queue. Note that you should not enable traffic classes unless
you really need them by your application. Each TC thread needs
stack so this feature requires more memory.

It is possible to disable transmit traffic class support and keep the
receive traffic class support, or vice versa. If both RX and TX traffic
classes are enabled, then both will use the same number of queues
defined by CONFIG_NET_TC_COUNT option.

Fixes zephyrproject-rtos#6588

Signed-off-by: Jukka Rissanen <[email protected]>
Test that we can set the priority of the network packet and
that high priority packets are sent before low priority ones.

Signed-off-by: Jukka Rissanen <[email protected]>
Add statistics for number of packets and bytes to each traffic
class. Print this information in net-shell.

Also make sure that we do not calculate total packet length many
times. So calculate network packet total length once and then use
that value instead of calculating it many times in a row.

Signed-off-by: Jukka Rissanen <[email protected]>
The "net stacks" command was printing TX or RX thread values so
that it was not possible to use the values in debugging easily.
Add traffic class value when printing the info so that it is
easy to see what TX or RX queue is doing.

Signed-off-by: Jukka Rissanen <[email protected]>
This demostrates how to classify the network traffic when sending
data. The application will create similar functionality as
echo-client so user can use echo-server running in remote host to
test this sample application.

Signed-off-by: Jukka Rissanen <[email protected]>
This avoids this crashing in qemu_x86

***** Stack Check Fail! *****
Current thread ID = 0x004015e0
Faulting segment:address = 0x0008:0x00003593
eax: 0x0041e930, ebx: 0x00000000, ecx: 0x004170bc, edx: 0x0000dff8
esi: 0xffffffff, edi: 0x0041e930, ebp: 0x00417010, esp: 0x00416ffc
eflags: 0x216
Fatal fault in essential thread! Spinning...
Terminate emulator due to fatal kernel error

Signed-off-by: Jukka Rissanen <[email protected]>
There can be lot of traffic class threads and each will have
their own stacks. This can trigger issue when traversing the
stacks list in "net stacks" shell command. To overcome this issue,
we need to align each net_stack_info struct by 32 bytes. This is
the same issue that happened with net_if earlier.

Signed-off-by: Jukka Rissanen <[email protected]>
@jukkar
Copy link
Member Author

jukkar commented Mar 26, 2018

@nashif could you force-apply this one as sanity is complaining non-issue and I cannot merge this?

@nashif nashif merged commit f947439 into zephyrproject-rtos:master Mar 27, 2018
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.

6 participants