* Program to test/use the 'low level Ethernet debugging features'
@ 2012-02-17 18:12 Ben Greear
0 siblings, 0 replies; only message in thread
From: Ben Greear @ 2012-02-17 18:12 UTC (permalink / raw)
To: netdev; +Cc: Jeff Kirsher, Brown, Aaron F
[-- Attachment #1: Type: text/plain, Size: 491 bytes --]
I'm attaching a small program I wrote to test the 'send custom fcs'
patches. You can also test the rx-fcs and rx-all logic by making
sure that the NIC properly handles the packets with bad FCS.
For those that might have seen a previous version of this, I added
the ability to specify the dest mac address which means you don't
have to put the receiving NIC into PROMISC mode now.
Thanks,
Ben
--
Ben Greear <greearb@candelatech•com>
Candela Technologies Inc http://www.candelatech.com
[-- Attachment #2: nofcs.c --]
[-- Type: text/plain, Size: 5748 bytes --]
/** This tool can be used to send packets with custom (ie, bad) Ethernet
* Frame Checksum.
*
* This requires the 'Low-level Ethernet debugging features.' patch series,
* which supports e100, e1000, and e1000e drivers. Support for igb and
* hopefully ixgbe will be added soon.
*
* To compile: gcc -Wall nofcs.c -o nofcs
*
* Usage:
* Send 10 packets out eth0 with bad FCS:
* ./nofcs -i eth0 -dm 00:11:22:33:44:55
*
* To receive the packets, you could use a version of ethtool that supports
* the feature strings logic posted by Michal Miroslaw and enable 'rx-all'
* and optionally: 'rx-fcs'.
*
* The patch for ethtool is posted here:
* http://patchwork.ozlabs.org/patch/96374/
*
* This code was written by Ben Greear <greearb@candelatech•com>
* and is hereby released into the public domain with no restrictions.
* February 17, 2012.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/if_packet.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <net/if.h>
static char* dev = NULL;
static int count = 10;
static int bytes = 128; // not counting fcs
static unsigned int fcs = 0xdeadbeef;
static char* dst_mac = NULL;
static void print_usage() {
printf("usage: -i [dev-name] -b [byte-count] -c [packet-count] -f [fcs] -dm [dest-mac]\n"
"Example: nofcs -i eth0 -b 128 -c 10 -dm 00:11:22:33:44:55 -f 0xdeadbeef\n\n");
}
int createPacketSocket(const char* dev_name, int ether_type) {
int s = socket(PF_PACKET, SOCK_RAW, htons(ether_type));
int r; //retval
struct sockaddr_ll myaddr;
if (s < 0) {
perror("socket(PF_PACKET)");
exit(1);
}
memset(&myaddr, '\0', sizeof(myaddr));
myaddr.sll_family = AF_PACKET;
myaddr.sll_protocol = htons(ether_type);
myaddr.sll_ifindex = if_nametoindex(dev_name);
if (myaddr.sll_ifindex == 0) {
perror("if_nametoindex");
exit(1);
}
r = bind(s, (struct sockaddr*)(&myaddr), sizeof(myaddr));
if (r < 0) {
perror("bind");
exit(1);
}
return s;
}
static int toMacString(unsigned char* rslt_mac, const char* raw_mac) {
/* Turn HEX into bytes. First, gather all the useful HEX */
char tmp[12]; /* More than 12 is useless, at least right now */
char c;
int j = 0; /* tmp's index. */
int i;
char tmp_bt[3];
for (i = 0; i<strlen(raw_mac); i++) {
c = toupper(raw_mac[i]);
if (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F'))) {
tmp[j] = c;
if (j == 11) {
break; /* done */
}
j++;
}
else {
if ((c == ':') || (c == ' ') || (c == '.')) {
/* Ok, valid divider */
}
else {
printf("ERROR: Invalid characters found in the MAC input string: %s index: %i character: %c\n",
raw_mac, i, c);
exit(1);
}
}
}
if (j != 11) {
printf("ERROR: Not enough HEX values in the input string.\n");
exit(1);
}
for (i = 0; i<6; i++) {
tmp_bt[0] = tmp[i*2];
tmp_bt[1] = tmp[i*2 +1];
tmp_bt[2] = 0;
rslt_mac[i] = (char)(strtol(tmp_bt, NULL, 16) & 0xFF); /* base 16 (HEX) */
}
return 0;
}//toMacString
int main(int argc, char **argv) {
int i;
int s;
unsigned char* buf;
unsigned int opt = 1;
dev = strdup("eth0");
dst_mac = strdup("00:11:22:33:44:55");
for (i = 1; i<argc; i++) {
/* Each argument requires a value */
if (argc < i+1) {
printf("ERROR: Not enough arguments, argc: %i i: %i\n",
argc, i);
print_usage();
exit(1);
}
if (strcasecmp(argv[i], "-i") == 0) {
free(dev);
dev = strdup(argv[i + 1]);
}
else if (strcasecmp(argv[i], "-c") == 0) {
count = strtoll(argv[i + 1], NULL, 0);
}
else if (strcasecmp(argv[i], "-b") == 0) {
bytes = strtoll(argv[i + 1], NULL, 0);
}
else if (strcasecmp(argv[i], "-f") == 0) {
fcs = strtoll(argv[i + 1], NULL, 0);
}
else if (strcasecmp(argv[i], "-dm") == 0) {
free(dst_mac);
dst_mac = strdup(argv[i + 1]);
}
else {
printf("Unknown argument: %s\n", argv[i]);
print_usage();
exit(1);
}
i++;
}
if (bytes < 14) {
printf("ERROR: Need at least 14 bytes of payload for ether header.\n");
exit(1);
}
if (bytes < 60) {
printf("WARNING: Most drivers require Ethernet frame of at least 60 bytes.\n");
}
/* Just use some made-up eth type */
s = createPacketSocket(dev, 0x1111);
if (setsockopt(s, SOL_SOCKET, 42 /* SO_NOFCS, see asm-x86/socket.h in linux kernel*/,
(char*)&opt, sizeof(opt)) < 0) {
perror("setsockopt SO_NOFCS");
printf("Kernel doesn't support the NO_FCS feature it seems.\n");
exit(2);
}
buf = malloc(bytes + 4);
/* mostly hard-code an ether header */
toMacString(buf, dst_mac);
/* src 00:22:22:22:22:22 */
buf[6] = 0;
for (i = 7; i<11; i++)
buf[i] = 0x22;
/* ether type */
buf[12] = 0x11;
buf[13] = 0x11;
for (i = 14; i<bytes; i++) {
buf[i] = i;
}
/* append our FCS */
buf[bytes] = (fcs >> 24) & 0xff;
buf[bytes + 1] = (fcs >> 16) & 0xff;
buf[bytes + 2] = (fcs >> 8) & 0xff;
buf[bytes + 3] = fcs & 0xff;
for (i = 0; i<count; i++) {
if (sendto(s, buf, bytes + 4, 0, NULL, 0) < 0) {
perror("sendto");
exit(1);
}
}
printf("Sent %i packets.\n", count);
/* Clean up, just to be nice */
free(dst_mac);
free(dev);
free(buf);
close(s);
exit(0);
}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-02-17 18:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-17 18:12 Program to test/use the 'low level Ethernet debugging features' Ben Greear
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox