tools: netmap: pkt-gen: check packet length against interface MTU
Validate the value of the -l argument (packet length) against the MTU of the netmap port. In case the netmap port does not refer to a physical interface (e.g. VALE port or pipe), then the netmap buffer size is used as MTU. This change also sets a better default value for the -M option, so that pkt-gen uses the largest possible fragments in case of multi-slot packets. Differential Revision: https://reviews.freebsd.org/D18436
This commit is contained in:
parent
1becbc64f8
commit
9e53f3bd67
@ -195,7 +195,7 @@ struct virt_header {
|
|||||||
uint8_t fields[VIRT_HDR_MAX];
|
uint8_t fields[VIRT_HDR_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_BODYSIZE 16384
|
#define MAX_BODYSIZE 65536
|
||||||
|
|
||||||
struct pkt {
|
struct pkt {
|
||||||
struct virt_header vh;
|
struct virt_header vh;
|
||||||
@ -238,7 +238,6 @@ struct mac_range {
|
|||||||
|
|
||||||
/* ifname can be netmap:foo-xxxx */
|
/* ifname can be netmap:foo-xxxx */
|
||||||
#define MAX_IFNAMELEN 64 /* our buffer for ifname */
|
#define MAX_IFNAMELEN 64 /* our buffer for ifname */
|
||||||
//#define MAX_PKTSIZE 1536
|
|
||||||
#define MAX_PKTSIZE MAX_BODYSIZE /* XXX: + IP_HDR + ETH_HDR */
|
#define MAX_PKTSIZE MAX_BODYSIZE /* XXX: + IP_HDR + ETH_HDR */
|
||||||
|
|
||||||
/* compact timestamp to fit into 60 byte packet. (enough to obtain RTT) */
|
/* compact timestamp to fit into 60 byte packet. (enough to obtain RTT) */
|
||||||
@ -263,7 +262,7 @@ struct glob_arg {
|
|||||||
int forever;
|
int forever;
|
||||||
uint64_t npackets; /* total packets to send */
|
uint64_t npackets; /* total packets to send */
|
||||||
int frags; /* fragments per packet */
|
int frags; /* fragments per packet */
|
||||||
u_int mtu; /* size of each fragment */
|
u_int frag_size; /* size of each fragment */
|
||||||
int nthreads;
|
int nthreads;
|
||||||
int cpus; /* cpus used for running */
|
int cpus; /* cpus used for running */
|
||||||
int system_cpus; /* cpus on the system */
|
int system_cpus; /* cpus on the system */
|
||||||
@ -308,6 +307,11 @@ struct glob_arg {
|
|||||||
};
|
};
|
||||||
enum dev_type { DEV_NONE, DEV_NETMAP, DEV_PCAP, DEV_TAP };
|
enum dev_type { DEV_NONE, DEV_NETMAP, DEV_PCAP, DEV_TAP };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TD_TYPE_SENDER = 1,
|
||||||
|
TD_TYPE_RECEIVER,
|
||||||
|
TD_TYPE_OTHER,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arguments for a new thread. The same structure is used by
|
* Arguments for a new thread. The same structure is used by
|
||||||
@ -509,6 +513,42 @@ extract_mac_range(struct mac_range *r)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_if_mtu(const struct glob_arg *g)
|
||||||
|
{
|
||||||
|
char ifname[IFNAMSIZ];
|
||||||
|
struct ifreq ifreq;
|
||||||
|
int s, ret;
|
||||||
|
|
||||||
|
if (!strncmp(g->ifname, "netmap:", 7) && !strchr(g->ifname, '{')
|
||||||
|
&& !strchr(g->ifname, '}')) {
|
||||||
|
/* Parse the interface name and ask the kernel for the
|
||||||
|
* MTU value. */
|
||||||
|
strncpy(ifname, g->ifname+7, IFNAMSIZ-1);
|
||||||
|
ifname[strcspn(ifname, "-*^{}/@")] = '\0';
|
||||||
|
|
||||||
|
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (s < 0) {
|
||||||
|
D("socket() failed: %s", strerror(errno));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ifreq, 0, sizeof(ifreq));
|
||||||
|
strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
|
||||||
|
|
||||||
|
ret = ioctl(s, SIOCGIFMTU, &ifreq);
|
||||||
|
if (ret) {
|
||||||
|
D("ioctl(SIOCGIFMTU) failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ifreq.ifr_mtu;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is a pipe or a VALE port, where the MTU is very large,
|
||||||
|
* so we use some practical limit. */
|
||||||
|
return 65536;
|
||||||
|
}
|
||||||
|
|
||||||
static struct targ *targs;
|
static struct targ *targs;
|
||||||
static int global_nthreads;
|
static int global_nthreads;
|
||||||
|
|
||||||
@ -1581,18 +1621,18 @@ sender_body(void *data)
|
|||||||
#endif /* NO_PCAP */
|
#endif /* NO_PCAP */
|
||||||
} else {
|
} else {
|
||||||
int tosend = 0;
|
int tosend = 0;
|
||||||
u_int bufsz, mtu = targ->g->mtu;
|
u_int bufsz, frag_size = targ->g->frag_size;
|
||||||
|
|
||||||
nifp = targ->nmd->nifp;
|
nifp = targ->nmd->nifp;
|
||||||
txring = NETMAP_TXRING(nifp, targ->nmd->first_tx_ring);
|
txring = NETMAP_TXRING(nifp, targ->nmd->first_tx_ring);
|
||||||
bufsz = txring->nr_buf_size;
|
bufsz = txring->nr_buf_size;
|
||||||
if (bufsz < mtu)
|
if (bufsz < frag_size)
|
||||||
mtu = bufsz;
|
frag_size = bufsz;
|
||||||
targ->frag_size = targ->g->pkt_size / targ->frags;
|
targ->frag_size = targ->g->pkt_size / targ->frags;
|
||||||
if (targ->frag_size > mtu) {
|
if (targ->frag_size > frag_size) {
|
||||||
targ->frags = targ->g->pkt_size / mtu;
|
targ->frags = targ->g->pkt_size / frag_size;
|
||||||
targ->frag_size = mtu;
|
targ->frag_size = frag_size;
|
||||||
if (targ->g->pkt_size % mtu != 0)
|
if (targ->g->pkt_size % frag_size != 0)
|
||||||
targ->frags++;
|
targ->frags++;
|
||||||
}
|
}
|
||||||
D("frags %u frag_size %u", targ->frags, targ->frag_size);
|
D("frags %u frag_size %u", targ->frags, targ->frag_size);
|
||||||
@ -2441,12 +2481,6 @@ usage(int errcode)
|
|||||||
exit(errcode);
|
exit(errcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
|
||||||
TD_TYPE_SENDER = 1,
|
|
||||||
TD_TYPE_RECEIVER,
|
|
||||||
TD_TYPE_OTHER,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
start_threads(struct glob_arg *g) {
|
start_threads(struct glob_arg *g) {
|
||||||
int i;
|
int i;
|
||||||
@ -2779,8 +2813,8 @@ main(int arc, char **argv)
|
|||||||
g.cpus = 1; /* default */
|
g.cpus = 1; /* default */
|
||||||
g.forever = 1;
|
g.forever = 1;
|
||||||
g.tx_rate = 0;
|
g.tx_rate = 0;
|
||||||
g.frags =1;
|
g.frags = 1;
|
||||||
g.mtu = 1500;
|
g.frag_size = (u_int)-1; /* use the netmap buffer size by default */
|
||||||
g.nmr_config = "";
|
g.nmr_config = "";
|
||||||
g.virt_header = 0;
|
g.virt_header = 0;
|
||||||
g.wait_link = 2; /* wait 2 seconds for physical ports */
|
g.wait_link = 2; /* wait 2 seconds for physical ports */
|
||||||
@ -2824,7 +2858,7 @@ main(int arc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
g.mtu = atoi(optarg);
|
g.frag_size = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
@ -3104,6 +3138,16 @@ main(int arc, char **argv)
|
|||||||
// continue, fail later
|
// continue, fail later
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g.td_type == TD_TYPE_SENDER) {
|
||||||
|
int mtu = get_if_mtu(&g);
|
||||||
|
|
||||||
|
if (mtu > 0 && g.pkt_size > mtu) {
|
||||||
|
D("pkt_size (%d) must be <= mtu (%d)",
|
||||||
|
g.pkt_size, mtu);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
struct netmap_if *nifp = g.nmd->nifp;
|
struct netmap_if *nifp = g.nmd->nifp;
|
||||||
struct nmreq *req = &g.nmd->req;
|
struct nmreq *req = &g.nmd->req;
|
||||||
|
Loading…
Reference in New Issue
Block a user