1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
14 #include <rte_ethdev.h>
16 #include <rte_mempool.h>
17 #include <rte_string_fns.h>
18 #include "compat_netmap.h"
21 #define BUF_SIZE RTE_MBUF_DEFAULT_DATAROOM
22 #define MBUF_DATA_SIZE (BUF_SIZE + RTE_PKTMBUF_HEADROOM)
24 #define MBUF_PER_POOL 8192
26 struct rte_eth_conf eth_conf
= {
31 .mq_mode
= ETH_MQ_TX_NONE
,
35 #define MAX_QUEUE_NUM 1
36 #define RX_QUEUE_NUM 1
37 #define TX_QUEUE_NUM 1
39 #define MAX_DESC_NUM 0x400
40 #define RX_DESC_NUM 0x100
41 #define TX_DESC_NUM 0x200
43 #define RX_SYNC_NUM 0x20
44 #define TX_SYNC_NUM 0x20
46 struct rte_netmap_port_conf port_conf
= {
47 .eth_conf
= ð_conf
,
48 .socket_id
= SOCKET_ID_ANY
,
49 .nr_tx_rings
= TX_QUEUE_NUM
,
50 .nr_rx_rings
= RX_QUEUE_NUM
,
51 .nr_tx_slots
= TX_DESC_NUM
,
52 .nr_rx_slots
= RX_DESC_NUM
,
53 .tx_burst
= TX_SYNC_NUM
,
54 .rx_burst
= RX_SYNC_NUM
,
57 struct rte_netmap_conf netmap_conf
= {
58 .socket_id
= SOCKET_ID_ANY
,
59 .max_bufsz
= BUF_SIZE
,
60 .max_rings
= MAX_QUEUE_NUM
,
61 .max_slots
= MAX_DESC_NUM
,
66 #define MAX_PORT_NUM 2
70 struct netmap_if
*nmif
;
71 struct netmap_ring
*rx_ring
;
72 struct netmap_ring
*tx_ring
;
79 struct netmap_port p
[MAX_PORT_NUM
];
84 usage(const char *prgname
)
86 fprintf(stderr
, "Usage: %s [EAL args] -- [OPTION]...\n"
87 "-h, --help \t Show this help message and exit\n"
88 "-i INTERFACE_A \t Interface (DPDK port number) to use\n"
89 "[ -i INTERFACE_B \t Interface (DPDK port number) to use ]\n",
94 parse_portid(const char *portid_str
)
99 id
= strtoul(portid_str
, &end
, 10);
101 if (end
== portid_str
|| *end
!= '\0' || id
> RTE_MAX_ETHPORTS
)
102 rte_exit(EXIT_FAILURE
, "Invalid port number\n");
108 parse_args(int argc
, char **argv
)
112 while ((opt
= getopt(argc
, argv
, "hi:")) != -1) {
116 rte_exit(EXIT_SUCCESS
, "exiting...");
119 if (ports
.num
>= RTE_DIM(ports
.p
)) {
121 rte_exit(EXIT_FAILURE
, "configs with %u "
122 "ports are not supported\n",
127 ports
.p
[ports
.num
].str
= optarg
;
128 ports
.p
[ports
.num
].id
= parse_portid(optarg
);
133 rte_exit(EXIT_FAILURE
, "invalid option: %c\n", opt
);
140 static void sigint_handler(__rte_unused
int sig
)
143 signal(SIGINT
, SIG_DFL
);
146 static void move(int n
, struct netmap_ring
*rx
, struct netmap_ring
*tx
)
151 tmp
= tx
->slot
[tx
->cur
].buf_idx
;
153 tx
->slot
[tx
->cur
].buf_idx
= rx
->slot
[rx
->cur
].buf_idx
;
154 tx
->slot
[tx
->cur
].len
= rx
->slot
[rx
->cur
].len
;
155 tx
->slot
[tx
->cur
].flags
|= NS_BUF_CHANGED
;
156 tx
->cur
= NETMAP_RING_NEXT(tx
, tx
->cur
);
159 rx
->slot
[rx
->cur
].buf_idx
= tmp
;
160 rx
->slot
[rx
->cur
].flags
|= NS_BUF_CHANGED
;
161 rx
->cur
= NETMAP_RING_NEXT(rx
, rx
->cur
);
167 netmap_port_open(uint32_t idx
)
170 struct netmap_port
*port
;
173 port
= ports
.p
+ idx
;
175 port
->fd
= rte_netmap_open("/dev/netmap", O_RDWR
);
177 strlcpy(req
.nr_name
, port
->str
, sizeof(req
.nr_name
));
178 req
.nr_version
= NETMAP_API
;
181 err
= rte_netmap_ioctl(port
->fd
, NIOCGINFO
, &req
);
183 printf("[E] NIOCGINFO ioctl failed (error %d)\n", err
);
187 strlcpy(req
.nr_name
, port
->str
, sizeof(req
.nr_name
));
188 req
.nr_version
= NETMAP_API
;
191 err
= rte_netmap_ioctl(port
->fd
, NIOCREGIF
, &req
);
193 printf("[E] NIOCREGIF ioctl failed (error %d)\n", err
);
197 /* mmap only once. */
198 if (ports
.mem
== NULL
)
199 ports
.mem
= rte_netmap_mmap(NULL
, req
.nr_memsize
,
200 PROT_WRITE
| PROT_READ
, MAP_PRIVATE
, port
->fd
, 0);
202 if (ports
.mem
== MAP_FAILED
) {
203 printf("[E] NETMAP mmap failed for fd: %d)\n", port
->fd
);
207 port
->nmif
= NETMAP_IF(ports
.mem
, req
.nr_offset
);
209 port
->tx_ring
= NETMAP_TXRING(port
->nmif
, 0);
210 port
->rx_ring
= NETMAP_RXRING(port
->nmif
, 0);
216 int main(int argc
, char *argv
[])
221 struct pollfd pollfd
[MAX_PORT_NUM
];
222 struct rte_mempool
*pool
;
223 struct netmap_ring
*rx_ring
, *tx_ring
;
225 ret
= rte_eal_init(argc
, argv
);
227 rte_exit(EXIT_FAILURE
, "Cannot initialize EAL\n");
232 parse_args(argc
, argv
);
235 rte_exit(EXIT_FAILURE
, "no ports specified\n");
237 if (rte_eth_dev_count_avail() < 1)
238 rte_exit(EXIT_FAILURE
, "Not enough ethernet ports available\n");
240 pool
= rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL
, 32, 0,
241 MBUF_DATA_SIZE
, rte_socket_id());
243 rte_exit(EXIT_FAILURE
, "Couldn't create mempool\n");
245 netmap_conf
.socket_id
= rte_socket_id();
246 err
= rte_netmap_init(&netmap_conf
);
249 rte_exit(EXIT_FAILURE
,
250 "Couldn't initialize librte_compat_netmap\n");
252 printf("librte_compat_netmap initialized\n");
254 port_conf
.pool
= pool
;
255 port_conf
.socket_id
= rte_socket_id();
257 for (i
= 0; i
!= ports
.num
; i
++) {
259 err
= rte_netmap_init_port(ports
.p
[i
].id
, &port_conf
);
261 rte_exit(EXIT_FAILURE
, "Couldn't setup port %hhu\n",
264 rte_eth_promiscuous_enable(ports
.p
[i
].id
);
267 for (i
= 0; i
!= ports
.num
; i
++) {
269 err
= netmap_port_open(i
);
271 rte_exit(EXIT_FAILURE
, "Couldn't set port %hhu "
272 "under NETMAP control\n",
276 printf("Port %hhu now in Netmap mode\n", ports
.p
[i
].id
);
279 memset(pollfd
, 0, sizeof(pollfd
));
281 for (i
= 0; i
!= ports
.num
; i
++) {
282 pollfd
[i
].fd
= ports
.p
[i
].fd
;
283 pollfd
[i
].events
= POLLIN
| POLLOUT
;
286 signal(SIGINT
, sigint_handler
);
288 pmsk
= ports
.num
- 1;
290 printf("Bridge up and running!\n");
295 pollfd
[0].revents
= 0;
296 pollfd
[1].revents
= 0;
298 ret
= rte_netmap_poll(pollfd
, ports
.num
, 0);
301 printf("[E] poll returned with error %d\n", ret
);
304 if (((pollfd
[0].revents
| pollfd
[1].revents
) & POLLERR
) != 0) {
305 printf("POLLERR!\n");
308 if ((pollfd
[0].revents
& POLLIN
) != 0 &&
309 (pollfd
[pmsk
].revents
& POLLOUT
) != 0) {
311 rx_ring
= ports
.p
[0].rx_ring
;
312 tx_ring
= ports
.p
[pmsk
].tx_ring
;
314 n_pkts
= RTE_MIN(rx_ring
->avail
, tx_ring
->avail
);
315 move(n_pkts
, rx_ring
, tx_ring
);
318 if (pmsk
!= 0 && (pollfd
[pmsk
].revents
& POLLIN
) != 0 &&
319 (pollfd
[0].revents
& POLLOUT
) != 0) {
321 rx_ring
= ports
.p
[pmsk
].rx_ring
;
322 tx_ring
= ports
.p
[0].tx_ring
;
324 n_pkts
= RTE_MIN(rx_ring
->avail
, tx_ring
->avail
);
325 move(n_pkts
, rx_ring
, tx_ring
);
329 printf("Bridge stopped!\n");
331 for (i
= 0; i
!= ports
.num
; i
++) {
332 err
= rte_netmap_ioctl(ports
.p
[i
].fd
, NIOCUNREGIF
, &req
);
334 printf("[E] NIOCUNREGIF ioctl failed (error %d)\n",
338 printf("Port %hhu unregistered from Netmap mode\n", ports
.p
[i
].id
);
340 rte_netmap_close(ports
.p
[i
].fd
);