From f30ba40d5a67e141d054e2066f8c057e076b3e45 Mon Sep 17 00:00:00 2001 From: Tomasz Grabiec <tgrabiec@cloudius-systems.com> Date: Thu, 24 Apr 2014 18:46:49 +0200 Subject: [PATCH] net: log packets going through loopback and virtio-net. There was no way to sniff packets going through OSv's loopback interface. I faced a need to debug in-guest TCP traffic. Packets are logged using tracing infrastructure. Packet data is serialized as sample data up to a limit, which is currently hardcoded to 128 bytes. To enable capturing of packets just enable tracepoints named: - net_packet_loopback - net_packet_eth Raw data can be seen in `trace list` output. Better presentation methods will be added in the following patches. This may also become useful when debugging network problems in the cloud, as we have no ability to run tcpdump on the host there. Signed-off-by: Tomasz Grabiec <tgrabiec@cloudius-systems.com> Signed-off-by: Pekka Enberg <penberg@cloudius-systems.com> --- bsd/sys/net/if_loop.cc | 2 + build.mk | 1 + core/net_trace.cc | 148 +++++++++++++++++++++++++++++++++++++++ drivers/virtio-net.cc | 8 ++- include/osv/net_trace.hh | 17 +++++ 5 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 core/net_trace.cc create mode 100644 include/osv/net_trace.hh diff --git a/bsd/sys/net/if_loop.cc b/bsd/sys/net/if_loop.cc index 5697545bb..09ffe899a 100644 --- a/bsd/sys/net/if_loop.cc +++ b/bsd/sys/net/if_loop.cc @@ -35,6 +35,7 @@ */ #include <osv/ioctl.h> +#include <osv/net_trace.hh> #include <bsd/porting/netport.h> #include <bsd/sys/sys/param.h> @@ -287,6 +288,7 @@ if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen) } ifp->if_ipackets++; ifp->if_ibytes += m->M_dat.MH.MH_pkthdr.len; + log_loopback_packet(m); netisr_queue(isr, m); /* mbuf is free'd on failure. */ return (0); } diff --git a/build.mk b/build.mk index c1d77d096..c88c6eea0 100644 --- a/build.mk +++ b/build.mk @@ -750,6 +750,7 @@ objects += core/chart.o objects += core/net_channel.o objects += core/demangle.o objects += core/async.o +objects += core/net_trace.o include $(src)/fs/build.mk include $(src)/libc/build.mk diff --git a/core/net_trace.cc b/core/net_trace.cc new file mode 100644 index 000000000..32d4961c1 --- /dev/null +++ b/core/net_trace.cc @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2014 Cloudius Systems, Ltd. + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#include <osv/trace.hh> +#include <osv/net_trace.hh> +#include <vector> +#include <iterator> + +class mbuf_iterator : public std::iterator<std::input_iterator_tag, char, size_t> { +private: + struct mbuf* _m; + size_t _pos; +private: + void ensure_next() + { + while (_m != nullptr && _pos == (size_t) _m->m_hdr.mh_len) { + _m = _m->m_hdr.mh_next; + _pos = 0; + } + } +public: + mbuf_iterator(struct mbuf* m) + : _m(m) + , _pos(0) + { + ensure_next(); + } + + void operator++() + { + _pos++; + ensure_next(); + } + + mbuf_iterator operator+(size_t delta) const + { + mbuf_iterator new_iterator(*this); + new_iterator += delta; + return new_iterator; + } + + void operator+=(size_t delta) + { + while (_m != nullptr && delta > 0) { + auto step = std::min(delta, _m->m_hdr.mh_len - _pos); + _pos += step; + delta -= step; + ensure_next(); + } + } + + char& operator*() + { + return _m->m_hdr.mh_data[_pos]; + } + + char* operator->() + { + return &_m->m_hdr.mh_data[_pos]; + } + + bool operator==(const mbuf_iterator& other) const + { + return other._m == _m && other._pos == _pos; + } + + bool operator!=(const mbuf_iterator& other) const + { + return !(*this == other); + } + + friend size_t std::distance<mbuf_iterator>(mbuf_iterator, mbuf_iterator); +}; + +namespace std { + +template<> +size_t distance<mbuf_iterator>(mbuf_iterator first, mbuf_iterator second) +{ + if (first._m == second._m) { + return second._pos - first._pos; + } + + size_t distance = 0; + auto* m = first._m; + + if (m) { + distance += m->m_hdr.mh_len - first._pos; + } + + m = m->m_hdr.mh_next; + + while (m && m != second._m) { + distance += m->m_hdr.mh_len; + m = m->m_hdr.mh_next; + } + + if (m) { + distance += second._pos; + } + + return distance; +} + +} + +template<size_t limit> +class mbuf_slice : public blob_tag { +private: + struct mbuf* _m; +public: + using iterator = mbuf_iterator; + + mbuf_slice(struct mbuf* m) + : _m(m) + { + } + + iterator begin() const + { + return mbuf_iterator(_m); + } + + iterator end() const + { + return begin() + limit; + } +}; + +static constexpr size_t capture_limit = 128; +using slice_t = mbuf_slice<capture_limit>; + +TRACEPOINT(trace_net_packet_eth, "if=%d, data=%s", int, slice_t); +TRACEPOINT(trace_net_packet_loopback, "data=%s", slice_t); + +void log_eth_packet(struct ifnet *ifp, struct mbuf* m) +{ + trace_net_packet_eth(ifp->if_index, slice_t(m)); +} + +void log_loopback_packet(struct mbuf* m) +{ + trace_net_packet_loopback(slice_t(m)); +} diff --git a/drivers/virtio-net.cc b/drivers/virtio-net.cc index 3fe369300..790a721fc 100644 --- a/drivers/virtio-net.cc +++ b/drivers/virtio-net.cc @@ -23,8 +23,8 @@ #include <osv/debug.h> #include <osv/sched.hh> -#include "osv/trace.hh" - +#include <osv/trace.hh> +#include <osv/net_trace.hh> #include <osv/device.h> #include <osv/ioctl.h> @@ -121,6 +121,8 @@ static int if_transmit(struct ifnet* ifp, struct mbuf* m_head) { net* vnet = (net*)ifp->if_softc; + log_eth_packet(ifp, m_head); + net_d("%s_start", __FUNCTION__); /* Process packets */ @@ -447,6 +449,8 @@ void net::receiver() rx_packets++; rx_bytes += m_head->M_dat.MH.MH_pkthdr.len; + log_eth_packet(_ifn, m_head); + bool fast_path = _ifn->if_classifier.post_packet(m_head); if (!fast_path) { (*_ifn->if_input)(_ifn, m_head); diff --git a/include/osv/net_trace.hh b/include/osv/net_trace.hh new file mode 100644 index 000000000..844010caa --- /dev/null +++ b/include/osv/net_trace.hh @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 Cloudius Systems, Ltd. + * + * This work is open source software, licensed under the terms of the + * BSD license as described in the LICENSE file in the top-level directory. + */ + +#ifndef NET_TRACE_HH +#define NET_TRACE_HH + +#include <bsd/sys/sys/mbuf.h> +#include <bsd/sys/net/if.h> + +void log_eth_packet(struct ifnet *ifp, struct mbuf *m); +void log_loopback_packet(struct mbuf *m); + +#endif -- GitLab