Repository: secdev/scapy

Issue:
sendpfast not passing float to tcpreplay
### Brief description

When sending a float for a fractional PPS, nothing is sent. Taking a look, I noticed tcpreplay doesn't get started. When I sent a PPS with a float of 10.5, I see tcpreplay start with a PPS of just 10.

Looking at the code:
Line 516 has the following
"--pps %i" % pps

If doing something like: f"--pps {pps}" instead, it will pass the float as intended to the call. I verified I can run the tcpreplay command manually using 10.5 no issues, but using sendpfast it doesn't pass to tcpreplay properly.

### Scapy version

2.5.0

### Python version

3.7

### Operating system

Linux 4.14 Amazon EC2 AMI

### Additional environment information

_No response_

### How to reproduce

Pass a fractional float into the PPS value of sendpfast. Under 1 I don't believe tcpreplay starts at all. Over 1, I notice it rounds it instead of using the full float passed.



### Actual result

tcpreplay with 10 as PPS

### Expected result

tcpreplay with 10.5 as PPS

### Related resources

_No response_


Discussion:
Could simply change %i to %f to allow passing a float as indicated in the sendpfast input argument that shows pps as a float.

To fix this locally for my project, I am simply doing a sed on this file change the i to an f in the Dockerfile process, which corrects the issue.
After this change, have you checked behavior thoroughly when using integer instead, with %f?
> After this change, have you checked behavior thoroughly when using integer instead, with %f?

Not yet. I did verify doing a sed on my site packages to change this results in the code starting tcpreplay with the float inserted. The tcpreplay docs as well as scrapy docs state this value to be a float. Tomorrow I’ll be running large traffic generation tests to confirm it properly generates the traffic.
> After this change, have you checked behavior thoroughly when using integer instead, with %f?

Ran some tests this morning and looks good using a float, which both sendpfast and tcpreplay say the PPS field to be a float. Tested using a UDP stream with .5 PPS and verified in tcpdump I seen one packet every other second. I'm calling it good and will leave my sed patch in place for now. I imagine most using scapy aren't looking at this low level amount of packets sent, but in my project we are generating traffic to match other traffic profiles we have for network testing. If using this for security testing, likely not going to come up.
@jbreed thanks for testing! do you feel like sending a PR?
> @jbreed thanks for testing! do you feel like sending a PR?

Sorry, forgot to check back on this. Our Dockerfile has been doing a sed to replace this, which I have continued to use for our traffic generators. Given this is used to mock up traffic based on traffic profiles needed that fine control to properly analyze traffic flows.

I will try and get a request submitted this evening to update it.

Resolving patch:
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -515,7 +515,7 @@ def sendpfast(x,  # type: _PacketIterable
         iface = conf.iface
     argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)]
     if pps is not None:
-        argv.append("--pps=%i" % pps)
+        argv.append("--pps=%f" % pps)
     elif mbps is not None:
         argv.append("--mbps=%f" % mbps)
     elif realtime is not None:


Test patch: