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