AF_XDP-interaction: cmdline options for MAC-addresses

Change Ethernet MAC in transmitted frames
 via cmdline options (-G|--tx-dmac) or (-H|--tx-smac)

Based on suggestion from: Ong Boon Leong <boon.leong.ong@intel.com>
 https://lore.kernel.org/all/20211124091821.3916046-3-boon.leong.ong@intel.com/

Suggested-by: Ong Boon Leong <boon.leong.ong@intel.com>
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
This commit is contained in:
Jesper Dangaard Brouer
2021-12-14 13:52:27 +01:00
parent b71f7f8cac
commit f3d5d3ca93
3 changed files with 50 additions and 23 deletions

View File

@@ -291,6 +291,12 @@ static const struct option_wrapper long_options[] = {
{{"busy-poll", no_argument, NULL, 'B' },
"Enable socket prefer NAPI busy-poll mode (remember adjust sysctl too)"},
{{"tx-dmac", required_argument, NULL, 'G' },
"Dest MAC addr of TX frame in aa:bb:cc:dd:ee:ff format", "aa:bb:cc:dd:ee:ff"},
{{"tx-smac", required_argument, NULL, 'H' },
"Src MAC addr of TX frame in aa:bb:cc:dd:ee:ff format", "aa:bb:cc:dd:ee:ff"},
{{0, 0, NULL, 0 }, NULL, false}
};
@@ -562,11 +568,9 @@ static inline void csum_replace2(__sum16 *sum, __be16 old, __be16 new)
*/
static uint8_t base_pkt_data[FRAME_SIZE];
static struct ether_addr opt_tx_smac =
{{ 0x24, 0x5e, 0xbe, 0x57, 0xf1, 0x64 }};
static struct ether_addr opt_tx_dmac =
//{{ 0x00, 0x1b, 0x21, 0xbb, 0x9a, 0x82 }};
{{ 0xbc, 0xee, 0x7b, 0xda, 0xc2, 0x62 }};
/* Can be changed via cmdline options (-G|--tx-dmac) or (-H|--tx-smac) */
static struct ether_addr default_tx_smac = {{ 0x24, 0x5e, 0xbe, 0x57, 0xf1, 0x64 }};
static struct ether_addr default_tx_dmac = {{ 0xbc, 0xee, 0x7b, 0xda, 0xc2, 0x62 }};
#define MIN_PKT_SIZE 64
static uint16_t opt_pkt_size = MIN_PKT_SIZE;
@@ -580,11 +584,13 @@ static uint16_t opt_pkt_size = MIN_PKT_SIZE;
#define UDP_PKT_SIZE (IP_PKT_SIZE - sizeof(struct iphdr))
#define UDP_PKT_DATA_SIZE (UDP_PKT_SIZE - sizeof(struct udphdr))
static void gen_eth_hdr(struct ethhdr *eth_hdr)
static void gen_eth_hdr(struct config *cfg, struct ethhdr *eth_hdr)
{
/* Ethernet header */
memcpy(eth_hdr->h_dest , &opt_tx_dmac, ETH_ALEN);
memcpy(eth_hdr->h_source, &opt_tx_smac, ETH_ALEN);
/* Ethernet header:
* Can be changed via cmdline options (-G|--tx-dmac) or (-H|--tx-smac)
*/
memcpy(eth_hdr->h_dest , &cfg->opt_tx_dmac, ETH_ALEN);
memcpy(eth_hdr->h_source, &cfg->opt_tx_smac, ETH_ALEN);
eth_hdr->h_proto = htons(ETH_P_IP);
}
@@ -652,7 +658,7 @@ static void gen_udp_hdr(struct udphdr *udp_hdr, struct iphdr *ip_hdr)
IPPROTO_UDP, (__u16 *)udp_hdr);
}
static void gen_base_pkt(uint8_t *pkt_ptr)
static void gen_base_pkt(struct config *cfg, uint8_t *pkt_ptr)
{
struct ethhdr *eth_hdr = (struct ethhdr *)pkt_ptr;
struct iphdr *ip_hdr = (struct iphdr *)(pkt_ptr +
@@ -661,7 +667,7 @@ static void gen_base_pkt(uint8_t *pkt_ptr)
sizeof(struct ethhdr) +
sizeof(struct iphdr));
gen_eth_hdr(eth_hdr);
gen_eth_hdr(cfg, eth_hdr);
gen_ip_hdr(ip_hdr);
gen_udp_hdr(udp_hdr, ip_hdr);
}
@@ -823,7 +829,7 @@ static void print_pkt_info(uint8_t *pkt, uint32_t len)
}
}
static void tx_pkt(struct xsk_socket_info *xsk)
static void tx_pkt(struct config *cfg, struct xsk_socket_info *xsk)
{
struct xsk_umem_info *umem = xsk->umem;
uint64_t pkt_addr = mem_alloc_umem_frame(&umem->mem);
@@ -834,7 +840,7 @@ static void tx_pkt(struct xsk_socket_info *xsk)
pr_addr_info(__func__, pkt_addr, umem);
pkt = xsk_umem__get_data(umem->buffer, pkt_addr);
gen_base_pkt(pkt);
gen_base_pkt(cfg, pkt);
{
uint32_t tx_idx = 0;
@@ -857,7 +863,7 @@ static void tx_pkt(struct xsk_socket_info *xsk)
/* Generate some fake packets (in umem area). Real system will deliver TX
* packets containing the needed control information.
*/
static int invent_tx_pkts(struct xsk_umem_info *umem,
static int invent_tx_pkts(struct config *cfg, struct xsk_umem_info *umem,
const unsigned int n, struct xdp_desc pkts[n])
{
uint32_t len = opt_pkt_size;
@@ -879,7 +885,7 @@ static int invent_tx_pkts(struct xsk_umem_info *umem,
/* Write into packet memory area */
pkt_data = xsk_umem__get_data(umem->buffer, pkt_addr);
gen_base_pkt(pkt_data);
gen_base_pkt(cfg, pkt_data);
pkts[i] = desc;
}
@@ -1173,8 +1179,8 @@ static void tx_cyclic_and_rx_process(struct config *cfg,
// Choosing xsk id 0
struct xsk_socket_info *xsk = xsks->sockets[0];
/* Get packets for first iteration */
tx_nr = invent_tx_pkts(xsk->umem, batch_nr, tx_pkts);
/* Get packets for *first* iteration */
tx_nr = invent_tx_pkts(cfg, xsk->umem, batch_nr, tx_pkts);
interval.tv_sec = period / USEC_PER_SEC;
interval.tv_nsec = (period % USEC_PER_SEC) * 1000;
@@ -1233,8 +1239,8 @@ static void tx_cyclic_and_rx_process(struct config *cfg,
next.tv_nsec += interval.tv_nsec;
tsnorm(&next);
/* Get packets for next iteration */
tx_nr = invent_tx_pkts(xsk->umem, batch_nr, tx_pkts);
/* Get packets for *next* iteration */
tx_nr = invent_tx_pkts(cfg, xsk->umem, batch_nr, tx_pkts);
/* Empty RX queues */
rx_avail_packets(xsks);
@@ -1366,6 +1372,8 @@ int main(int argc, char **argv)
.progsec = "xdp_sock",
.xsk_wakeup_mode = true, /* Default, change via --spin */
.xsk_if_queue = -1,
.opt_tx_dmac = default_tx_dmac,
.opt_tx_smac = default_tx_smac,
};
pthread_t stats_poll_thread;
struct xsk_umem_info *umem;
@@ -1484,7 +1492,7 @@ int main(int argc, char **argv)
}
/* Generate packets to TX */
gen_base_pkt((uint8_t*)&base_pkt_data);
gen_base_pkt(&cfg, (uint8_t*)&base_pkt_data);
/* Open and configure the AF_XDP (xsk) socket(s) */
for (i = 0; i < xsks.num; i++) {
@@ -1538,7 +1546,7 @@ int main(int argc, char **argv)
* be initilized correctly?
*/
//sleep(3);
// tx_pkt(xsks.sockets[0]);
// tx_pkt(&cfg, xsks.sockets[0]);
/* Receive and count packets than drop them */
// rx_and_process(&cfg, &xsks);

View File

@@ -4,6 +4,7 @@
#include <net/if.h>
#include <linux/types.h>
#include <stdbool.h>
#include <netinet/ether.h> /* struct ether_addr */
struct config {
__u32 xdp_flags;
@@ -27,6 +28,8 @@ struct config {
int sched_prio;
int sched_policy;
bool opt_busy_poll;
struct ether_addr opt_tx_smac;
struct ether_addr opt_tx_dmac;
};
/* Defined in common_params.o */

View File

@@ -29,7 +29,7 @@ void _print_options(const struct option_wrapper *long_options, bool required)
if (long_options[i].required != required)
continue;
if (long_options[i].option.val > 64) /* ord('A') = 65 */
if (long_options[i].option.val > 64) /* ord('A') = 65 = 0x41 */
printf(" -%c,", long_options[i].option.val);
else
printf(" ");
@@ -96,7 +96,7 @@ void parse_cmdline_args(int argc, char **argv,
}
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hd:r:L:R:BASNFUMQ:czqp:",
while ((opt = getopt_long(argc, argv, "hd:r:L:R:BASNFUMQ:G:H:czqp:",
long_options, &longindex)) != -1) {
switch (opt) {
case 'd':
@@ -129,6 +129,22 @@ void parse_cmdline_args(int argc, char **argv,
goto error;
}
break;
case 'G':
if (!ether_aton_r(optarg,
(struct ether_addr *)&cfg->opt_tx_dmac)) {
fprintf(stderr, "Invalid dest MAC address:%s\n",
optarg);
goto error;
}
break;
case 'H':
if (!ether_aton_r(optarg,
(struct ether_addr *)&cfg->opt_tx_smac)) {
fprintf(stderr, "Invalid src MAC address:%s\n",
optarg);
goto error;
}
break;
case 'B':
cfg->opt_busy_poll = true;
break;