]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright (C) 2014 Cloudius Systems, Ltd. | |
20 | * | |
21 | */ | |
22 | ||
23 | #include <seastar/net/virtio.hh> | |
24 | #include <seastar/net/dpdk.hh> | |
25 | #include <seastar/core/reactor.hh> | |
26 | #include <seastar/net/ip.hh> | |
20effc67 | 27 | #include <seastar/net/native-stack.hh> |
11fdf7f2 TL |
28 | #include <iostream> |
29 | #include <utility> | |
30 | #include <algorithm> | |
31 | ||
32 | using namespace seastar; | |
33 | using namespace net; | |
34 | ||
35 | void dump_packet(const packet& p) { | |
36 | std::cout << "rx:"; | |
37 | auto f = p.frag(0); | |
38 | for (unsigned i = 0; i < std::min(f.size, size_t(30)); ++i) { | |
39 | char x[4]; | |
40 | std::sprintf(x, " %02x", uint8_t(f.base[i])); | |
41 | std::cout << x; | |
42 | } | |
43 | std::cout << "\n"; | |
44 | } | |
45 | ||
46 | future<> echo_packet(net::qp& netif, packet p) { | |
47 | auto f = p.frag(0); | |
48 | if (f.size < sizeof(eth_hdr)) { | |
49 | return make_ready_future<>(); | |
50 | } | |
51 | auto pos = 0; | |
52 | auto eh = reinterpret_cast<eth_hdr*>(f.base + pos); | |
53 | pos += sizeof(*eh); | |
54 | *eh = ntoh(*eh); | |
55 | if (eh->eth_proto != 0x0800) { | |
56 | return make_ready_future<>(); | |
57 | } | |
58 | auto iph = reinterpret_cast<ip_hdr*>(f.base + pos); | |
59 | *iph = ntoh(*iph); | |
60 | pos += iph->ihl * 4; | |
61 | if (iph->ver != 4 || iph->ihl < 5 || iph->ip_proto != 1) { | |
62 | return make_ready_future<>(); | |
63 | } | |
64 | auto ip_len = iph->len; | |
65 | auto icmph = reinterpret_cast<icmp_hdr*>(f.base + pos); | |
66 | if (icmph->type != icmp_hdr::msg_type::echo_request) { | |
67 | return make_ready_future<>(); | |
68 | } | |
69 | auto icmp_len = ip_len - iph->ihl * 4; | |
70 | std::swap(eh->src_mac, eh->dst_mac); | |
71 | std::swap(iph->src_ip, iph->dst_ip); | |
72 | icmph->type = icmp_hdr::msg_type::echo_reply; | |
73 | icmph->csum = 0; | |
74 | *iph = hton(*iph); | |
75 | *eh = hton(*eh); | |
76 | icmph->csum = ip_checksum(icmph, icmp_len); | |
77 | iph->csum = 0; | |
78 | iph->csum = ip_checksum(iph, iph->ihl * 4); | |
79 | return netif.send(std::move(p)); | |
80 | } | |
81 | ||
82 | #ifdef SEASTAR_HAVE_DPDK | |
83 | void usage() | |
84 | { | |
85 | std::cout<<"Usage: echotest [-virtio|-dpdk]"<<std::endl; | |
86 | std::cout<<" -virtio - use virtio backend (default)"<<std::endl; | |
87 | std::cout<<" -dpdk - use dpdk-pmd backend"<<std::endl; | |
88 | } | |
89 | #endif | |
90 | ||
91 | int main(int ac, char** av) { | |
92 | std::unique_ptr<net::device> dnet; | |
93 | net::qp* vnet; | |
94 | ||
20effc67 | 95 | native_stack_options opts; |
11fdf7f2 TL |
96 | |
97 | #ifdef SEASTAR_HAVE_DPDK | |
98 | if (ac > 2) { | |
99 | usage(); | |
100 | return -1; | |
101 | } | |
102 | ||
103 | if ((ac == 1) || !std::strcmp(av[1], "-virtio")) { | |
20effc67 | 104 | dnet = create_virtio_net_device(opts.virtio_opts, opts.lro); |
11fdf7f2 TL |
105 | } else if (!std::strcmp(av[1], "-dpdk")) { |
106 | dnet = create_dpdk_net_device(); | |
107 | } else { | |
108 | usage(); | |
109 | return -1; | |
110 | } | |
111 | #else | |
20effc67 | 112 | dnet = create_virtio_net_device(opts.virtio_opts, opts.lro); |
11fdf7f2 TL |
113 | #endif // SEASTAR_HAVE_DPDK |
114 | ||
115 | auto qp = dnet->init_local_queue(opts, 0); | |
116 | vnet = qp.get(); | |
117 | dnet->set_local_queue(std::move(qp)); | |
9f95a23c | 118 | future<> rx_done = |
11fdf7f2 TL |
119 | dnet->receive([vnet] (packet p) { |
120 | return echo_packet(*vnet, std::move(p)); | |
121 | }); | |
122 | engine().run(); | |
123 | return 0; | |
124 | } | |
125 | ||
126 |