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_neighbors,
73 0 : ulong const tile_to_cpu[ FD_TILE_MAX ] ) {
74 : /* net_umem: Packet buffers */
75 0 : fd_topob_wksp( topo, "net_umem" );
76 :
77 : /* Create workspaces */
78 :
79 0 : if( 0==strcmp( net_cfg->provider, "xdp" ) ) {
80 :
81 : /* net: private working memory of the net tiles */
82 0 : fd_topob_wksp( topo, "net" );
83 : /* netlnk: private working memory of the netlnk tile */
84 0 : fd_topob_wksp( topo, "netlnk" );
85 : /* netbase: shared network config (config plane) */
86 0 : fd_topob_wksp( topo, "netbase" );
87 : /* net_netlnk: net->netlnk ARP requests */
88 0 : fd_topob_wksp( topo, "net_netlnk" );
89 :
90 0 : fd_topo_tile_t * netlink_tile = fd_topob_tile( topo, "netlnk", "netlnk", "metric_in", tile_to_cpu[ topo->tile_cnt ], 0, 0 );
91 0 : fd_netlink_topo_create( netlink_tile, topo, netlnk_max_routes, netlnk_max_neighbors, net_cfg->interface );
92 :
93 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
94 0 : setup_xdp_tile( topo, i, netlink_tile, tile_to_cpu, net_cfg );
95 0 : }
96 :
97 0 : } else if( 0==strcmp( net_cfg->provider, "socket" ) ) {
98 :
99 : /* sock: private working memory of the sock tiles */
100 0 : fd_topob_wksp( topo, "sock" );
101 :
102 0 : for( ulong i=0UL; i<net_tile_cnt; i++ ) {
103 0 : setup_sock_tile( topo, tile_to_cpu, net_cfg );
104 0 : }
105 :
106 0 : } else {
107 0 : FD_LOG_ERR(( "invalid `net.provider`" ));
108 0 : }
109 0 : }
110 :
111 : static int
112 0 : topo_is_xdp( fd_topo_t * topo ) {
113 : /* FIXME hacky */
114 0 : for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
115 0 : if( 0==strcmp( topo->tiles[ j ].name, "net" ) ) {
116 0 : return 1;
117 0 : }
118 0 : }
119 0 : return 0;
120 0 : }
121 :
122 : static void
123 : add_xdp_rx_link( fd_topo_t * topo,
124 : char const * link_name,
125 : ulong net_kind_id,
126 0 : ulong depth ) {
127 0 : if( FD_UNLIKELY( !topo || !link_name ) ) FD_LOG_ERR(( "NULL args" ));
128 0 : if( FD_UNLIKELY( strlen( link_name )>=sizeof(topo->links[ topo->link_cnt ].name ) ) ) FD_LOG_ERR(( "link name too long: %s", link_name ));
129 0 : if( FD_UNLIKELY( topo->link_cnt>=FD_TOPO_MAX_LINKS ) ) FD_LOG_ERR(( "too many links" ));
130 :
131 0 : ulong kind_id = 0UL;
132 0 : for( ulong i=0UL; i<topo->link_cnt; i++ ) {
133 0 : if( !strcmp( topo->links[ i ].name, link_name ) ) kind_id++;
134 0 : }
135 :
136 0 : fd_topo_link_t * link = &topo->links[ topo->link_cnt ];
137 0 : strncpy( link->name, link_name, sizeof(link->name) );
138 0 : link->id = topo->link_cnt;
139 0 : link->kind_id = kind_id;
140 0 : link->depth = depth;
141 0 : link->mtu = FD_NET_MTU;
142 0 : link->burst = 0UL;
143 :
144 0 : fd_topo_obj_t * obj = fd_topob_obj( topo, "mcache", "net_umem" );
145 0 : link->mcache_obj_id = obj->id;
146 0 : FD_TEST( fd_pod_insertf_ulong( topo->props, depth, "obj.%lu.depth", obj->id ) );
147 :
148 0 : link->dcache_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
149 0 : if( FD_UNLIKELY( link->dcache_obj_id==ULONG_MAX ) ) FD_LOG_ERR(( "umem dcache not found for net %lu", net_kind_id ));
150 :
151 0 : topo->link_cnt++;
152 0 : }
153 :
154 : void
155 : fd_topos_net_rx_link( fd_topo_t * topo,
156 : char const * link_name,
157 : ulong net_kind_id,
158 0 : ulong depth ) {
159 0 : if( topo_is_xdp( topo ) ) {
160 0 : add_xdp_rx_link( topo, link_name, net_kind_id, depth );
161 0 : fd_topob_tile_out( topo, "net", net_kind_id, link_name, net_kind_id );
162 0 : } else {
163 0 : fd_topob_link( topo, link_name, "net_umem", depth, FD_NET_MTU, 64 );
164 0 : fd_topob_tile_out( topo, "sock", net_kind_id, link_name, net_kind_id );
165 0 : }
166 0 : }
167 :
168 : void
169 : fd_topos_tile_in_net( fd_topo_t * topo,
170 : char const * fseq_wksp,
171 : char const * link_name,
172 : ulong link_kind_id,
173 : int reliable,
174 0 : int polled ) {
175 0 : for( ulong j=0UL; j<(topo->tile_cnt); j++ ) {
176 0 : if( 0==strcmp( topo->tiles[ j ].name, "net" ) ||
177 0 : 0==strcmp( topo->tiles[ j ].name, "sock" ) ) {
178 0 : fd_topob_tile_in( topo, topo->tiles[ j ].name, topo->tiles[ j ].kind_id, fseq_wksp, link_name, link_kind_id, reliable, polled );
179 0 : }
180 0 : }
181 0 : }
182 :
183 : void
184 : fd_topos_net_tile_finish( fd_topo_t * topo,
185 0 : ulong net_kind_id ) {
186 0 : if( !topo_is_xdp( topo ) ) return;
187 :
188 0 : fd_topo_tile_t * net_tile = &topo->tiles[ fd_topo_find_tile( topo, "net", net_kind_id ) ];
189 :
190 0 : ulong rx_depth = net_tile->xdp.xdp_rx_queue_size;
191 0 : ulong tx_depth = net_tile->xdp.xdp_tx_queue_size;
192 0 : rx_depth += (rx_depth/2UL);
193 0 : tx_depth += (tx_depth/2UL);
194 :
195 0 : if( net_kind_id==0 ) {
196 : /* Double it for loopback XSK */
197 0 : rx_depth *= 2UL;
198 0 : tx_depth *= 2UL;
199 0 : }
200 :
201 0 : ulong cum_frame_cnt = rx_depth + tx_depth;
202 :
203 : /* Count up the depth of all RX mcaches */
204 :
205 0 : for( ulong j=0UL; j<(net_tile->out_cnt); j++ ) {
206 0 : ulong link_id = net_tile->out_link_id[ j ];
207 0 : ulong mcache_obj_id = topo->links[ link_id ].mcache_obj_id;
208 0 : ulong depth = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "obj.%lu.depth", mcache_obj_id );
209 0 : if( FD_UNLIKELY( depth==ULONG_MAX ) ) FD_LOG_ERR(( "Didn't find depth for mcache %s", topo->links[ link_id ].name ));
210 0 : cum_frame_cnt += depth + 1UL;
211 0 : }
212 :
213 : /* Create a dcache object */
214 :
215 0 : ulong umem_obj_id = fd_pod_queryf_ulong( topo->props, ULONG_MAX, "net.%lu.umem", net_kind_id );
216 0 : FD_TEST( umem_obj_id!=ULONG_MAX );
217 :
218 0 : FD_TEST( net_tile->net.umem_dcache_obj_id > 0 );
219 0 : fd_pod_insertf_ulong( topo->props, cum_frame_cnt, "obj.%lu.depth", umem_obj_id );
220 0 : fd_pod_insertf_ulong( topo->props, 2UL, "obj.%lu.burst", umem_obj_id ); /* 4096 byte padding */
221 0 : fd_pod_insertf_ulong( topo->props, 2048UL, "obj.%lu.mtu", umem_obj_id );
222 0 : }
|