-
Notifications
You must be signed in to change notification settings - Fork 537
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add (G)ARP sender to fix switch broadcast storms #413
base: master
Are you sure you want to change the base?
Conversation
Needed to maintain {mac:ip} assocation on the switch port. This likely fixes many of the reported pkt-gen issues. Also added PHY link state poll ("auto wait") when '-w0' is specified.
Yes, this breaks compilation on FreeBSD |
Can you paste the build error please? |
|
Try now? |
FYI, here there are some ready to use FreeBSD VM images for many hypervisors |
Cool, I'll do that next time. It should be fixed now |
I would merge the contribution now, then fix the hardcoded 6 later. |
apps/pkt-gen/pkt-gen.c
Outdated
int copy = options & OPT_COPY || slot->flags & NS_BUF_CHANGED; | ||
/* sender_body() drops OPT_COPY after starting, but we need to | ||
* copy over any ARP packets lingering in the txring */ | ||
copy |= (old->eh.ether_type == htons(ETHERTYPE_ARP)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is likely a cache miss, I would do that only if -G is specified
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually worse than it looks... Only thread 0 can have (targ->garp != 0) but here all TX threads are checking for no reason. Let me improve this.
(My initial implementation used the "sem[]" area in the netmap_ring to store a dirty flag, for when the ring needs to be checked. It works fine but it's fiddly and I don't think people would like it.)
@@ -1570,6 +1690,13 @@ sender_body(void *data) | |||
nexttime = timespec_add(nexttime, targ->g->tx_period); | |||
wait_time(nexttime); | |||
} | |||
if (targ->garp) { | |||
clock_gettime(CLOCK_REALTIME_PRECISE, &tmptime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to be CLOCK_REALTIME_PRECISE
? COARSE will be enough, and it's faster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, the Linux manpage says COARSE is Linux-specific. I'm sure not what other supported platforms will need a work-around. How about gettimeofday?
@@ -1792,6 +1925,14 @@ receiver_body(void *data) | |||
goto quit; | |||
} | |||
#endif /* !BUSYWAIT */ | |||
if (targ->garp) { | |||
clock_gettime(CLOCK_REALTIME_PRECISE, &tmptime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just going along with what was already being used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I had not seen that the _PRECISE is just a macro that maps back to CLOCK_REALTIME, which is ok.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha, you just beat me to saying that
D("Ready..."); | ||
} else { | ||
D("Wait for phy reset"); | ||
for (i = 5*4; i > 0; i--) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
20?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1000/250*5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are waiting for 5 seconds here (max)
D("Wait up to 5 seconds for phy reset")
The check is now only done on thread 0, and before touching the slot buffer we check if slot->len == sizeof(ARP packet), ie 42, whereas the smallest packet size pkt-gen does without crashing is 50. (This commit also includes a better minimum packet size constraint for the -l argument). Some related code has been tidied up, and I've added #defines for IPv4 and MAC address sizes (IP4_ALEN, ETH_ALEN) to get rid of some magic numbers.
Sorry about the delay. I've updated this now! |
paylen = targ->g->pkt_size - sizeof(*eh) - | ||
(targ->g->af == AF_INET ? sizeof(ip): sizeof(ip6)); | ||
paylen = targ->g->pkt_size - | ||
PKT_OVERHD(targ->g->af, targ->g->virt_header); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkt_size
does not include virt_header
... why are you including that in PKT_OVERHD
?
bcopy(src_mac, pkt->arp4.arp_sha, ETH_ALEN); | ||
bcopy(src_mac, pkt->arp4.arp_tha, ETH_ALEN); | ||
bcopy(&src_ip, pkt->arp4.arp_spa, IP4_ALEN); | ||
bcopy(&src_ip, pkt->arp4.arp_spa, IP4_ALEN); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last two lines are the same... did you mean to use dst_ip
in the second one?
bzero(pkt->arp4.arp_tha, ETH_ALEN); | ||
bcopy(&src_ip, pkt->arp4.arp_spa, IP4_ALEN); | ||
bcopy(&dst_ip, pkt->arp4.arp_tpa, IP4_ALEN); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please move the lines that are common to both if
and else
out of the if-else
construct
|
||
/* sender_body() drops OPT_COPY after starting, but we need | ||
* to copy over any ARP packets lingering in the txring */ | ||
if (!copy && slot->len == arp_size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you replace this condition with options & OPT_GARP
? In this way you make only a single check in the common case.
any news on this? |
I'm travelling for the next 4 weeks. If I get a chance to do any coding, I'll follow this up. Sorry! |
On many switches it's basically impossible to use pkt-gen without sending regular ARPs to maintain association with the switch port. When the PHY resets into netmap mode, the association is usually lost, causing traffic to be broadcast to all ports. This breaks the receiver and destroys network performance.
Also added link state auto wait option when you specify -w0.
I have tested on Linux boxes only, so there is a chance of broken builds for other platforms. Could someone check FreeBSD etc?