forked from Bananymous/banan-os
				
			Kernel: Fix TCP window scaling
This commit is contained in:
		
							parent
							
								
									a0123e7c2d
								
							
						
					
					
						commit
						c9132d984b
					
				|  | @ -91,7 +91,7 @@ namespace Kernel | ||||||
| 			bool						has_ghost_byte { false }; | 			bool						has_ghost_byte { false }; | ||||||
| 
 | 
 | ||||||
| 			uint32_t					data_size	{ 0 }; // number of bytes in this buffer
 | 			uint32_t					data_size	{ 0 }; // number of bytes in this buffer
 | ||||||
| 			uint8_t						scale		{ 1 }; // window scale
 | 			uint8_t						scale_shift	{ 0 }; // window scale
 | ||||||
| 			BAN::UniqPtr<VirtualRange>	buffer; | 			BAN::UniqPtr<VirtualRange>	buffer; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
|  | @ -99,8 +99,8 @@ namespace Kernel | ||||||
| 		{ | 		{ | ||||||
| 			uint32_t					mss				{ 0 }; // maximum segment size
 | 			uint32_t					mss				{ 0 }; // maximum segment size
 | ||||||
| 			uint16_t					non_scaled_size	{ 0 }; // window size without scaling
 | 			uint16_t					non_scaled_size	{ 0 }; // window size without scaling
 | ||||||
| 			uint8_t						scale			{ 0 }; // window scale
 | 			uint8_t						scale_shift		{ 0 }; // window scale
 | ||||||
| 			uint32_t 					scaled_size() const { return (uint32_t)non_scaled_size << scale; } | 			uint32_t 					scaled_size() const { return (uint32_t)non_scaled_size << scale_shift; } | ||||||
| 
 | 
 | ||||||
| 			uint32_t					start_seq		{ 0 }; // sequence number of first byte in buffer
 | 			uint32_t					start_seq		{ 0 }; // sequence number of first byte in buffer
 | ||||||
| 			uint32_t					current_seq		{ 0 }; // sequence number of next send
 | 			uint32_t					current_seq		{ 0 }; // sequence number of next send
 | ||||||
|  | @ -118,6 +118,7 @@ namespace Kernel | ||||||
| 		{ | 		{ | ||||||
| 			sockaddr_storage	address; | 			sockaddr_storage	address; | ||||||
| 			socklen_t			address_len; | 			socklen_t			address_len; | ||||||
|  | 			bool				has_window_scale; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		struct PendingConnection | 		struct PendingConnection | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ namespace Kernel | ||||||
| 			PageTable::Flags::ReadWrite | PageTable::Flags::Present, | 			PageTable::Flags::ReadWrite | PageTable::Flags::Present, | ||||||
| 			true | 			true | ||||||
| 		)); | 		)); | ||||||
| 		socket->m_recv_window.scale = 12; // use PAGE_SIZE windows
 | 		socket->m_recv_window.scale_shift = PAGE_SIZE_SHIFT; // use PAGE_SIZE windows
 | ||||||
| 		socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range( | 		socket->m_send_window.buffer = TRY(VirtualRange::create_to_vaddr_range( | ||||||
| 			PageTable::kernel(), | 			PageTable::kernel(), | ||||||
| 			KERNEL_OFFSET, | 			KERNEL_OFFSET, | ||||||
|  | @ -80,7 +80,6 @@ namespace Kernel | ||||||
| 		auto connection = m_pending_connections.front(); | 		auto connection = m_pending_connections.front(); | ||||||
| 		m_pending_connections.pop(); | 		m_pending_connections.pop(); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		auto listen_key = ListenKey( | 		auto listen_key = ListenKey( | ||||||
| 			reinterpret_cast<const sockaddr*>(&connection.target.address), | 			reinterpret_cast<const sockaddr*>(&connection.target.address), | ||||||
| 			connection.target.address_len | 			connection.target.address_len | ||||||
|  | @ -104,6 +103,9 @@ namespace Kernel | ||||||
| 		return_inode->m_next_state = State::SynReceived; | 		return_inode->m_next_state = State::SynReceived; | ||||||
| 		return_inode->m_mutex.unlock(); | 		return_inode->m_mutex.unlock(); | ||||||
| 
 | 
 | ||||||
|  | 		if (!return_inode->m_connection_info->has_window_scale) | ||||||
|  | 			return_inode->m_recv_window.scale_shift = 0; | ||||||
|  | 
 | ||||||
| 		TRY(m_listen_children.emplace(listen_key, return_inode)); | 		TRY(m_listen_children.emplace(listen_key, return_inode)); | ||||||
| 
 | 
 | ||||||
| 		const uint64_t wake_time_ms = SystemTimer::get().ms_since_boot() + 5000; | 		const uint64_t wake_time_ms = SystemTimer::get().ms_since_boot() + 5000; | ||||||
|  | @ -155,7 +157,7 @@ namespace Kernel | ||||||
| 		if (!is_bound()) | 		if (!is_bound()) | ||||||
| 			TRY(m_network_layer.bind_socket_to_unused(this, address, address_len)); | 			TRY(m_network_layer.bind_socket_to_unused(this, address, address_len)); | ||||||
| 
 | 
 | ||||||
| 		m_connection_info.emplace(sockaddr_storage {}, address_len); | 		m_connection_info.emplace(sockaddr_storage {}, address_len, true); | ||||||
| 		memcpy(&m_connection_info->address, address, address_len); | 		memcpy(&m_connection_info->address, address, address_len); | ||||||
| 
 | 
 | ||||||
| 		m_next_flags = SYN; | 		m_next_flags = SYN; | ||||||
|  | @ -377,16 +379,18 @@ namespace Kernel | ||||||
| 		header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte; | 		header.seq_number = m_send_window.current_seq + m_send_window.has_ghost_byte; | ||||||
| 		header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte; | 		header.ack_number = m_recv_window.start_seq + m_recv_window.data_size + m_recv_window.has_ghost_byte; | ||||||
| 		header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t); | 		header.data_offset = (sizeof(TCPHeader) + m_tcp_options_bytes) / sizeof(uint32_t); | ||||||
| 		header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size() >> m_recv_window.scale); | 		header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size() >> m_recv_window.scale_shift); | ||||||
| 		header.flags = m_next_flags; | 		header.flags = m_next_flags; | ||||||
| 		if (header.flags & FIN) | 		if (header.flags & FIN) | ||||||
| 			m_send_window.has_ghost_byte = true; | 			m_send_window.has_ghost_byte = true; | ||||||
| 		m_next_flags = 0; | 		m_next_flags = 0; | ||||||
| 
 | 
 | ||||||
| 		if (m_state == State::Closed) | 		if (m_state == State::Closed || m_state == State::SynReceived) | ||||||
| 		{ | 		{ | ||||||
| 			add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, m_interface->payload_mtu() - m_network_layer.header_size()); | 			add_tcp_header_option<0, TCPOption::MaximumSeqmentSize>(header, m_interface->payload_mtu() - m_network_layer.header_size()); | ||||||
| 			add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale); | 
 | ||||||
|  | 			if (m_connection_info->has_window_scale) | ||||||
|  | 				add_tcp_header_option<4, TCPOption::WindowScale>(header, m_recv_window.scale_shift); | ||||||
| 			header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size()); | 			header.window_size = BAN::Math::min<size_t>(0xFFFF, m_recv_window.buffer->size()); | ||||||
| 
 | 
 | ||||||
| 			m_send_window.mss = 1440; | 			m_send_window.mss = 1440; | ||||||
|  | @ -463,9 +467,12 @@ namespace Kernel | ||||||
| 				if (options.maximum_seqment_size.has_value()) | 				if (options.maximum_seqment_size.has_value()) | ||||||
| 					m_send_window.mss = *options.maximum_seqment_size; | 					m_send_window.mss = *options.maximum_seqment_size; | ||||||
| 				if (options.window_scale.has_value()) | 				if (options.window_scale.has_value()) | ||||||
| 					m_send_window.scale = *options.window_scale; | 					m_send_window.scale_shift = *options.window_scale; | ||||||
| 				else | 				else | ||||||
| 					m_recv_window.scale = 1; | 				{ | ||||||
|  | 					m_recv_window.scale_shift = 0; | ||||||
|  | 					m_connection_info->has_window_scale = false; | ||||||
|  | 				} | ||||||
| 
 | 
 | ||||||
| 				m_send_window.start_seq = m_send_window.current_seq; | 				m_send_window.start_seq = m_send_window.current_seq; | ||||||
| 				m_send_window.current_ack = m_send_window.current_seq; | 				m_send_window.current_ack = m_send_window.current_seq; | ||||||
|  | @ -492,6 +499,7 @@ namespace Kernel | ||||||
| 						ConnectionInfo connection_info; | 						ConnectionInfo connection_info; | ||||||
| 						memcpy(&connection_info.address, sender, sender_len); | 						memcpy(&connection_info.address, sender, sender_len); | ||||||
| 						connection_info.address_len = sender_len; | 						connection_info.address_len = sender_len; | ||||||
|  | 						connection_info.has_window_scale = parse_tcp_options(header).window_scale.has_value(); | ||||||
| 						MUST(m_pending_connections.emplace( | 						MUST(m_pending_connections.emplace( | ||||||
| 							connection_info, | 							connection_info, | ||||||
| 							header.seq_number + 1 | 							header.seq_number + 1 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue