Line data Source code
1 : /* Topology support routines for the net tile */
2 :
3 : #include "fd_net_tile.h"
4 : #include "../topo/fd_topob.h"
5 : #include "../netlink/fd_netlink_tile.h"
6 : #include "../../app/shared/fd_config.h" /* FIXME layering violation */
7 : #include "../../util/pod/fd_pod_format.h"
8 :
9 : #include <net/if.h>
10 :
11 : static void
12 : setup_xdp_tile( fd_topo_t * topo,
13 : ulong i,
14 : fd_topo_tile_t * netlink_tile,
15 : ulong const * tile_to_cpu,
16 0 : fd_config_net_t const * net_cfg ) {
17 0 : fd_topo_tile_t * tile = fd_topob_tile( topo, "net", "net", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
18 0 : fd_topob_link( topo, "net_netlnk", "net_netlnk", 128UL, 0UL, 0UL );
19 0 : fd_topob_tile_in( topo, "netlnk", 0UL, "metric_in", "net_netlnk", i, FD_TOPOB_UNRELIABLE, FD_TOPOB_POLLED );
20 0 : fd_topob_tile_out( topo, "net", i, "net_netlnk", i );
21 0 : fd_netlink_topo_join( topo, netlink_tile, tile );
22 :
23 0 : fd_topo_obj_t * umem_obj = fd_topob_obj( topo, "dcache", "net_umem" );
24 0 : fd_topob_tile_uses( topo, tile, umem_obj, FD_SHMEM_JOIN_MODE_READ_WRITE );
25 0 : fd_pod_insertf_ulong( topo->props, umem_obj->id, "net.%lu.umem", i );
26 :
27 0 : FD_STATIC_ASSERT( sizeof(tile->xdp.interface)==IF_NAMESIZE, str_bounds );
28 0 : fd_cstr_fini( fd_cstr_append_cstr_safe( fd_cstr_init( tile->xdp.interface ), net_cfg->interface, IF_NAMESIZE-1 ) );
29 0 : tile->net.bind_address = net_cfg->bind_address_parsed;
30 :
31 0 : tile->xdp.tx_flush_timeout_ns = (long)net_cfg->xdp.flush_timeout_micros * 1000L;
32 0 : tile->xdp.xdp_rx_queue_size = net_cfg->xdp.xdp_rx_queue_size;
33 0 : tile->xdp.xdp_tx_queue_size = net_cfg->xdp.xdp_tx_queue_size;
34 0 : tile->xdp.zero_copy = net_cfg->xdp.xdp_zero_copy;
35 0 : fd_memset( tile->xdp.xdp_mode, 0, 4 );
36 0 : fd_memcpy( tile->xdp.xdp_mode, net_cfg->xdp.xdp_mode, strnlen( net_cfg->xdp.xdp_mode, 3 ) ); /* GCC complains about strncpy */
37 :
38 0 : tile->xdp.net.umem_dcache_obj_id= umem_obj->id;
39 0 : tile->xdp.netdev_dbl_buf_obj_id = netlink_tile->netlink.netdev_dbl_buf_obj_id;
40 0 : tile->xdp.fib4_main_obj_id = netlink_tile->netlink.fib4_main_obj_id;
41 0 : tile->xdp.fib4_local_obj_id = netlink_tile->netlink.fib4_local_obj_id;
42 0 : tile->xdp.neigh4_obj_id = netlink_tile->netlink.neigh4_obj_id;
43 0 : tile->xdp.neigh4_ele_obj_id = netlink_tile->netlink.neigh4_ele_obj_id;
44 :
45 : /* Allocate free ring */
46 :
47 0 : tile->xdp.free_ring_depth = tile->xdp.xdp_tx_queue_size;
48 0 : if( i==0 ) {
49 : /* Allocate additional frames for loopback */
50 0 : tile->xdp.free_ring_depth += 16384UL;
51 0 : }
52 0 : }
53 :
54 : static void
55 : setup_sock_tile( fd_topo_t * topo,
56 : ulong const * tile_to_cpu,
57 0 : fd_config_net_t const * net_cfg ) {
58 0 : fd_topo_tile_t * tile = fd_topob_tile( topo, "sock", "sock", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
59 0 : tile->sock.net.bind_address = net_cfg->bind_address_parsed;
60 :
61 0 : if( FD_UNLIKELY( net_cfg->socket.receive_buffer_size>INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.receive_buffer_size]" ));
62 0 : if( FD_UNLIKELY( net_cfg->socket.send_buffer_size >INT_MAX ) ) FD_LOG_ERR(( "invalid [net.socket.send_buffer_size]" ));
63 0 : tile->sock.so_rcvbuf = (int)net_cfg->socket.receive_buffer_size;
64 0 : tile->sock.so_sndbuf = (int)net_cfg->socket.send_buffer_size ;
65 0 : }
66 :
67 : void
68 : fd_topos_net_tiles( fd_topo_t * topo,
69 : ulong net_tile_cnt,
70 : fd_config_net_t const * net_cfg,
71 : ulong netlnk_max_routes,
72 : ulong netlnk_max_peer_routes,
73 : ulong netlnk_max_neighbors,
74 0 : ulong const tile_to_cpu[ FD_TILE_MAX ] ) {
75 : /* net_umem: Packet buffers */
76 0 : fd_topob_wksp( topo, "net_umem" );
77 :
78 : /* Create workspaces */
79 :
80 0 : if( 0==strcmp( net_cfg->provider, "xdp" ) ) {
81 :
82 : /* net: private working memory of the net tiles */
83 0 : fd_topob_wksp( topo, "net" );
84 : /* netlnk: private working memory of the netlnk tile */
85 0 : fd_topob_wksp( topo, "netlnk" );
86 : /* netbase: shared network config (config plane) */
87 0 : fd_topob_wksp( topo, "netbase" );
88 : /* net_netlnk: net->netlnk ARP requests */
89 0 : fd_topob_wksp( topo, "net_netlnk" );
90 :
91 0 : fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
92 0 : fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_peer_routes, netlnk_max_neighbors, net_cfg->interface );
93 :
94 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
95 0 : setup_xdp_tile( topo, i, netlink_tile, tile_to_cpu, net_cfg );
96 0 : }
97 :
98 0 : } else if( 0==strcmp( net_cfg->provider, "socket" ) ) {
99 :
100 : /* sock: private working memory of the sock tiles */
101 0 : fd_topob_wksp( topo, "sock" );
102 :
103 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
104 0 : setup_sock_tile( topo, tile_to_cpu, net_cfg );
105 0 : }
106 :
107 0 : } else {
108 0 : FD_LOG_ERR(( "invalid `net.provider`" ));
109 0 : }
110 0 : }
111 :
112 : static int
113 0 : topo_is_xdp( fd_topo_t * topo ) {
114 : /* FIXME hacky */
115 0 : for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
116 0 : if( 0==strcmp( topo->tiles[ j ].name, "net" ) ) {
117 0 : return 1;
118 0 : }
119 0 : }
120 0 : return 0;
121 0 : }
122 :
123 : static void
124 : add_xdp_rx_link( fd_topo_t * topo,
125 : char const * link_name,
126 : ulong net_kind_id,
127 0 : ulong depth ) {
128 0 : if( FD_UNLIKELY( !topo || !link_name ) ) FD_LOG_ERR(( "NULL args" ));
129 0 : if( FD_UNLIKELY( strlen( link_name )>=sizeof(topo->links[ topo->link_cnt ].name ) ) ) FD_LOG_ERR(( "link name too long: %s", link_name ));
130 0 : if( FD_UNLIKELY( topo->link_cnt>=FD_TOPO_MAX_LINKS ) ) FD_LOG_ERR(( "too many links" ));
131 :
132 0 : ulong kind_id = 0UL;
133 0 : for( ulong i=0UL; i<topo->link_cnt; i++ ) {
134 0 : if( !strcmp( topo->links[ i ].name, link_name ) ) kind_id++;
135 0 : }
136 :
137 0 : fd_topo_link_t * link = &topo->links[ topo->link_cnt ];
138 0 : strncpy( link->name, link_name, sizeof(link->name) );
139 0 : link->id = topo->link_cnt;
140 0 : link->kind_id = kind_id;
141 0 : link->depth = depth;
142 0 : link->mtu = FD_NET_MTU;
143 0 : link->burst = 0UL;
144 :
145 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "mcache", "net_umem" );
146 0 : link->mcache_obj_id = obj->id;
147 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
148 :
149 0 : link->dcache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
150 0 : if( FD_UNLIKELY( link->dcache_obj_id==ULONG_MAX ) ) FD_LOG_ERR(( "umem dcache not found for net %lu", net_kind_id ));
151 :
152 0 : topo->link_cnt++;
153 0 : }
154 :
155 : void
156 : fd_topos_net_rx_link( fd_topo_t * topo,
157 : char const * link_name,
158 : ulong net_kind_id,
159 0 : ulong depth ) {
160 0 : if( topo_is_xdp( topo ) ) {
161 0 : add_xdp_rx_link( topo, link_name, net_kind_id, depth );
162 0 : fd_topob_tile_out( topo, "net", net_kind_id, link_name, net_kind_id );
163 0 : } else {
164 0 : fd_topob_link( topo, link_name, "net_umem", depth, FD_NET_MTU, 64 );
165 0 : fd_topob_tile_out( topo, "sock", net_kind_id, link_name, net_kind_id );
166 0 : }
167 0 : }
168 :
169 : void
170 : fd_topos_tile_in_net( fd_topo_t * topo,
171 : char const * fseq_wksp,
172 : char const * link_name,
173 : ulong link_kind_id,
174 : int reliable,
175 0 : int polled ) {
176 0 : for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
177 0 : if( 0==strcmp( topo->tiles[ j ].name, "net" ) ||
178 0 : 0==strcmp( topo->tiles[ j ].name, "sock" ) ) {
179 0 : fd_topob_tile_in( topo, topo->tiles[ j ].name, topo->tiles[ j ].kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled );
180 0 : }
181 0 : }
182 0 : }
183 :
184 : void
185 : fd_topos_net_tile_finish( fd_topo_t * topo,
186 0 : ulong net_kind_id ) {
187 0 : if( !topo_is_xdp( topo ) ) return;
188 :
189 0 : fd_topo_tile_t * net_tile = &topo->tiles[ fd_topo_find_tile( topo, "net", net_kind_id ) ];
190 :
191 0 : ulong rx_depth = net_tile->xdp.xdp_rx_queue_size;
192 0 : ulong tx_depth = net_tile->xdp.xdp_tx_queue_size;
193 0 : rx_depth += (rx_depth/2UL);
194 0 : tx_depth += (tx_depth/2UL);
195 :
196 0 : if( net_kind_id==0 ) {
197 : /* Double it for loopback XSK */
198 0 : rx_depth *= 2UL;
199 0 : tx_depth *= 2UL;
200 0 : }
201 :
202 0 : ulong cum_frame_cnt = rx_depth + tx_depth;
203 :
204 : /* Count up the depth of all RX mcaches */
205 :
206 0 : for( ulong j=0UL; j<(net_tile->out_cnt); j++ ) {
207 0 : ulong link_id = net_tile->out_link_id[ j ];
208 0 : ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
209 0 : ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
210 0 : if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
211 0 : cum_frame_cnt += depth + 1UL;
212 0 : }
213 :
214 : /* Create a dcache object */
215 :
216 0 : ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
217 0 : FD_TEST( umem_obj_id!=ULONG_MAX );
218 :
219 0 : FD_TEST( net_tile->net.umem_dcache_obj_id > 0 );
220 0 : fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
221 0 : fd_pod_insertf_ulong( topo->props, 2UL, "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
222 0 : fd_pod_insertf_ulong( topo->props, 2048UL, "obj.%lu.mtu", umem_obj_id );
223 0 : }
|