Skip to content

Commit 57189dc

Browse files
authored
Network: add support for simultaneous outgoing connections via different network interface (#87)
1 parent fe3adcc commit 57189dc

File tree

12 files changed

+126
-45
lines changed

12 files changed

+126
-45
lines changed

Components/Network/Include/rl_net.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: rl_net.h
66
* Purpose: Network API
@@ -17,7 +17,7 @@
1717

1818
/// Network component version
1919
#define MW_NET_VERSION_MAJOR 8
20-
#define MW_NET_VERSION_MINOR 0
20+
#define MW_NET_VERSION_MINOR 1
2121
#define MW_NET_VERSION_PATCH 0
2222

2323
#ifdef __cplusplus
@@ -136,6 +136,7 @@ typedef enum {
136136
typedef enum {
137137
netTCP_OptionTOS = 0, ///< IPv4 Type of Service; val=TOS
138138
netTCP_OptionTrafficClass, ///< IPv6 Traffic Class; val=TrafficClass
139+
netTCP_OptionInterface, ///< Network interface to bind; val=if_id (class and number)
139140
netTCP_OptionTimeout, ///< TCP Idle Timeout; val=timeout (in seconds)
140141
netTCP_OptionKeepAlive, ///< TCP Keep Alive; val: 0=disabled (default), 1=enabled
141142
netTCP_OptionFlowControl, ///< TCP Flow Control; val: 0=disabled (default), 1=enabled

Components/Network/Network.scvd

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22

33
<component_viewer schemaVersion="0.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="Component_Viewer.xsd">
4-
<component name="Network" shortname="NET" version="8.0.1"/> <!-- name and version of the component -->
4+
<component name="Network" shortname="NET" version="8.1.0"/> <!-- name and version of the component -->
55

66
<typedefs>
77
<!-- Network Library variant -->
@@ -745,7 +745,7 @@
745745
<enum name="TTL" value="1" info="IPv4 Multi-cast Time to Live"/>
746746
<enum name="TrafficClass" value="2" info="IPv6 Traffic Class"/>
747747
<enum name="HopLimit" value="3" info="IPv6 Multi-cast Hop limit"/>
748-
<enum name="Interface" value="4" info="Broadcast Network interface"/>
748+
<enum name="Interface" value="4" info="Bound Network interface"/>
749749
<enum name="Checksum" value="5" info="Checksum Options"/>
750750
</member>
751751
</typedef>
@@ -808,10 +808,11 @@
808808
<member name="id" type="uint8_t" offset="0">
809809
<enum name="TOS" value="0" info="IPv4 Type of Service"/>
810810
<enum name="TrafficClass" value="1" info="IPv6 Traffic Class"/>
811-
<enum name="Timeout" value="2" info="TCP Idle Timeout"/>
812-
<enum name="KeepAlive" value="3" info="TCP Keep Alive"/>
813-
<enum name="FlowControl" value="4" info="TCP Flow Control"/>
814-
<enum name="DelayedACK" value="5" info="TCP Delayed Acknowledgment"/>
811+
<enum name="Interface" value="2" info="Bound Network interface"/>
812+
<enum name="Timeout" value="3" info="TCP Idle Timeout"/>
813+
<enum name="KeepAlive" value="4" info="TCP Keep Alive"/>
814+
<enum name="FlowControl" value="5" info="TCP Flow Control"/>
815+
<enum name="DelayedACK" value="6" info="TCP Delayed Acknowledgment"/>
815816
</member>
816817
</typedef>
817818

@@ -2110,7 +2111,7 @@
21102111
<event id="19 + 0xD000" level="Detail" property="SetOptionTclass" value="socket=%d[val1], tclass=%d[val2]" info="Set socket option traffic class for IPv6"/>
21112112
<event id="20 + 0xD000" level="Detail" property="SetOptionHopLimit" value="socket=%d[val1], hop_limit=%d[val2]" info="Set socket option hop limit for IPv6"/>
21122113
<event id="21 + 0xD000" level="Detail" property="SetOptionChecksum" value="socket=%d[val1], send=%t[val2 &amp; 1 ? &quot;On&quot; : &quot;Off&quot;], verify=%t[val2 &amp; 2 ? &quot;On&quot; : &quot;Off&quot;]" info="Set socket checksum calculation options"/>
2113-
<event id="42 + 0xD000" level="Detail" property="SetOptionInterface" value="socket=%d[val1], netif=%E[val2, NetIf:id]" info="Set Network Interface for broadcasts and multicasts"/>
2114+
<event id="42 + 0xD000" level="Detail" property="SetOptionInterface" value="socket=%d[val1], netif=%E[val2, NetIf:id]" info="Set Network Interface for broadcasts, multicasts and internet access"/>
21142115
<event id="22 + 0xD000" level="Error" property="SetOptionWrongOption" value="socket=%d[val1], opt=%E[val2, UDP_Opt:id]" info="Invalid option requested"/>
21152116
<event id="23 + 0xD000" level="Error" property="SetOptionWrongValue" value="socket=%d[val1], value=%d[val2]" info="Invalid value for option provided"/>
21162117
<event id="24 + 0xD000" level="Error" property="GetBufferFailed" value="size=%d[val1]" info="GetBuffer failed, out of memory error"/>
@@ -2189,6 +2190,7 @@
21892190
<event id="50 + 0xD100" level="Detail" property="SetOptionKeepAlive" value="socket=%d[val1], enable=%d[val2]" info="Set socket option keep-alive"/>
21902191
<event id="51 + 0xD100" level="Detail" property="SetOptionFlowControl" value="socket=%d[val1], enable=%d[val2]" info="Set socket option flow-control"/>
21912192
<event id="52 + 0xD100" level="Detail" property="SetOptionDelayedAck" value="socket=%d[val1], enable=%d[val2]" info="Set socket option delayed-acknowledge"/>
2193+
<event id="116+ 0xD100" level="Detail" property="SetOptionInterface" value="socket=%d[val1], netif=%E[val2, NetIf:id]" info="Set Network Interface for internet connections"/>
21922194
<event id="53 + 0xD100" level="Error" property="SetOptionWrongOption" value="socket=%d[val1], opt=%E[val2, TCP_Opt:id]" info="Invalid option requested"/>
21932195
<event id="54 + 0xD100" level="Error" property="SetOptionWrongValue" value="socket=%d[val1], value=%d[val2]" info="Invalid value for option provided"/>
21942196
<event id="55 + 0xD100" level="Op" property="SendDelayedAck" value="socket=%d[val1]" info="Send delayed-acknowledge"/>

Components/Network/Source/net_bsd.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: net_bsd.c
66
* Purpose: Berkeley Socket API
@@ -1793,6 +1793,7 @@ int32_t getsockname (int32_t sock, SOCKADDR *name, int32_t *namelen) {
17931793
int32_t setsockopt (int32_t sock, int32_t level,
17941794
int32_t optname, const char *optval, int32_t optlen) {
17951795
NET_BSD_INFO *bsd_s;
1796+
netStatus retv;
17961797
uint32_t bval;
17971798
uint16_t bval16;
17981799

@@ -1896,15 +1897,23 @@ not_supp: ERRORF (BSD,"Setsockopt, Socket %d opt not supported\n",sock);
18961897
break;
18971898

18981899
case SO_BINDTODEVICE:
1899-
/* Bind a socket to network interface */
1900-
if (bsd_s->Type != SOCK_DGRAM) {
1901-
goto not_supp;
1900+
/* Bind socket to network interface */
1901+
if (bsd_s->Type == SOCK_STREAM) {
1902+
if (bsd_s->State > BSD_STATE_CREATED) {
1903+
ERRORF (BSD,"Setsockopt, Socket %d already bound\n",sock);
1904+
EvrNetBSD_SetoptSocketBound (sock);
1905+
RETURN (BSD_ERROR);
1906+
}
1907+
retv = net_tcp_set_option (bsd_s->Socket, netTCP_OptionInterface, bval);
1908+
}
1909+
else {
1910+
retv = net_udp_set_option (bsd_s->Socket, netUDP_OptionInterface, bval);
19021911
}
1903-
if (net_udp_set_option (bsd_s->Socket, netUDP_OptionInterface, bval) != netOK) {
1912+
if (retv != netOK) {
19041913
/* Invalid interface id */
19051914
goto inv_arg;
19061915
}
1907-
DEBUGF (BSD," Bind to %s\n", net_if_map_lan(bval)->Name);
1916+
DEBUGF (BSD," Bind to %s\n", net_if_map_all(bval)->Name);
19081917
EvrNetBSD_SetoptBindToDevice (sock, bval);
19091918
break;
19101919

@@ -2116,8 +2125,9 @@ not_supp: ERRORF (BSD,"Getsockopt, Socket %d opt not supported\n",sock);
21162125

21172126
case SO_BINDTODEVICE:
21182127
/* Bound network interface */
2119-
if (bsd_s->Type != SOCK_DGRAM) {
2120-
goto not_supp;
2128+
if (bsd_s->Type == SOCK_STREAM) {
2129+
retv = net_tcp_get_option (bsd_s->Socket, netTCP_OptionInterface);
2130+
break;
21212131
}
21222132
retv = net_udp_get_option (bsd_s->Socket, netUDP_OptionInterface);
21232133
break;

Components/Network/Source/net_evr.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: net_evr.h
66
* Purpose: Network definitions for Event Recorder
@@ -9140,7 +9140,7 @@ typedef struct evr_addr {
91409140
#endif
91419141

91429142
/**
9143-
\brief Event on UDP set socket option broadcast interface (Detail)
9143+
\brief Event on UDP set socket option bind to interface (Detail)
91449144
\param socket socket handle
91459145
\param if_id network interface identifier
91469146
*/
@@ -9426,7 +9426,7 @@ typedef struct evr_addr {
94269426
#define EvtNetTCP_ConnectLocalPortInvalid EventID (EventLevelError, EvtNetTCP, 17)
94279427
#define EvtNetTCP_AssignLocalPort EventID (EventLevelOp, EvtNetTCP, 18)
94289428
#define EvtNetTCP_ConnectSocketWrongState EventID (EventLevelError, EvtNetTCP, 19)
9429-
#define EvtNetTCP_ConnectNoRouteFound EventID (EventLevelError, EvtNetTCP,115) // End
9429+
#define EvtNetTCP_ConnectNoRouteFound EventID (EventLevelError, EvtNetTCP,115)
94309430
#define EvtNetTCP_ShowRttVariables EventID (EventLevelDetail,EvtNetTCP, 20)
94319431
#define EvtNetTCP_GetBufferFailed EventID (EventLevelError, EvtNetTCP, 21)
94329432
#define EvtNetTCP_SendFrame EventID (EventLevelOp, EvtNetTCP, 22)
@@ -9460,6 +9460,7 @@ typedef struct evr_addr {
94609460
#define EvtNetTCP_SetOptionKeepAlive EventID (EventLevelDetail,EvtNetTCP, 50)
94619461
#define EvtNetTCP_SetOptionFlowControl EventID (EventLevelDetail,EvtNetTCP, 51)
94629462
#define EvtNetTCP_SetOptionDelayedAck EventID (EventLevelDetail,EvtNetTCP, 52)
9463+
#define EvtNetTCP_SetOptionInterface EventID (EventLevelDetail,EvtNetTCP,116) // End
94639464
#define EvtNetTCP_SetOptionWrongOption EventID (EventLevelError, EvtNetTCP, 53)
94649465
#define EvtNetTCP_SetOptionWrongValue EventID (EventLevelError, EvtNetTCP, 54)
94659466
#define EvtNetTCP_SendDelayedAck EventID (EventLevelOp, EvtNetTCP, 55)
@@ -10139,6 +10140,19 @@ typedef struct evr_addr {
1013910140
#define EvrNetTCP_SetOptionTclass(socket, ip6_tclass)
1014010141
#endif
1014110142

10143+
/**
10144+
\brief Event on TCP set socket option bind to interface (Detail)
10145+
\param socket socket handle
10146+
\param if_id network interface identifier
10147+
*/
10148+
#ifdef Network_Debug_EVR
10149+
__STATIC_INLINE void EvrNetTCP_SetOptionInterface(int32_t socket, uint16_t if_id) {
10150+
EventRecord2 (EvtNetTCP_SetOptionInterface, (uint32_t)socket, if_id);
10151+
}
10152+
#else
10153+
#define EvrNetTCP_SetOptionInterface(socket, if_id)
10154+
#endif
10155+
1014210156
/**
1014310157
\brief Event on TCP set socket option connection timeout (Detail)
1014410158
\param socket socket handle

Components/Network/Source/net_ip4.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: net_ip4.c
66
* Purpose: Internet Protocol Version 4
@@ -483,6 +483,11 @@ NET_IF_CFG *net_ip4_find_route (NET_IF_CFG *net_if, const uint8_t *dst_addr) {
483483
}
484484
}
485485
/* Address is external */
486+
if (net_if != NULL) {
487+
/* Use desired interface */
488+
return (net_if);
489+
}
490+
/* Use default interface */
486491
return (ip4->DefNetIf);
487492
}
488493

Components/Network/Source/net_tcp.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: net_tcp.c
66
* Purpose: Transmission Control Protocol
@@ -276,6 +276,7 @@ netStatus net_tcp_listen (int32_t socket, uint16_t port) {
276276
*/
277277
netStatus net_tcp_connect (int32_t socket, const __ADDR *addr, uint16_t local_port) {
278278
NET_TCP_INFO *tcp_s;
279+
NET_IF_CFG *out_if;
279280

280281
DEBUGF (TCP,"Connect Socket %d, LocPort %d\n",socket,local_port);
281282
EvrNetTCP_ConnectSocket (socket, local_port);
@@ -323,14 +324,16 @@ netStatus net_tcp_connect (int32_t socket, const __ADDR *addr, uint16_t local_po
323324
EvrNetTCP_ConnectSocketWrongState (socket, tcp_s->State);
324325
return (netWrongState);
325326
}
326-
/* Assign an interface for the connection */
327-
tcp_s->net_if = net_addr_find_route (NULL, addr);
328-
if (tcp_s->net_if == NULL) {
329-
/* No route to destination, also fails for IP6 in IP4_only variant */
327+
328+
/* Check the interface routing */
329+
out_if = net_addr_find_route (tcp_s->net_if, addr);
330+
if (!out_if || (tcp_s->net_if && (out_if != tcp_s->net_if))) {
331+
/* No route or the route differs from the requested */
330332
ERRORF (TCP,"Connect, Socket %d no route found\n",socket);
331333
EvrNetTCP_ConnectNoRouteFound (socket);
332334
return (netError);
333335
}
336+
tcp_s->net_if = out_if;
334337

335338
/* Socket mode is Client now */
336339
tcp_s->Type &= ~TCP_TYPE_SERVER;
@@ -885,6 +888,7 @@ netStatus net_tcp_reset_window (int32_t socket) {
885888
*/
886889
netStatus net_tcp_set_option (int32_t socket, netTCP_Option option, uint32_t val) {
887890
NET_TCP_INFO *tcp_s;
891+
NET_IF_CFG *net_if;
888892

889893
DEBUGF (TCP,"SetOption Socket %d\n",socket);
890894
EvrNetTCP_SetOptionSocket (socket, option, val);
@@ -895,6 +899,7 @@ netStatus net_tcp_set_option (int32_t socket, netTCP_Option option, uint32_t val
895899
}
896900
tcp_s = &tcp->Scb[socket-1];
897901
if (tcp_s->State == netTCP_StateUNUSED) {
902+
wrong_state:
898903
ERRORF (TCP,"SetOption, Socket %d wrong state\n",socket);
899904
EvrNetTCP_SetOptionSocketWrongState (socket, tcp_s->State);
900905
return (netWrongState);
@@ -916,6 +921,17 @@ netStatus net_tcp_set_option (int32_t socket, netTCP_Option option, uint32_t val
916921
return (netOK);
917922
#endif
918923

924+
case netTCP_OptionInterface:
925+
if (tcp_s->State != netTCP_StateCLOSED) {
926+
goto wrong_state;
927+
}
928+
net_if = net_if_map_all (val);
929+
if (net_if == NULL) break;
930+
DEBUGF (TCP," Interface=%s\n",net_if->Name);
931+
EvrNetTCP_SetOptionInterface (socket, net_if->Id);
932+
tcp_s->net_if = net_if;
933+
return (netOK);
934+
919935
case netTCP_OptionTimeout:
920936
if (val > 65535) break;
921937
if (val == 0) {
@@ -992,6 +1008,13 @@ uint32_t net_tcp_get_option (int32_t socket, netTCP_Option option) {
9921008
return (tcp_s->TClass);
9931009
#endif
9941010

1011+
case netTCP_OptionInterface:
1012+
if (!tcp_s->net_if) {
1013+
/* Network interface not assigned */
1014+
return (0);
1015+
}
1016+
return (tcp_s->net_if->Id);
1017+
9951018
case netTCP_OptionTimeout:
9961019
return (tcp_s->ConnTout);
9971020

Components/Network/Source/net_udp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*------------------------------------------------------------------------------
22
* MDK Middleware - Component ::Network
3-
* Copyright (c) 2004-2024 Arm Limited (or its affiliates). All rights reserved.
3+
* Copyright (c) 2004-2025 Arm Limited (or its affiliates). All rights reserved.
44
*------------------------------------------------------------------------------
55
* Name: net_udp.c
66
* Purpose: User Datagram Protocol
@@ -278,7 +278,7 @@ netStatus net_udp_set_option (int32_t socket, netUDP_Option option, uint32_t val
278278
#endif
279279

280280
case netUDP_OptionInterface:
281-
net_if = net_if_map_lan (val);
281+
net_if = net_if_map_all (val);
282282
if (net_if == NULL) break;
283283
DEBUGF (UDP," Interface=%s\n",net_if->Name);
284284
EvrNetUDP_SetOptionInterface (socket, net_if->Id);

Documentation/Doxygen/General/src/revision_history.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<tr>
1313
<td>V8.0.1-dev</td>
1414
<td>
15-
- Network Component Version 8.0.1
15+
- Network Component Version 8.1.0
1616
- FileSystem Component Version 8.0.1
1717
</td>
1818
</tr>

Documentation/Doxygen/Network/src/net_evr.txt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7190,7 +7190,7 @@ This usually happens when the \ref netUDP_SetOption function is executed.
71907190
\details
71917191
The event \b SetOptionInterface is created, when the internal function \e udp_set_option
71927192
sets the network interface for the socket that is used when the \ref netUDP_Send sends data
7193-
to a broadcast or a multicast address. This usually happens when the \ref netUDP_SetOption
7193+
to a broadcast, multicast or external address. This usually happens when the \ref netUDP_SetOption
71947194
function is executed.
71957195

71967196
\b Value in the Event Recorder shows:
@@ -8032,6 +8032,18 @@ when the \ref netTCP_SetOption function is executed.
80328032
- \b enable: controlling the delayed acknowledgement (1= enable, 0= disable).
80338033
*/
80348034

8035+
/**
8036+
\fn __STATIC_INLINE void EvrNetTCP_SetOptionInterface(int32_t socket, uint16_t if_id)
8037+
\details
8038+
The event \b SetOptionInterface is created, when the internal function \e tcp_set_option
8039+
sets the network interface for the socket used to connect to an external address.
8040+
This usually happens when the \ref netTCP_SetOption function is executed.
8041+
8042+
\b Value in the Event Recorder shows:
8043+
- \b socket: TCP socket handle for setting the option.
8044+
- \b netif: network interface identifier.
8045+
*/
8046+
80358047
/**
80368048
\fn __STATIC_INLINE void EvrNetTCP_SetOptionWrongOption(int32_t socket, int32_t tcp_option)
80378049
\details
@@ -8830,8 +8842,8 @@ the required socket is not created. This happens when the \ref bind function is
88308842
\fn __STATIC_INLINE void EvrNetBSD_BindSocketAlreadyBound(int32_t sock)
88318843
\details
88328844
The event \b BindSocketAlreadyBound is created when the BSD socket can not bind,
8833-
because the required socket is bound already. This happens when the \ref bind function
8834-
is executed.
8845+
because the required socket is bound already. This happens when the \ref bind or
8846+
\ref setsockopt function is executed.
88358847

88368848
\b Value in the Event Recorder shows:
88378849
- \b sock: BSD socket descriptor for binding.

Documentation/Doxygen/Network/src/revision_history.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
<th>Description</th>
77
</tr>
88
<tr>
9-
<td>V8.0.1</td>
9+
<td>V8.1.0</td>
1010
<td>
11+
- added support for simultaneous outgoing connections via different network interfaces
1112
- fixed handling of Ethernet drivers not supporting multicast address filtering
1213
</td>
1314
</tr>

0 commit comments

Comments
 (0)