Skip to content

Commit b0106f5

Browse files
other examples
1 parent ff8a42b commit b0106f5

3 files changed

Lines changed: 678 additions & 0 deletions

File tree

fe.c

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
/*
2+
* This program reads UDP packets from the first netmap port and
3+
* selectively forwards them to the second or third port, depending
4+
* on the UDP destination port. The user can specify two UDP ports A and
5+
* B by command line: packets with destination port A will be forwarded
6+
* to the second netmap port; packets with destination port B will be
7+
* forwarded to the third netmap port; all the other packets are
8+
* dropped.
9+
*/
10+
#include <stdio.h>
11+
#include <stdlib.h>
12+
#include <unistd.h>
13+
#include <signal.h>
14+
#include <errno.h>
15+
#include <poll.h>
16+
#include <net/if.h>
17+
#include <stdint.h>
18+
#include <net/netmap.h>
19+
#define NETMAP_WITH_LIBS
20+
#include <net/netmap_user.h>
21+
#include <netinet/ether.h>
22+
#include <netinet/ip.h>
23+
#include <netinet/udp.h>
24+
#include <netinet/tcp.h>
25+
26+
static int stop = 0;
27+
static unsigned long long fwdback = 0;
28+
static unsigned long long fwda = 0;
29+
static unsigned long long fwdb = 0;
30+
static unsigned long long tot = 0;
31+
32+
static void
33+
sigint_handler(int signum)
34+
{
35+
stop = 1;
36+
}
37+
38+
static int
39+
rx_ready(struct nm_desc *nmd)
40+
{
41+
unsigned int ri;
42+
43+
for (ri = nmd->first_rx_ring; ri <= nmd->last_rx_ring; ri ++) {
44+
struct netmap_ring *ring;
45+
46+
ring = NETMAP_RXRING(nmd->nifp, ri);
47+
if (nm_ring_space(ring)) {
48+
return 1; /* there is something to read */
49+
}
50+
}
51+
52+
return 0;
53+
}
54+
55+
static inline int
56+
pkt_get_udp_port(const char *buf)
57+
{
58+
struct ether_header *ethh;
59+
struct iphdr *iph;
60+
struct udphdr *udph;
61+
62+
ethh = (struct ether_header *)buf;
63+
if (ethh->ether_type != htons(ETHERTYPE_IP)) {
64+
/* Filter out non-IP traffic. */
65+
return 0;
66+
}
67+
iph = (struct iphdr *)(ethh + 1);
68+
if (iph->protocol != IPPROTO_UDP) {
69+
/* Filter out non-UDP traffic. */
70+
return 0;
71+
}
72+
udph = (struct udphdr *)(iph + 1);
73+
74+
/* Return destination port. */
75+
return ntohs(udph->dest);
76+
}
77+
78+
79+
static void
80+
forward_pkts(struct nm_desc *src, struct nm_desc *dst)
81+
{
82+
unsigned int si = src->first_rx_ring;
83+
unsigned int di = dst->first_tx_ring;
84+
85+
while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
86+
struct netmap_ring *txring;
87+
struct netmap_ring *rxring;
88+
unsigned int rxhead, txhead;
89+
int nrx, ntx;
90+
91+
rxring = NETMAP_RXRING(src->nifp, si);
92+
txring = NETMAP_TXRING(dst->nifp, di);
93+
nrx = nm_ring_space(rxring);
94+
ntx = nm_ring_space(txring);
95+
if (nrx == 0) {
96+
si++;
97+
continue;
98+
}
99+
if (ntx == 0) {
100+
di++;
101+
continue;
102+
}
103+
104+
rxhead = rxring->head;
105+
txhead = txring->head;
106+
for (; nrx > 0 && ntx > 0;
107+
nrx --, rxhead = nm_ring_next(rxring, rxhead), tot ++) {
108+
struct netmap_slot *rs = &rxring->slot[rxhead];
109+
struct netmap_slot *ts = &txring->slot[txhead];
110+
char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx);
111+
char *txbuf = NETMAP_BUF(txring, ts->buf_idx);
112+
113+
ts->len = rs->len;
114+
memcpy(txbuf, rxbuf, ts->len);
115+
txhead = nm_ring_next(txring, txhead);
116+
ntx --;
117+
fwdback ++;
118+
tot ++;
119+
}
120+
/* Update state of netmap ring. */
121+
rxring->head = rxring->cur = rxhead;
122+
txring->head = txring->cur = txhead;
123+
}
124+
}
125+
126+
static int
127+
main_loop(const char *netmap_port_one, const char *netmap_port_two,
128+
const char *netmap_port_three, int udp_port_a, int udp_port_b)
129+
{
130+
struct nm_desc *nmd_one;
131+
struct nm_desc *nmd_two;
132+
struct nm_desc *nmd_three;
133+
134+
nmd_one = nm_open(netmap_port_one, NULL, 0, NULL);
135+
if (nmd_one == NULL) {
136+
if (!errno) {
137+
printf("Failed to nm_open(%s): not a netmap port\n",
138+
netmap_port_one);
139+
} else {
140+
printf("Failed to nm_open(%s): %s\n", netmap_port_one,
141+
strerror(errno));
142+
}
143+
return -1;
144+
}
145+
146+
nmd_two = nm_open(netmap_port_two, NULL, 0, NULL);
147+
if (nmd_two == NULL) {
148+
if (!errno) {
149+
printf("Failed to nm_open(%s): not a netmap port\n",
150+
netmap_port_two);
151+
} else {
152+
printf("Failed to nm_open(%s): %s\n", netmap_port_two,
153+
strerror(errno));
154+
}
155+
return -1;
156+
}
157+
158+
nmd_three = nm_open(netmap_port_three, NULL, 0, NULL);
159+
if (nmd_three == NULL) {
160+
if (!errno) {
161+
printf("Failed to nm_open(%s): not a netmap port\n",
162+
netmap_port_three);
163+
} else {
164+
printf("Failed to nm_open(%s): %s\n", netmap_port_three,
165+
strerror(errno));
166+
}
167+
return -1;
168+
}
169+
170+
while (!stop) {
171+
172+
/* Forward traffic from ports two and three back to port one. */
173+
forward_pkts(nmd_two, nmd_one);
174+
forward_pkts(nmd_three, nmd_one);
175+
}
176+
177+
nm_close(nmd_one);
178+
nm_close(nmd_two);
179+
nm_close(nmd_three);
180+
181+
printf("Total processed packets: %llu\n", tot);
182+
printf("Forwarded to port one : %llu\n", fwdback);
183+
printf("Forwarded to port two : %llu\n", fwda);
184+
printf("Forwarded to port three: %llu\n", fwdb);
185+
186+
return 0;
187+
}
188+
189+
static void
190+
usage(char **argv)
191+
{
192+
printf("usage: %s [-h] [-i NETMAP_PORT_ONE] "
193+
"[-i NETMAP_PORT_TWO] [-i NETMAP_PORT_THREE] "
194+
"[-p UDP_PORT_A] [-p UDP_PORT_B]\n", argv[0]);
195+
exit(EXIT_SUCCESS);
196+
}
197+
198+
int
199+
main(int argc, char **argv)
200+
{
201+
const char *netmap_port_one = NULL;
202+
const char *netmap_port_two = NULL;
203+
const char *netmap_port_three = NULL;
204+
int udp_port;
205+
int udp_port_a = 8000;
206+
int udp_port_b = 8001;
207+
int udp_port_args = 0;
208+
struct sigaction sa;
209+
int opt;
210+
int ret;
211+
212+
while ((opt = getopt(argc, argv, "hi:p:")) != -1) {
213+
switch (opt) {
214+
case 'h':
215+
usage(argv);
216+
return 0;
217+
218+
case 'i':
219+
if (netmap_port_one == NULL) {
220+
netmap_port_one = optarg;
221+
} else if (netmap_port_two == NULL) {
222+
netmap_port_two = optarg;
223+
} else if (netmap_port_three == NULL) {
224+
netmap_port_three = optarg;
225+
}
226+
break;
227+
228+
case 'p':
229+
udp_port = atoi(optarg);
230+
if (udp_port <= 0 || udp_port >= 65535) {
231+
printf(" invalid UDP port %s\n", optarg);
232+
usage(argv);
233+
}
234+
switch (udp_port_args) {
235+
case 0:
236+
udp_port_a = udp_port;
237+
break;
238+
case 1:
239+
udp_port_b = udp_port;
240+
break;
241+
}
242+
udp_port_args ++;
243+
break;
244+
245+
default:
246+
printf(" unrecognized option '-%c'\n", opt);
247+
usage(argv);
248+
return -1;
249+
}
250+
}
251+
252+
if (netmap_port_one == NULL) {
253+
printf(" missing netmap port #1\n");
254+
usage(argv);
255+
}
256+
257+
if (netmap_port_two == NULL) {
258+
printf(" missing netmap port #2\n");
259+
usage(argv);
260+
}
261+
262+
/* Register Ctrl-C handler. */
263+
sa.sa_handler = sigint_handler;
264+
sigemptyset(&sa.sa_mask);
265+
sa.sa_flags = SA_RESTART;
266+
ret = sigaction(SIGINT, &sa, NULL);
267+
if (ret) {
268+
perror("sigaction(SIGINT)");
269+
exit(EXIT_FAILURE);
270+
}
271+
(void)rx_ready;
272+
273+
printf("Port one : %s\n", netmap_port_one);
274+
printf("Port two : %s\n", netmap_port_two);
275+
printf("Port three: %s\n", netmap_port_three);
276+
printf("UDP port A: %d\n", udp_port_a);
277+
printf("UDP port B: %d\n", udp_port_b);
278+
279+
main_loop(netmap_port_one, netmap_port_two, netmap_port_three,
280+
udp_port_a, udp_port_b);
281+
282+
return 0;
283+
}

0 commit comments

Comments
 (0)