/* * Copyright (c) 2015 Intel Corporation * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ #include LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL); #include #include #include #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); } }