Line data Source code
1 : /* fd_pktgen_tile floods a net tile with small outgoing packets. 2 : 3 : Each packet is a minimum size Ethernet frame. IPv4 ethertype is used 4 : with TTL=0 so packets get dropped immediately and don't leak to the 5 : Internet. 6 : 7 : Each packet contains a 16 bit sequence number in the ip4 net_id field 8 : such that each payload is different. Experiments revealed that some NICs 9 : stop sending if we send the same payload over and over again. 10 : (probably protection against a buggy driver melting the network). */ 11 : 12 : #include "../../../../disco/topo/fd_topo.h" 13 : #include "../../../../util/net/fd_eth.h" 14 : 15 : extern uint fd_pktgen_active; 16 : uint fd_pktgen_active = 0U; 17 : 18 : struct fd_pktgen_tile_ctx { 19 : void * out_base; 20 : ulong chunk0; 21 : ulong wmark; 22 : ulong chunk; 23 : ushort tag; 24 : uint fake_dst_ip; 25 : }; 26 : 27 : typedef struct fd_pktgen_tile_ctx fd_pktgen_tile_ctx_t; 28 : 29 : FD_FN_CONST static inline ulong 30 0 : scratch_align( void ) { 31 0 : return alignof(fd_pktgen_tile_ctx_t); 32 0 : } 33 : 34 : FD_FN_PURE static inline ulong 35 0 : scratch_footprint( fd_topo_tile_t const * tile FD_PARAM_UNUSED ) { 36 0 : return sizeof(fd_pktgen_tile_ctx_t); 37 0 : } 38 : 39 : static void 40 : unprivileged_init( fd_topo_t * topo, 41 0 : fd_topo_tile_t * tile ) { 42 0 : fd_pktgen_tile_ctx_t * ctx = fd_topo_obj_laddr( topo, tile->tile_obj_id ); 43 0 : FD_TEST( tile->out_cnt==1UL ); 44 0 : void * out_base = topo->workspaces[ topo->objs[ topo->links[ tile->out_link_id[ 0 ] ].dcache_obj_id ].wksp_id ].wksp; 45 0 : void * out_dcache = topo->links[ tile->out_link_id[ 0 ] ].dcache; 46 0 : ctx->out_base = out_base; 47 0 : ctx->chunk0 = fd_dcache_compact_chunk0( out_base, out_dcache ); 48 0 : ctx->wmark = fd_dcache_compact_wmark( out_base, out_dcache, FD_NET_MTU ); 49 0 : ctx->chunk = ctx->chunk0; 50 0 : ctx->tag = 0UL; 51 0 : ctx->fake_dst_ip = tile->pktgen.fake_dst_ip; 52 : 53 : /* Assume dcache was zero initialized */ 54 0 : } 55 : 56 : static void 57 : before_credit( fd_pktgen_tile_ctx_t * ctx, 58 : fd_stem_context_t * stem, 59 0 : int * charge_busy ) { 60 0 : if( FD_VOLATILE_CONST( fd_pktgen_active )!=1U ) return; 61 : 62 0 : *charge_busy = 1; 63 : 64 : /* Select an arbitrary public IP as the fake destination. The outgoing 65 : packet is not an Internet packet, so it will not reach that 66 : destination. The net tile, however, needs a valid dst IP to select 67 : the dst MAC address. */ 68 0 : ulong sig = fd_disco_netmux_sig( 0U, 0U, ctx->fake_dst_ip, DST_PROTO_OUTGOING, FD_NETMUX_SIG_MIN_HDR_SZ ); 69 : 70 : /* Send an Ethernet frame */ 71 0 : ulong chunk = ctx->chunk; 72 0 : uchar * frame = fd_chunk_to_laddr( ctx->out_base, chunk ); 73 0 : ushort tag = ctx->tag; 74 0 : ulong sz = sizeof(fd_eth_hdr_t) + 46; 75 : 76 : /* Set IPv4 ethertype and minimal IPv4 header for XDP validation */ 77 0 : fd_eth_hdr_t * eth = (fd_eth_hdr_t *)frame; 78 0 : fd_ip4_hdr_t * ip4 = (fd_ip4_hdr_t *)(eth+1); 79 0 : eth->net_type = fd_ushort_bswap( FD_ETH_HDR_TYPE_IP ); 80 0 : ip4->verihl = FD_IP4_VERIHL( 4, 5 ); 81 0 : ip4->ttl = 0; 82 0 : ip4->net_id = tag; 83 : 84 0 : fd_stem_publish( stem, 0UL, sig, chunk, sz, 0UL, 0UL, 0UL ); 85 : 86 : /* Wind up for next iteration */ 87 0 : chunk++; /* Min sz Ethernet frames are exactly FD_CHUNK_SZ */ 88 0 : chunk = fd_ulong_if( chunk>ctx->wmark, ctx->chunk0, chunk ); 89 0 : ctx->tag = tag+1; 90 0 : ctx->chunk = chunk; 91 0 : } 92 : 93 0 : #define STEM_BURST (1UL) 94 : 95 0 : #define STEM_CALLBACK_CONTEXT_TYPE fd_pktgen_tile_ctx_t 96 0 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_pktgen_tile_ctx_t) 97 : 98 0 : #define STEM_CALLBACK_BEFORE_CREDIT before_credit 99 : 100 0 : #define STEM_LAZY ((ulong)1e9) /* max possible */ 101 : 102 : #include "../../../../disco/stem/fd_stem.c" 103 : 104 : fd_topo_run_tile_t fd_tile_pktgen = { 105 : .name = "pktgen", 106 : .scratch_align = scratch_align, 107 : .scratch_footprint = scratch_footprint, 108 : .unprivileged_init = unprivileged_init, 109 : .run = stem_run 110 : };