1 /*
2  * Copyright (c) 2015 Intel Corporation
3  * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
10 
11 #include <zephyr/kernel.h>
12 
13 #include <zephyr/net/net_pkt.h>
14 #include <zephyr/net/udp.h>
15 
16 #include "zperf_session.h"
17 
18 #define SESSION_MAX CONFIG_NET_ZPERF_MAX_SESSIONS
19 
20 static struct session sessions[SESSION_PROTO_END][SESSION_MAX];
21 
22 /* Get session from a given packet */
get_session(const struct sockaddr * addr,enum session_proto proto)23 struct session *get_session(const struct sockaddr *addr,
24 			    enum session_proto proto)
25 {
26 	struct session *active = NULL;
27 	struct session *free = NULL;
28 	int i = 0;
29 	const struct sockaddr_in *addr4 = (const struct sockaddr_in *)addr;
30 	const struct sockaddr_in6 *addr6 = (const struct sockaddr_in6 *)addr;
31 
32 	if (proto != SESSION_TCP && proto != SESSION_UDP) {
33 		NET_ERR("Error! unsupported proto.\n");
34 		return NULL;
35 	}
36 
37 	/* Check whether we already have an active session */
38 	while (!active && i < SESSION_MAX) {
39 		struct session *ptr = &sessions[proto][i];
40 
41 		if (IS_ENABLED(CONFIG_NET_IPV4) &&
42 		    addr->sa_family == AF_INET &&
43 		    ptr->ip.family == AF_INET &&
44 		    ptr->port == addr4->sin_port &&
45 		    net_ipv4_addr_cmp(&ptr->ip.in_addr, &addr4->sin_addr)) {
46 			/* We found an active session */
47 			active = ptr;
48 			break;
49 		}
50 
51 		if (IS_ENABLED(CONFIG_NET_IPV6) &&
52 		    addr->sa_family == AF_INET6 &&
53 		    ptr->ip.family == AF_INET6 &&
54 		    ptr->port == addr6->sin6_port &&
55 		    net_ipv6_addr_cmp(&ptr->ip.in6_addr, &addr6->sin6_addr)) {
56 			/* We found an active session */
57 			active = ptr;
58 			break;
59 		}
60 
61 		if (!free && (ptr->state == STATE_NULL ||
62 			      ptr->state == STATE_COMPLETED)) {
63 			/* We found a free slot - just in case */
64 			free = ptr;
65 		}
66 
67 		i++;
68 	}
69 
70 	/* If no active session then create a new one */
71 	if (!active && free) {
72 		active = free;
73 
74 		if (IS_ENABLED(CONFIG_NET_IPV4) && addr->sa_family == AF_INET) {
75 			active->port = addr4->sin_port;
76 			active->ip.family = AF_INET;
77 			net_ipaddr_copy(&active->ip.in_addr, &addr4->sin_addr);
78 		} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
79 			   addr->sa_family == AF_INET6) {
80 			active->port = addr6->sin6_port;
81 			active->ip.family = AF_INET6;
82 			net_ipaddr_copy(&active->ip.in6_addr, &addr6->sin6_addr);
83 		}
84 	}
85 
86 	return active;
87 }
88 
zperf_reset_session_stats(struct session * session)89 void zperf_reset_session_stats(struct session *session)
90 {
91 	if (!session) {
92 		return;
93 	}
94 
95 	session->counter = 0U;
96 	session->start_time = 0U;
97 	session->next_id = 1U;
98 	session->length = 0U;
99 	session->outorder = 0U;
100 	session->error = 0U;
101 	session->jitter = 0;
102 	session->last_transit_time = 0;
103 }
104 
zperf_session_reset(enum session_proto proto)105 void zperf_session_reset(enum session_proto proto)
106 {
107 	int i, j;
108 
109 	if (proto >= SESSION_PROTO_END) {
110 		return;
111 	}
112 
113 	i = (int)proto;
114 
115 	for (j = 0; j < SESSION_MAX; j++) {
116 		sessions[i][j].state = STATE_NULL;
117 		zperf_reset_session_stats(&(sessions[i][j]));
118 	}
119 }
120 
zperf_session_init(void)121 void zperf_session_init(void)
122 {
123 	int i;
124 
125 	for (i = 0; i < SESSION_PROTO_END; i++) {
126 		zperf_session_reset(i);
127 	}
128 }
129