129 lines
2.9 KiB
C
129 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2015 Intel Corporation
|
|
* Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/logging/log.h>
|
|
LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|
|
|
#include <zephyr/kernel.h>
|
|
|
|
#include <zephyr/net/net_pkt.h>
|
|
#include <zephyr/net/udp.h>
|
|
|
|
#include "zperf_session.h"
|
|
|
|
#define SESSION_MAX CONFIG_NET_ZPERF_MAX_SESSIONS
|
|
|
|
static struct session sessions[SESSION_PROTO_END][SESSION_MAX];
|
|
|
|
/* Get session from a given packet */
|
|
struct session *get_session(const struct sockaddr *addr,
|
|
enum session_proto proto)
|
|
{
|
|
struct session *active = NULL;
|
|
struct session *free = NULL;
|
|
int i = 0;
|
|
const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
|
|
const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
|
|
|
|
if (proto != SESSION_TCP && proto != SESSION_UDP) {
|
|
NET_ERR("Error! unsupported proto.\n");
|
|
return NULL;
|
|
}
|
|
|
|
/* Check whether we already have an active session */
|
|
while (!active && i < SESSION_MAX) {
|
|
struct session *ptr = &sessions[proto][i];
|
|
|
|
if (IS_ENABLED(CONFIG_NET_IPV4) &&
|
|
addr->sa_family == AF_INET &&
|
|
ptr->ip.family == AF_INET &&
|
|
ptr->port == addr4->sin_port &&
|
|
net_ipv4_addr_cmp(&ptr->ip.in_addr, &addr4->sin_addr)) {
|
|
/* We found an active session */
|
|
active = ptr;
|
|
break;
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_NET_IPV6) &&
|
|
addr->sa_family == AF_INET6 &&
|
|
ptr->ip.family == AF_INET6 &&
|
|
ptr->port == addr6->sin6_port &&
|
|
net_ipv6_addr_cmp(&ptr->ip.in6_addr, &addr6->sin6_addr)) {
|
|
/* We found an active session */
|
|
active = ptr;
|
|
break;
|
|
}
|
|
|
|
if (!free && (ptr->state == STATE_NULL ||
|
|
ptr->state == STATE_COMPLETED)) {
|
|
/* We found a free slot - just in case */
|
|
free = ptr;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
/* If no active session then create a new one */
|
|
if (!active && free) {
|
|
active = free;
|
|
|
|
if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
|
|
active->port = addr4->sin_port;
|
|
active->ip.family = AF_INET;
|
|
net_ipaddr_copy(&active->ip.in_addr, &addr4->sin_addr);
|
|
} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
|
|
addr->sa_family == AF_INET6) {
|
|
active->port = addr6->sin6_port;
|
|
active->ip.family = AF_INET6;
|
|
net_ipaddr_copy(&active->ip.in6_addr, &addr6->sin6_addr);
|
|
}
|
|
}
|
|
|
|
return active;
|
|
}
|
|
|
|
void zperf_reset_session_stats(struct session *session)
|
|
{
|
|
if (!session) {
|
|
return;
|
|
}
|
|
|
|
session->counter = 0U;
|
|
session->start_time = 0U;
|
|
session->next_id = 1U;
|
|
session->length = 0U;
|
|
session->outorder = 0U;
|
|
session->error = 0U;
|
|
session->jitter = 0;
|
|
session->last_transit_time = 0;
|
|
}
|
|
|
|
void zperf_session_reset(enum session_proto proto)
|
|
{
|
|
int i, j;
|
|
|
|
if (proto >= SESSION_PROTO_END) {
|
|
return;
|
|
}
|
|
|
|
i = (int)proto;
|
|
|
|
for (j = 0; j < SESSION_MAX; j++) {
|
|
sessions[i][j].state = STATE_NULL;
|
|
zperf_reset_session_stats(&(sessions[i][j]));
|
|
}
|
|
}
|
|
|
|
void zperf_session_init(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < SESSION_PROTO_END; i++) {
|
|
zperf_session_reset(i);
|
|
}
|
|
}
|