samples/net: Switch zperf sample to new net_context API

No need to build the net_pkt, just send the buffer directly.

Let's reuse already parsed ip/proto headers as well.

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2019-03-13 09:16:42 +01:00 committed by Anas Nashif
commit fa58d1e6ce
6 changed files with 116 additions and 247 deletions

View file

@ -19,13 +19,16 @@ LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);
static struct session sessions[SESSION_PROTO_END][SESSION_MAX];
/* Get session from a given packet */
struct session *get_session(struct net_pkt *pkt, enum session_proto proto)
struct session *get_session(struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr,
enum session_proto proto)
{
struct session *active = NULL;
struct session *free = NULL;
struct in6_addr ipv6 = { };
struct in_addr ipv4 = { };
struct net_udp_hdr hdr, *udp_hdr;
struct net_udp_hdr *udp_hdr;
int i = 0;
u16_t port;
@ -39,19 +42,15 @@ struct session *get_session(struct net_pkt *pkt, enum session_proto proto)
return NULL;
}
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
printk("Invalid UDP data\n");
return NULL;
}
udp_hdr = proto_hdr->udp;
/* Get tuple of the remote connection */
port = udp_hdr->src_port;
if (net_pkt_family(pkt) == AF_INET6) {
net_ipaddr_copy(&ipv6, &NET_IPV6_HDR(pkt)->src);
net_ipaddr_copy(&ipv6, &ip_hdr->ipv6->src);
} else if (net_pkt_family(pkt) == AF_INET) {
net_ipaddr_copy(&ipv4, &NET_IPV4_HDR(pkt)->src);
net_ipaddr_copy(&ipv4, &ip_hdr->ipv4->src);
} else {
printk("Error! unsupported protocol %d\n",
net_pkt_family(pkt));

View file

@ -58,7 +58,10 @@ struct session {
struct zperf_server_hdr stat;
};
struct session *get_session(struct net_pkt *pkt, enum session_proto proto);
struct session *get_session(struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr,
enum session_proto proto);
struct session *get_tcp_session(struct net_context *ctx);
void zperf_session_init(void);
void zperf_reset_session_stats(struct session *session);

View file

@ -70,7 +70,7 @@ static void tcp_received(struct net_context *context,
session->counter++;
if (pkt) {
session->length += net_pkt_appdatalen(pkt);
session->length += net_pkt_remaining_data(pkt);
}
if (pkt == NULL && status == 0) { /* EOF */

View file

@ -51,43 +51,19 @@ void zperf_tcp_upload(const struct shell *shell,
do {
int ret = 0;
struct net_pkt *pkt;
struct net_buf *frag;
u32_t loop_time;
/* Timestamps */
loop_time = k_cycle_get_32();
last_loop_time = loop_time;
pkt = net_pkt_get_tx(ctx, K_FOREVER);
if (!pkt) {
shell_fprintf(shell, SHELL_ERROR,
"Failed to retrieve a packet\n");
break;
}
frag = net_pkt_get_data(ctx, K_FOREVER);
if (!frag) {
net_pkt_unref(pkt);
shell_fprintf(shell, SHELL_ERROR,
"Failed to retrieve a fragment\n");
break;
}
net_pkt_frag_add(pkt, frag);
/* Fill in the TCP payload */
net_pkt_append(pkt, sizeof(sample_packet),
sample_packet, K_FOREVER);
/* Send the packet */
ret = net_context_send(pkt, NULL, K_NO_WAIT, NULL, NULL);
ret = net_context_send_new(ctx, sample_packet,
sizeof(sample_packet), NULL,
K_NO_WAIT, NULL, NULL);
if (ret < 0) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to send the packet (%d)\n",
ret);
net_pkt_unref(pkt);
nb_errors++;
break;
} else {

View file

@ -32,93 +32,81 @@ static struct sockaddr_in *in4_addr_my;
static inline void set_dst_addr(const struct shell *shell,
sa_family_t family,
struct net_pkt *pkt,
union net_ip_header *ip_hdr,
struct net_udp_hdr *udp_hdr,
struct sockaddr *dst_addr)
{
struct net_udp_hdr hdr, *udp_hdr;
udp_hdr = net_udp_get_hdr(pkt, &hdr);
if (!udp_hdr) {
shell_fprintf(shell, SHELL_WARNING,
"Invalid UDP data\n");
return;
}
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6) {
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
&NET_IPV6_HDR(pkt)->src);
&ip_hdr->ipv6->src);
net_sin6(dst_addr)->sin6_family = AF_INET6;
net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
}
if (IS_ENABLED(CONFIG_NET_IPV4) && family == AF_INET) {
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
&NET_IPV4_HDR(pkt)->src);
&ip_hdr->ipv4->src);
net_sin(dst_addr)->sin_family = AF_INET;
net_sin(dst_addr)->sin_port = udp_hdr->src_port;
}
}
static inline struct net_pkt *build_reply_pkt(const struct shell *shell,
struct net_context *context,
struct net_pkt *pkt,
struct zperf_udp_datagram *hdr,
struct zperf_server_hdr *stat)
static inline void build_reply(struct zperf_udp_datagram *hdr,
struct zperf_server_hdr *stat,
u8_t *buf)
{
struct net_pkt *reply_pkt;
struct net_buf *frag;
int pos = 0;
struct zperf_server_hdr *stat_hdr;
shell_fprintf(shell, SHELL_NORMAL,
"Received %d bytes\n", net_pkt_appdatalen(pkt));
memcpy(&buf[pos], hdr, sizeof(struct zperf_udp_datagram));
pos += sizeof(struct zperf_udp_datagram);
reply_pkt = net_pkt_get_tx(context, K_FOREVER);
frag = net_pkt_get_data(context, K_FOREVER);
stat_hdr = (struct zperf_server_hdr *)&buf[pos];
net_pkt_frag_add(reply_pkt, frag);
net_pkt_append_be32(reply_pkt, hdr->id);
net_pkt_append_be32(reply_pkt, hdr->tv_sec);
net_pkt_append_be32(reply_pkt, hdr->tv_usec);
net_pkt_append_be32(reply_pkt, stat->flags);
net_pkt_append_be32(reply_pkt, stat->total_len1);
net_pkt_append_be32(reply_pkt, stat->total_len2);
net_pkt_append_be32(reply_pkt, stat->stop_sec);
net_pkt_append_be32(reply_pkt, stat->stop_usec);
net_pkt_append_be32(reply_pkt, stat->error_cnt);
net_pkt_append_be32(reply_pkt, stat->outorder_cnt);
net_pkt_append_be32(reply_pkt, stat->datagrams);
net_pkt_append_be32(reply_pkt, stat->jitter1);
net_pkt_append_be32(reply_pkt, stat->jitter2);
return reply_pkt;
stat_hdr->flags = htonl(stat->flags);
stat_hdr->total_len1 = htonl(stat->total_len1);
stat_hdr->total_len2 = htonl(stat->total_len2);
stat_hdr->stop_sec = htonl(stat->stop_sec);
stat_hdr->stop_usec = htonl(stat->stop_usec);
stat_hdr->error_cnt = htonl(stat->error_cnt);
stat_hdr->outorder_cnt = htonl(stat->outorder_cnt);
stat_hdr->datagrams = htonl(stat->datagrams);
stat_hdr->jitter1 = htonl(stat->jitter1);
stat_hdr->jitter2 = htonl(stat->jitter2);
}
/* Send statistics to the remote client */
#define BUF_SIZE sizeof(struct zperf_udp_datagram) + \
sizeof(struct zperf_server_hdr)
static int zperf_receiver_send_stat(const struct shell *shell,
struct net_context *context,
struct net_pkt *pkt,
union net_ip_header *ip_hdr,
struct net_udp_hdr *udp_hdr,
struct zperf_udp_datagram *hdr,
struct zperf_server_hdr *stat)
{
struct net_pkt *reply_pkt;
u8_t reply[BUF_SIZE];
struct sockaddr dst_addr;
int ret;
set_dst_addr(shell, net_pkt_family(pkt), pkt, &dst_addr);
shell_fprintf(shell, SHELL_NORMAL,
"Received %d bytes\n", net_pkt_remaining_data(pkt));
reply_pkt = build_reply_pkt(shell, context, pkt, hdr, stat);
set_dst_addr(shell, net_pkt_family(pkt),
pkt, ip_hdr, udp_hdr, &dst_addr);
net_pkt_unref(pkt);
build_reply(hdr, stat, reply);
ret = net_context_sendto(reply_pkt, &dst_addr,
net_pkt_family(pkt) == AF_INET6 ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in),
NULL, 0, NULL, NULL);
ret = net_context_sendto_new(context, reply, BUF_SIZE, &dst_addr,
net_pkt_family(pkt) == AF_INET6 ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in),
NULL, 0, NULL, NULL);
if (ret < 0) {
shell_fprintf(shell, SHELL_WARNING,
" Cannot send data to peer (%d)", ret);
net_pkt_unref(reply_pkt);
}
return ret;
@ -131,11 +119,11 @@ static void udp_received(struct net_context *context,
int status,
void *user_data)
{
NET_PKT_DATA_ACCESS_DEFINE(zperf, struct zperf_udp_datagram);
struct net_udp_hdr *udp_hdr = proto_hdr->udp;
const struct shell *shell = user_data;
struct zperf_udp_datagram hdr;
struct zperf_udp_datagram *hdr;
struct session *session;
struct net_buf *frag;
u16_t offset, pos;
s32_t transit_time;
u32_t time;
s32_t id;
@ -144,31 +132,23 @@ static void udp_received(struct net_context *context,
return;
}
frag = pkt->frags;
if (net_pkt_appdatalen(pkt) < sizeof(struct zperf_udp_datagram)) {
hdr = (struct zperf_udp_datagram *)net_pkt_get_data_new(pkt, &zperf);
if (!hdr) {
shell_fprintf(shell, SHELL_WARNING,
"Short iperf packet!\n");
net_pkt_unref(pkt);
return;
goto out;
}
time = k_cycle_get_32();
session = get_session(pkt, SESSION_UDP);
session = get_session(pkt, ip_hdr, proto_hdr, SESSION_UDP);
if (!session) {
shell_fprintf(shell, SHELL_WARNING,
"Cannot get a session!\n");
return;
goto out;
}
offset = net_pkt_appdata(pkt) - net_pkt_ip_data(pkt);
frag = net_frag_read_be32(frag, offset, &pos, (u32_t *)&hdr.id);
frag = net_frag_read_be32(frag, pos, &pos, &hdr.tv_sec);
frag = net_frag_read_be32(frag, pos, &pos, &hdr.tv_usec);
id = hdr.id;
id = ntohl(hdr->id);
switch (session->state) {
case STATE_COMPLETED:
@ -177,7 +157,8 @@ static void udp_received(struct net_context *context,
/* Session is already completed: Resend the stat packet
* and continue
*/
if (zperf_receiver_send_stat(shell, context, pkt, &hdr,
if (zperf_receiver_send_stat(shell, context, pkt,
ip_hdr, udp_hdr, hdr,
&session->stat) < 0) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to send the packet\n");
@ -194,12 +175,13 @@ static void udp_received(struct net_context *context,
break;
case STATE_ONGOING:
if (id < 0) { /* Negative id means session end. */
u32_t rate_in_kbps;
u32_t duration;
shell_fprintf(shell, SHELL_NORMAL, "End of session!\n");
u32_t rate_in_kbps;
u32_t duration = HW_CYCLES_TO_USEC(
duration = HW_CYCLES_TO_USEC(
time_delta(session->start_time, time));
/* Update state machine */
session->state = STATE_COMPLETED;
@ -226,7 +208,8 @@ static void udp_received(struct net_context *context,
session->stat.jitter1 = 0;
session->stat.jitter2 = session->jitter;
if (zperf_receiver_send_stat(shell, context, pkt, &hdr,
if (zperf_receiver_send_stat(shell, context, pkt,
ip_hdr, udp_hdr, hdr,
&session->stat) < 0) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to send the packet\n");
@ -260,12 +243,13 @@ static void udp_received(struct net_context *context,
} else {
/* Update counter */
session->counter++;
session->length += net_pkt_appdatalen(pkt);
session->length += net_pkt_remaining_data(pkt);
/* Compute jitter */
transit_time = time_delta(HW_CYCLES_TO_USEC(time),
hdr.tv_sec * USEC_PER_SEC +
hdr.tv_usec);
ntohl(hdr->tv_sec) *
USEC_PER_SEC +
ntohl(hdr->tv_usec));
if (session->last_transit_time != 0) {
s32_t delta_transit = transit_time -
session->last_transit_time;
@ -297,6 +281,7 @@ static void udp_received(struct net_context *context,
break;
}
out:
net_pkt_unref(pkt);
}

View file

@ -18,62 +18,43 @@ LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);
#include "zperf.h"
#include "zperf_internal.h"
static u8_t sample_packet[PACKET_SIZE_MAX];
static u8_t sample_packet[sizeof(struct zperf_udp_datagram) + PACKET_SIZE_MAX];
static inline void zperf_upload_decode_stat(const struct shell *shell,
struct net_pkt *pkt,
struct zperf_results *results)
{
struct net_buf *frag;
struct zperf_server_hdr hdr;
u16_t offset;
u16_t pos;
NET_PKT_DATA_ACCESS_DEFINE(zperf_udp, struct zperf_udp_datagram);
NET_PKT_DATA_ACCESS_DEFINE(zperf_stat, struct zperf_server_hdr);
struct zperf_udp_datagram *hdr;
struct zperf_server_hdr *stat;
if (!pkt) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to receive statistics\n");
return;
}
frag = net_frag_get_pos(pkt,
net_pkt_ip_hdr_len(pkt) +
net_pkt_ipv6_ext_len(pkt) +
sizeof(struct net_udp_hdr) +
sizeof(struct zperf_udp_datagram),
&offset);
if (!frag) {
hdr = (struct zperf_udp_datagram *)
net_pkt_get_data_new(pkt, &zperf_udp);
if (!hdr) {
shell_fprintf(shell, SHELL_WARNING,
"Network packet too short\n");
return;
}
/* Decode stat */
if (net_pkt_appdatalen(pkt) <
(sizeof(struct zperf_server_hdr) +
sizeof(struct zperf_udp_datagram))) {
net_pkt_acknowledge_data(pkt, &zperf_udp);
stat = (struct zperf_server_hdr *)
net_pkt_get_data_new(pkt, &zperf_stat);
if (!stat) {
shell_fprintf(shell, SHELL_WARNING,
"Statistics too small\n");
"Network packet too short\n");
return;
}
frag = net_frag_read_be32(frag, offset, &pos, (u32_t *)&hdr.flags);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.total_len1);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.total_len2);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.stop_sec);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.stop_usec);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.error_cnt);
frag = net_frag_read_be32(frag, pos, &pos,
(u32_t *)&hdr.outorder_cnt);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.datagrams);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.jitter1);
frag = net_frag_read_be32(frag, pos, &pos, (u32_t *)&hdr.jitter2);
results->nb_packets_rcvd = hdr.datagrams;
results->nb_packets_lost = hdr.error_cnt;
results->nb_packets_outorder = hdr.outorder_cnt;
results->nb_bytes_sent = hdr.total_len2;
results->time_in_us = hdr.stop_usec + hdr.stop_sec * USEC_PER_SEC;
results->jitter_in_us = hdr.jitter2 + hdr.jitter1 * USEC_PER_SEC;
results->nb_packets_rcvd = ntohl(stat->datagrams);
results->nb_packets_lost = ntohl(stat->error_cnt);
results->nb_packets_outorder = ntohl(stat->outorder_cnt);
results->nb_bytes_sent = ntohl(stat->total_len2);
results->time_in_us = ntohl(stat->stop_usec) +
ntohl(stat->stop_sec) * USEC_PER_SEC;
results->jitter_in_us = ntohl(stat->jitter2) +
ntohl(stat->jitter1) * USEC_PER_SEC;
}
static void stat_received(struct net_context *context,
@ -96,65 +77,27 @@ static inline void zperf_upload_fin(const struct shell *shell,
struct zperf_results *results)
{
struct net_pkt *stat = NULL;
struct zperf_udp_datagram datagram;
struct zperf_udp_datagram *datagram;
int loop = 2;
int ret;
while (!stat && loop-- > 0) {
struct net_pkt *pkt;
struct net_buf *frag;
bool status;
pkt = net_pkt_get_tx(context, K_FOREVER);
if (!pkt) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to retrieve a packet\n");
continue;
}
frag = net_pkt_get_data(context, K_FOREVER);
if (!frag) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to retrieve a fragment\n");
continue;
}
net_pkt_frag_add(pkt, frag);
datagram = (struct zperf_udp_datagram *)sample_packet;
/* Fill the packet header */
datagram.id = htonl(-nb_packets);
datagram.tv_sec = htonl(HW_CYCLES_TO_SEC(end_time));
datagram.tv_usec = htonl(HW_CYCLES_TO_USEC(end_time) %
USEC_PER_SEC);
status = net_pkt_append_all(pkt, sizeof(datagram),
(u8_t *)&datagram, K_FOREVER);
if (!status) {
shell_fprintf(shell, SHELL_WARNING,
"Cannot append datagram data\n");
break;
}
/* Fill the remain part of the datagram */
if (packet_size > sizeof(struct zperf_udp_datagram)) {
int size = packet_size -
sizeof(struct zperf_udp_datagram);
u16_t pos;
frag = net_pkt_write(pkt, net_buf_frag_last(pkt->frags),
sizeof(struct zperf_udp_datagram),
&pos, size,
(u8_t *)sample_packet,
K_FOREVER);
}
datagram->id = htonl(-nb_packets);
datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(end_time));
datagram->tv_usec = htonl(HW_CYCLES_TO_USEC(end_time) %
USEC_PER_SEC);
/* Send the packet */
ret = net_context_send(pkt, NULL, K_NO_WAIT, NULL, NULL);
ret = net_context_send_new(context, sample_packet,
packet_size, NULL,
K_NO_WAIT, NULL, NULL);
if (ret < 0) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to send the packet (%d)\n",
ret);
net_pkt_unref(pkt);
continue;
}
@ -230,12 +173,9 @@ void zperf_udp_upload(const struct shell *shell,
(void)memset(sample_packet, 'z', sizeof(sample_packet));
do {
struct zperf_udp_datagram datagram;
struct net_pkt *pkt;
struct net_buf *frag;
struct zperf_udp_datagram *datagram;
u32_t loop_time;
s32_t adjust;
bool status;
int ret;
/* Timestamp */
@ -259,56 +199,22 @@ void zperf_udp_upload(const struct shell *shell,
last_loop_time = loop_time;
pkt = net_pkt_get_tx(context, K_FOREVER);
if (!pkt) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to retrieve a packet\n");
continue;
}
frag = net_pkt_get_data(context, K_FOREVER);
if (!frag) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to retrieve a frag\n");
continue;
}
net_pkt_frag_add(pkt, frag);
/* Fill the packet header */
datagram.id = htonl(nb_packets);
datagram.tv_sec = htonl(HW_CYCLES_TO_SEC(loop_time));
datagram.tv_usec =
datagram = (struct zperf_udp_datagram *)sample_packet;
datagram->id = htonl(nb_packets);
datagram->tv_sec = htonl(HW_CYCLES_TO_SEC(loop_time));
datagram->tv_usec =
htonl(HW_CYCLES_TO_USEC(loop_time) % USEC_PER_SEC);
status = net_pkt_append_all(pkt, sizeof(datagram),
(u8_t *)&datagram, K_FOREVER);
if (!status) {
shell_fprintf(shell, SHELL_WARNING,
"Cannot append datagram data\n");
break;
}
/* Fill the remain part of the datagram */
if (packet_size > sizeof(struct zperf_udp_datagram)) {
int size = packet_size -
sizeof(struct zperf_udp_datagram);
u16_t pos;
frag = net_pkt_write(pkt, net_buf_frag_last(pkt->frags),
sizeof(struct zperf_udp_datagram),
&pos, size, sample_packet,
K_FOREVER);
}
/* Send the packet */
ret = net_context_send(pkt, NULL, K_NO_WAIT, NULL, NULL);
ret = net_context_send_new(context, sample_packet,
packet_size, NULL,
K_NO_WAIT, NULL, NULL);
if (ret < 0) {
shell_fprintf(shell, SHELL_WARNING,
"Failed to send the packet (%d)\n",
ret);
net_pkt_unref(pkt);
break;
} else {
nb_packets++;