/*************************************************************************** * The recieve thread doesn't transmit packets. Instead, it queues them * up on the transmit thread. Every so often, the transmit thread needs * to flush this transmit queue and send everything. * * This is an inherent design issue trying to send things as batches rather * than individually. It increases latency, but increases performance. We * don't really care about latency. ***************************************************************************/ void flush_packets(struct Adapter *adapter, PACKET_QUEUE *packet_buffers, PACKET_QUEUE *transmit_queue, struct Throttler *throttler, uint64_t *packets_sent) { uint64_t batch_size; unsigned is_queue_empty = 0; while (!is_queue_empty) { /* * Only send a few packets at a time, throttled according to the max * --max-rate set by the user */ batch_size = throttler_next_batch(throttler, *packets_sent); /* * Send a batch of queued packets */ for ( ; batch_size; batch_size--) { int err; struct PacketBuffer *p; /* * Get the next packet from the transmit queue. This packet was * put there by a receive thread, and will contain things like * an ACK or an HTTP request */ err = rte_ring_sc_dequeue(transmit_queue, (void**)&p); if (err) { is_queue_empty = 1; break; /* queue is empty, nothing to send */ } /* * Actually send the packet */ rawsock_send_packet(adapter, p->px, (unsigned)p->length, 1); /* * Now that we are done with the packet, put it on the free list * of buffers that the transmit thread can reuse */ for (err=1; err; ) { err = rte_ring_sp_enqueue(packet_buffers, p); if (err) { LOG(0, "transmit queue full (should be impossible)\n"); pixie_usleep(10000); } } /* * Remember that we sent a packet, which will be used in * throttling. */ (*packets_sent)++; } } }
/*************************************************************************** * Sends the TCP SYN probe packet. * * Step 1: format the packet * Step 2: send it in a portable manner ***************************************************************************/ void rawsock_send_probe( struct Adapter *adapter, unsigned ip_them, unsigned port_them, unsigned ip_me, unsigned port_me, unsigned seqno, unsigned flush, struct TemplateSet *tmplset) { /* * Construct the destination packet */ template_set_target(tmplset, ip_them, port_them, ip_me, port_me, seqno); if (tmplset->length < 60) tmplset->length = 60; /* * Send it */ rawsock_send_packet(adapter, tmplset->px, tmplset->length, flush); }
/*************************************************************************** * Sends the TCP SYN probe packet. * * Step 1: format the packet * Step 2: send it in a portable manner ***************************************************************************/ void rawsock_send_probe( struct Adapter *adapter, unsigned ip_them, unsigned port_them, unsigned ip_me, unsigned port_me, unsigned seqno, unsigned flush, struct TemplateSet *tmplset) { unsigned char px[2048]; size_t packet_length; /* * Construct the destination packet */ template_set_target(tmplset, ip_them, port_them, ip_me, port_me, seqno, px, sizeof(px), &packet_length); /* * Send it */ rawsock_send_packet(adapter, px, (unsigned)packet_length, flush); }