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.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
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
19 * Copyright (C) 2014 Cloudius Systems, Ltd.
23 #include <seastar/net/virtio.hh>
24 #include <seastar/net/dpdk.hh>
25 #include <seastar/core/reactor.hh>
26 #include <seastar/net/ip.hh>
27 #include <seastar/net/native-stack.hh>
32 using namespace seastar
;
35 void dump_packet(const packet
& p
) {
38 for (unsigned i
= 0; i
< std::min(f
.size
, size_t(30)); ++i
) {
40 std::sprintf(x
, " %02x", uint8_t(f
.base
[i
]));
46 future
<> echo_packet(net::qp
& netif
, packet p
) {
48 if (f
.size
< sizeof(eth_hdr
)) {
49 return make_ready_future
<>();
52 auto eh
= reinterpret_cast<eth_hdr
*>(f
.base
+ pos
);
55 if (eh
->eth_proto
!= 0x0800) {
56 return make_ready_future
<>();
58 auto iph
= reinterpret_cast<ip_hdr
*>(f
.base
+ pos
);
61 if (iph
->ver
!= 4 || iph
->ihl
< 5 || iph
->ip_proto
!= 1) {
62 return make_ready_future
<>();
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
<>();
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
;
76 icmph
->csum
= ip_checksum(icmph
, icmp_len
);
78 iph
->csum
= ip_checksum(iph
, iph
->ihl
* 4);
79 return netif
.send(std::move(p
));
82 #ifdef SEASTAR_HAVE_DPDK
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
;
91 int main(int ac
, char** av
) {
92 std::unique_ptr
<net::device
> dnet
;
95 native_stack_options opts
;
97 #ifdef SEASTAR_HAVE_DPDK
103 if ((ac
== 1) || !std::strcmp(av
[1], "-virtio")) {
104 dnet
= create_virtio_net_device(opts
.virtio_opts
, opts
.lro
);
105 } else if (!std::strcmp(av
[1], "-dpdk")) {
106 dnet
= create_dpdk_net_device();
112 dnet
= create_virtio_net_device(opts
.virtio_opts
, opts
.lro
);
113 #endif // SEASTAR_HAVE_DPDK
115 auto qp
= dnet
->init_local_queue(opts
, 0);
117 dnet
->set_local_queue(std::move(qp
));
119 dnet
->receive([vnet
] (packet p
) {
120 return echo_packet(*vnet
, std::move(p
));