From ad81836e34a15613e7452014419e5f5317c2f735 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 12 May 2018 09:27:07 -0600 Subject: [PATCH 001/424] Initial commit of DRX and TBN readers for bifrost. It would be nice if we could merge these all into a single disk_reader.cpp file but I haven't figured that out yet. --- python/bifrost/drx.py | 53 +++ python/bifrost/tbn.py | 53 +++ src/Makefile | 2 + src/bifrost/drx_reader.h | 71 ++++ src/bifrost/tbn_reader.h | 71 ++++ src/drx_reader.cpp | 751 +++++++++++++++++++++++++++++++++++++++ src/tbn_reader.cpp | 711 ++++++++++++++++++++++++++++++++++++ 7 files changed, 1712 insertions(+) create mode 100644 python/bifrost/drx.py create mode 100644 python/bifrost/tbn.py create mode 100644 src/bifrost/drx_reader.h create mode 100644 src/bifrost/tbn_reader.h create mode 100644 src/drx_reader.cpp create mode 100644 src/tbn_reader.cpp diff --git a/python/bifrost/drx.py b/python/bifrost/drx.py new file mode 100644 index 000000000..234a8e1ec --- /dev/null +++ b/python/bifrost/drx.py @@ -0,0 +1,53 @@ + +# Copyright (c) 2017, The Bifrost Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# **TODO: Write tests for this class + +from libbifrost import _bf, _check, _get, BifrostObject + +class DrxReader(BifrostObject): + def __init__(self, fh, ring, nsrc, src0, + buffer_nframe, slot_nframe, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfDrxReaderCreate, _bf.bfDrxReaderDestroy, + fh.fileno(), ring.obj, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.end() + def read(self): + status = _bf.BFdrxreader_status() + _check(_bf.bfDrxReaderRead(self.obj, status)) + return status + def flush(self): + _check(_bf.bfDrxReaderFlush(self.obj)) + def end(self): + _check(_bf.bfDrxReaderEnd(self.obj)) diff --git a/python/bifrost/tbn.py b/python/bifrost/tbn.py new file mode 100644 index 000000000..81ec96d54 --- /dev/null +++ b/python/bifrost/tbn.py @@ -0,0 +1,53 @@ + +# Copyright (c) 2017, The Bifrost Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# **TODO: Write tests for this class + +from libbifrost import _bf, _check, _get, BifrostObject + +class TbnReader(BifrostObject): + def __init__(self, fh, ring, nsrc, src0, + buffer_nframe, slot_nframe, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfTbnReaderCreate, _bf.bfTbnReaderDestroy, + fh.fileno(), ring.obj, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.end() + def read(self): + status = _bf.BFtbnreader_status() + _check(_bf.bfTbnReaderRead(self.obj, status)) + return status + def flush(self): + _check(_bf.bfTbnReaderFlush(self.obj)) + def end(self): + _check(_bf.bfTbnReaderEnd(self.obj)) diff --git a/src/Makefile b/src/Makefile index 793b613f9..ff994a37e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,6 +16,8 @@ LIBBIFROST_OBJS = \ udp_socket.o \ udp_capture.o \ udp_transmit.o \ + drx_reader.o \ + tbn_reader.o \ unpack.o \ quantize.o \ proclog.o diff --git a/src/bifrost/drx_reader.h b/src/bifrost/drx_reader.h new file mode 100644 index 000000000..00ce79ae8 --- /dev/null +++ b/src/bifrost/drx_reader.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_DRX_READER_H_INCLUDE_GUARD_ +#define BF_DRX_READER_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { + #endif + + #include + + typedef struct BFdrxreader_impl* BFdrxreader; + + typedef int (*BFdrxreader_sequence_callback)(BFoffset, BFoffset, int, int, int, + void const**, size_t*); + + typedef enum BFdrxreader_status_ { + BF_READ_STARTED, + BF_READ_ENDED, + BF_READ_CONTINUED, + BF_READ_CHANGED, + BF_READ_NO_DATA, + BF_READ_INTERRUPTED, + BF_READ_ERROR + } BFdrxreader_status; + + BFstatus bfDrxReaderCreate(BFdrxreader* obj, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdrxreader_sequence_callback sequence_callback, + int core); + BFstatus bfDrxReaderDestroy(BFdrxreader obj); + BFstatus bfDrxReaderRead(BFdrxreader obj, BFdrxreader_status* result); + BFstatus bfDrxReaderFlush(BFdrxreader obj); + BFstatus bfDrxReaderEnd(BFdrxreader obj); + + #ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_DRX_READER_H_INCLUDE_GUARD_ diff --git a/src/bifrost/tbn_reader.h b/src/bifrost/tbn_reader.h new file mode 100644 index 000000000..557b474af --- /dev/null +++ b/src/bifrost/tbn_reader.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_TBN_READER_H_INCLUDE_GUARD_ +#define BF_TBN_READER_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { + #endif + + #include + + typedef struct BFtbnreader_impl* BFtbnreader; + + typedef int (*BFtbnreader_sequence_callback)(BFoffset, BFoffset, int, int, + void const**, size_t*); + + typedef enum BFtbnreader_status_ { + BF_READ_STARTED, + BF_READ_ENDED, + BF_READ_CONTINUED, + BF_READ_CHANGED, + BF_READ_NO_DATA, + BF_READ_INTERRUPTED, + BF_READ_ERROR + } BFtbnreader_status; + + BFstatus bfTbnReaderCreate(BFtbnreader* obj, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFtbnreader_sequence_callback sequence_callback, + int core); + BFstatus bfTbnReaderDestroy(BFtbnreader obj); + BFstatus bfTbnReaderRead(BFtbnreader obj, BFtbnreader_status* result); + BFstatus bfTbnReaderFlush(BFtbnreader obj); + BFstatus bfTbnReaderEnd(BFtbnreader obj); + + #ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_TBN_READER_H_INCLUDE_GUARD_ diff --git a/src/drx_reader.cpp b/src/drx_reader.cpp new file mode 100644 index 000000000..b3dd0a749 --- /dev/null +++ b/src/drx_reader.cpp @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include +using bifrost::ring::RingWrapper; +using bifrost::ring::RingWriter; +using bifrost::ring::WriteSpan; +using bifrost::ring::WriteSequence; +#include "proclog.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include +#include + +#ifndef BF_HWLOC_ENABLED +#define BF_HWLOC_ENABLED 0 +//#define BF_HWLOC_ENABLED 1 +#endif + +enum { + DRX_FRAME_SIZE = 4128 +}; + +template +inline T atomic_add_and_fetch(T* dst, T val) { + return __sync_add_and_fetch(dst, val); // GCC builtin +} +template +inline T atomic_fetch_and_add(T* dst, T val) { + return __sync_fetch_and_add(dst, val); // GCC builtin +} + +// Wrap-safe comparisons +inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } +inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } + +template +class AlignedBuffer { + enum { DEFAULT_ALIGNMENT = 4096 }; + T* _buf; + size_t _size; + size_t _alignment; + void alloc() { + int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); + if( err ) { + throw std::runtime_error("Allocation failed"); + } + } + void copy(T const* srcbuf, size_t n) { + ::memcpy(_buf, srcbuf, n*sizeof(T)); + } + void free() { + if( _buf ) { + ::free(_buf); + _buf = 0; + _size = 0; + } + } +public: + //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) + // : _buf(0), _size(0), _alignment(alignment) {} + AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) + : _buf(0), _size(size), _alignment(alignment) { + this->alloc(); + } + AlignedBuffer(AlignedBuffer const& other) + : _buf(0), _size(other._size), _alignment(other._alignment) { + this->alloc(); + this->copy(other._buf, other._size); + } + AlignedBuffer& operator=(AlignedBuffer const& other) { + if( &other != this ) { + this->free(); + _size = other.size; + _alignment = other.alignment; + this->alloc(); + this->copy(other._buf, other._size); + } + return *this; + } + ~AlignedBuffer() { + this->free(); + } + inline void swap(AlignedBuffer const& other) { + std::swap(_buf, other._buf); + std::swap(_size, other._size); + std::swap(_alignment, other._alignment); + } + inline void resize(size_t n) { + if( n <= _size ) { + _size = n; + } else { + AlignedBuffer tmp(n, _alignment); + tmp.copy(&_buf[0], _size); + tmp.swap(*this); + } + } + inline size_t size() const { return _size; } + inline T & operator[](size_t i) { return _buf[i]; } + inline T const& operator[](size_t i) const { return _buf[i]; } +}; + +#if BF_HWLOC_ENABLED +#include +class HardwareLocality { + hwloc_topology_t _topo; + HardwareLocality(HardwareLocality const&); + HardwareLocality& operator=(HardwareLocality const&); +public: + HardwareLocality() { + hwloc_topology_init(&_topo); + hwloc_topology_load(_topo); + } + ~HardwareLocality() { + hwloc_topology_destroy(_topo); + } + int bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; + } +}; +#endif // BF_HWLOC_ENABLED + +class BoundThread { + #if BF_HWLOC_ENABLED + HardwareLocality _hwloc; + #endif +public: + BoundThread(int core) { + bfAffinitySetCore(core); + #if BF_HWLOC_ENABLED + assert(_hwloc.bind_memory_to_core(core) == 0); + #endif + } +}; + +class DRXReaderReader { + int _fd; + AlignedBuffer _buf; +public: + DRXReaderReader(int fd, size_t frm_size_max=DRX_FRAME_SIZE) + : _fd(fd), _buf(frm_size_max) + {} + inline int read_frame(uint8_t** frm_ptr, int flags=0) { + *frm_ptr = &_buf[0]; + return ::read(_fd, &_buf[0], _buf.size()); + } +}; + + +struct FrameDesc { + uint32_t sync; + uint64_t time_tag; + uint64_t seq; + int nsrc; + int src; + int tuning; + int decimation; + int valid_mode; + int payload_size; + const uint8_t* payload_ptr; +}; +struct FrameStats { + size_t ninvalid; + size_t ninvalid_bytes; + size_t nlate; + size_t nlate_bytes; + size_t nvalid; + size_t nvalid_bytes; +}; + +class DRXReaderThread : public BoundThread { + DRXReaderReader _disk; + FrameStats _stats; + std::vector _src_stats; + bool _have_frm; + FrameDesc _frm; +public: + enum { + READ_SUCCESS = 1 << 0, + READ_TIMEOUT = 1 << 1, + READ_INTERRUPTED = 1 << 2, + READ_ERROR = 1 << 3 + }; + DRXReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) + : BoundThread(core), _disk(fd, frm_size_max), _src_stats(nsrc), + _have_frm(false) { + this->reset_stats(); + } + // Reads, decodes and unpacks frames into the provided buffers + // Note: Read continues until the first frame that belongs + // beyond the end of the provided buffers. This frame is + // saved, accessible via get_last_frame(), and will be + // processed on the next call to run() if possible. + template + int run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + FrameDecoder* decode, + FrameProcessor* process) { + uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; + size_t local_ngood_bytes[2] = {0, 0}; + int ret; + while( true ) { + if( !_have_frm ) { + uint8_t* frm_ptr; + int frm_size = _disk.read_frame(&frm_ptr); + if( frm_size <= 0 ) { + if( errno == EAGAIN || errno == EWOULDBLOCK ) { + ret = READ_TIMEOUT; // Timed out + } else if( errno == EINTR ) { + ret = READ_INTERRUPTED; // Interrupted by signal + } else { + ret = READ_ERROR; // Socket error + } + break; + } + if( !(*decode)(frm_ptr, frm_size, &_frm) ) { + ++_stats.ninvalid; + _stats.ninvalid_bytes += frm_size; + continue; + } + _have_frm = true; + } + if( greater_equal(_frm.seq, seq_end) ) { + // Reached the end of this processing gulp, so leave this + // frame unprocessed and return. + ret = READ_SUCCESS; + break; + } + _have_frm = false; + if( less_than(_frm.seq, seq_beg) ) { + ++_stats.nlate; + _stats.nlate_bytes += _frm.payload_size; + ++_src_stats[_frm.src].nlate; + _src_stats[_frm.src].nlate_bytes += _frm.payload_size; + continue; + } + ++_stats.nvalid; + _stats.nvalid_bytes += _frm.payload_size; + ++_src_stats[_frm.src].nvalid; + _src_stats[_frm.src].nvalid_bytes += _frm.payload_size; + // HACK TODO: src_ngood_bytes should be accumulated locally and + // then atomically updated, like ngood_bytes. The + // current way is not thread-safe. + (*process)(&_frm, seq_beg, nseq_per_obuf, nbuf, obufs, + local_ngood_bytes, /*local_*/src_ngood_bytes); + } + if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } + if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } + return ret; + } + inline const FrameDesc* get_last_frame() const { + return _have_frm ? &_frm : NULL; + } + inline void reset_last_frame() { + _have_frm = false; + } + inline const FrameStats* get_stats() const { return &_stats; } + inline const FrameStats* get_stats(int src) const { return &_src_stats[src]; } + inline void reset_stats() { + ::memset(&_stats, 0, sizeof(_stats)); + ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(FrameStats)); + } +}; + +#pragma pack(1) +struct drx_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t seconds_count; + uint16_t decimation; + uint16_t time_offset; + uint64_t time_tag; + uint32_t tuning_word; + uint32_t flags; +}; + +class DRXDecoder { +protected: + int _nsrc; + int _src0; + inline bool valid_frame(const FrameDesc* frm) const { + return (frm->sync == 0x5CDEC0DE && + frm->src >= 0 && + frm->src < _nsrc && + frm->time_tag >= 0 && + frm->tuning >= 0); + } +public: + DRXDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} + inline bool operator()(const uint8_t* frm_ptr, + int frm_size, + FrameDesc* frm) const { + if( frm_size < (int)sizeof(drx_hdr_type) ) { + return false; + } + const drx_hdr_type* frm_hdr = (drx_hdr_type*)frm_ptr; + const uint8_t* frm_pld = frm_ptr + sizeof(drx_hdr_type); + int pld_size = frm_size - sizeof(drx_hdr_type); + int frm_id = frm_hdr->frame_count_word & 0xFF; + //uint8_t frm_beam = (frm_id & 0x7) - 1; + int frm_tune = ((frm_id >> 3) & 0x7) - 1; + int frm_pol = ((frm_id >> 7) & 0x1); + frm_id = (frm_tune << 1) | frm_pol; + frm->sync = frm_hdr->sync_word; + frm->time_tag = be64toh(frm_hdr->time_tag) - be16toh(frm_hdr->time_offset); + frm->seq = frm->time_tag / be16toh(frm_hdr->decimation) / 4096; + //frm->nsrc = frm_hdr->nroach; + frm->nsrc = _nsrc; + frm->src = frm_id - _src0; + frm->tuning = be32toh(frm_hdr->tuning_word); + frm->decimation = be16toh(frm_hdr->decimation); + frm->valid_mode = 1; + frm->payload_size = pld_size; + frm->payload_ptr = frm_pld; +// cout << frm_id << frm->src << "valid? " << this->valid_frame(frm) << endl; + return this->valid_frame(frm); + } +}; + +class DRXProcessor { +public: + inline void operator()(const FrameDesc* frm, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + + (frm->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = frm->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][frm->src] += nbyte; + int payload_size = frm->payload_size; + + size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; + uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + int samp = 0; + for( ; samp<4096; ++samp ) { // HACK TESTING + out[samp*frm->nsrc + frm->src] = in[samp]; + } + } + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nseq) { + uint8_t* __restrict__ aligned_data = (uint8_t*)data; + for( int t=0; t _process_time; + std::chrono::duration _reserve_time; + + int _nsrc; + int _nseq_per_buf; + int _slot_nframe; + BFoffset _seq; + BFoffset _time_tag; + int _chan0; + int _chan1; + int _payload_size; + bool _active; + uint8_t _tstate; + BFdrxreader_sequence_callback _sequence_callback; + + RingWrapper _ring; + RingWriter _oring; + std::queue > _bufs; + std::queue _buf_ngood_bytes; + std::queue > _buf_src_ngood_bytes; + std::shared_ptr _sequence; + size_t _ngood_bytes; + size_t _nmissing_bytes; + + inline size_t bufsize(int payload_size=-1) { + if( payload_size == -1 ) { + payload_size = _payload_size; + } + return _nseq_per_buf * _nsrc * payload_size; + } + inline void reserve_buf() { + _buf_ngood_bytes.push(0); + _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); + size_t size = this->bufsize(); + // TODO: Can make this simpler? + _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); + } + inline void commit_buf() { + size_t expected_bytes = _bufs.front()->size(); + + for( int src=0; src<_nsrc; ++src ) { + // TODO: This assumes all sources contribute equally; should really + // allow non-uniform partitioning. + size_t src_expected_bytes = expected_bytes / _nsrc; + size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; + size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; + // Detect >50% missing data from this source + if( src_nmissing_bytes > src_ngood_bytes ) { + // Zero-out this source's contribution to the buffer + uint8_t* data = (uint8_t*)_bufs.front()->data(); + _processor.blank_out_source(data, src, _nsrc, + _nseq_per_buf); + } + } + _buf_src_ngood_bytes.pop(); + + _ngood_bytes += _buf_ngood_bytes.front(); + _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); + _buf_ngood_bytes.pop(); + + _bufs.front()->commit(); + _bufs.pop(); + _seq += _nseq_per_buf; + } + inline void begin_sequence() { + BFoffset seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + const void* hdr; + size_t hdr_size; + BFoffset time_tag = _time_tag; + if( _sequence_callback ) { + int status = (*_sequence_callback)(seq0, + _time_tag, + _chan0, + _chan1, + _nsrc, + &hdr, + &hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + time_tag = _time_tag; + hdr = NULL; + hdr_size = 0; + } + const char* name = ""; + int nringlet = 1; + _sequence.reset(new WriteSequence(_oring, name, time_tag, + hdr_size, hdr, nringlet)); + } + inline void end_sequence() { + _sequence.reset(); // Note: This is releasing the shared_ptr + } +public: + inline BFdrxreader_impl(int fd, + BFring ring, + int nsrc, + int src0, + int buffer_nframe, + int slot_nframe, + BFdrxreader_sequence_callback sequence_callback, + int core) + : _reader(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor(), + _type_log("lwa_file/type"), + _bind_log("lwa_file/bind"), + _out_log("lwa_file/out"), + _size_log("lwa_file/sizes"), + _chan_log("lwa_file/chans"), + _stat_log("lwa_file/stats"), + _perf_log("lwa_file/perf"), + _nsrc(nsrc), _nseq_per_buf(buffer_nframe), _slot_nframe(slot_nframe), + _seq(0), _time_tag(0), _chan0(), _active(false), _tstate(0), + _sequence_callback(sequence_callback), + _ring(ring), _oring(_ring), + // TODO: Add reset method for stats + _ngood_bytes(0), _nmissing_bytes(0) { + size_t contig_span = this->bufsize(DRX_FRAME_SIZE - sizeof(drx_hdr_type)); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "drx"); + _bind_log.update("ncore : %i\n" + "core0 : %i\n", + 1, core); + _out_log.update("nring : %i\n" + "ring0 : %s\n", + 1, _ring.name()); + _size_log.update("nsrc : %i\n" + "nseq_per_buf : %i\n" + "slot_nframe : %i\n", + _nsrc, _nseq_per_buf, _slot_nframe); + } + inline void flush() { + while( _bufs.size() ) { + this->commit_buf(); + } + if( _sequence ) { + this->end_sequence(); + } + } + inline void end_writing() { + this->flush(); + _oring.close(); + } + BFdrxreader_status read() { + _t0 = std::chrono::high_resolution_clock::now(); + + uint8_t* buf_ptrs[2]; + // Minor HACK to access the buffers in a 2-element queue + buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; + buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; + + size_t* ngood_bytes_ptrs[2]; + ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; + ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; + + size_t* src_ngood_bytes_ptrs[2]; + src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; + src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; + + int state = _reader.run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + &_decoder, + &_processor); + if( state & DRXReaderThread::READ_ERROR ) { + return BF_READ_ERROR; + } else if( state & DRXReaderThread::READ_INTERRUPTED ) { + return BF_READ_INTERRUPTED; + } + const FrameStats* stats = _reader.get_stats(); + _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" + << "nmissing_bytes : " << _nmissing_bytes << "\n" + << "ninvalid : " << stats->ninvalid << "\n" + << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" + << "nlate : " << stats->nlate << "\n" + << "nlate_bytes : " << stats->nlate_bytes << "\n" + << "nvalid : " << stats->nvalid << "\n" + << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; + + _t1 = std::chrono::high_resolution_clock::now(); + + BFdrxreader_status ret; + bool was_active = _active; + _active = state & DRXReaderThread::READ_SUCCESS; + if( _active ) { + const FrameDesc* frm = _reader.get_last_frame(); + if( frm ) { + //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; + } + else { + //cout << "No latest frame" << endl; + } + + if( frm->src / 2 == 0 ) { + if( frm->tuning != _chan0 ) { + _tstate |= 1; + _chan0 = frm->tuning; + } + } else { + if( frm->tuning != _chan1 ) { + _tstate |= 2; + _chan1 = frm->tuning; + } + } + //cout << "State is now " << int(_tstate) << " with " << _chan0 << " and " << _chan1 << " with " << _seq << endl; + //cout << " " << frm->time_tag << endl; + + if( !was_active ) { + if( (_tstate == 3 && _nsrc == 4) || + (_tstate != 0 && _nsrc == 2) ) { + _seq = round_nearest(frm->seq, _nseq_per_buf); + _time_tag = frm->time_tag; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->begin_sequence(); + ret = BF_READ_STARTED; + _tstate = 0; + } else { + ret = BF_READ_NO_DATA; + _active = false; + _reader.reset_last_frame(); + } + } else { + //cout << "Continuing data, seq = " << seq << endl; + if( (_tstate == 3 && _nsrc == 4) || + (_tstate != 0 && _nsrc == 2) ) { + _time_tag = frm->time_tag; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->end_sequence(); + this->begin_sequence(); + ret = BF_READ_CHANGED; + _tstate = 0; + } else { + ret = BF_READ_CONTINUED; + } + } + + if( ret != BF_READ_NO_DATA ) { + if( _bufs.size() == 2 ) { + this->commit_buf(); + } + this->reserve_buf(); + } + } else { + + if( was_active ) { + this->flush(); + ret = BF_READ_ENDED; + } else { + ret = BF_READ_NO_DATA; + } + } + + _t2 = std::chrono::high_resolution_clock::now(); + _process_time = std::chrono::duration_cast>(_t1-_t0); + _reserve_time = std::chrono::duration_cast>(_t2-_t1); + _perf_log.update() << "acquire_time : " << -1.0 << "\n" + << "process_time : " << _process_time.count() << "\n" + << "reserve_time : " << _reserve_time.count() << "\n"; + + return ret; + } +}; + +BFstatus bfDrxReaderCreate(BFdrxreader* obj, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_nframe, + BFsize slot_nframe, + BFdrxreader_sequence_callback sequence_callback, + int core) { + BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); + BF_TRY_RETURN_ELSE(*obj = new BFdrxreader_impl(fd, ring, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core), + *obj = 0); +} +BFstatus bfDrxReaderDestroy(BFdrxreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} +BFstatus bfDrxReaderRead(BFdrxreader obj, BFdrxreader_status* result) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN_ELSE(*result = obj->read(), + *result = BF_READ_ERROR); +} +BFstatus bfDrxReaderFlush(BFdrxreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->flush()); +} +BFstatus bfDrxReaderEnd(BFdrxreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->end_writing()); +} \ No newline at end of file diff --git a/src/tbn_reader.cpp b/src/tbn_reader.cpp new file mode 100644 index 000000000..24d301ab9 --- /dev/null +++ b/src/tbn_reader.cpp @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include +using bifrost::ring::RingWrapper; +using bifrost::ring::RingWriter; +using bifrost::ring::WriteSpan; +using bifrost::ring::WriteSequence; +#include "proclog.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include +#include + +#ifndef BF_HWLOC_ENABLED +#define BF_HWLOC_ENABLED 0 +//#define BF_HWLOC_ENABLED 1 +#endif + +enum { + TBN_FRAME_SIZE = 1048 +}; + +template +inline T atomic_add_and_fetch(T* dst, T val) { + return __sync_add_and_fetch(dst, val); // GCC builtin +} +template +inline T atomic_fetch_and_add(T* dst, T val) { + return __sync_fetch_and_add(dst, val); // GCC builtin +} + +// Wrap-safe comparisons +inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } +inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } + +template +class AlignedBuffer { + enum { DEFAULT_ALIGNMENT = 4096 }; + T* _buf; + size_t _size; + size_t _alignment; + void alloc() { + int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); + if( err ) { + throw std::runtime_error("Allocation failed"); + } + } + void copy(T const* srcbuf, size_t n) { + ::memcpy(_buf, srcbuf, n*sizeof(T)); + } + void free() { + if( _buf ) { + ::free(_buf); + _buf = 0; + _size = 0; + } + } +public: + //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) + // : _buf(0), _size(0), _alignment(alignment) {} + AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) + : _buf(0), _size(size), _alignment(alignment) { + this->alloc(); + } + AlignedBuffer(AlignedBuffer const& other) + : _buf(0), _size(other._size), _alignment(other._alignment) { + this->alloc(); + this->copy(other._buf, other._size); + } + AlignedBuffer& operator=(AlignedBuffer const& other) { + if( &other != this ) { + this->free(); + _size = other.size; + _alignment = other.alignment; + this->alloc(); + this->copy(other._buf, other._size); + } + return *this; + } + ~AlignedBuffer() { + this->free(); + } + inline void swap(AlignedBuffer const& other) { + std::swap(_buf, other._buf); + std::swap(_size, other._size); + std::swap(_alignment, other._alignment); + } + inline void resize(size_t n) { + if( n <= _size ) { + _size = n; + } else { + AlignedBuffer tmp(n, _alignment); + tmp.copy(&_buf[0], _size); + tmp.swap(*this); + } + } + inline size_t size() const { return _size; } + inline T & operator[](size_t i) { return _buf[i]; } + inline T const& operator[](size_t i) const { return _buf[i]; } +}; + +#if BF_HWLOC_ENABLED +#include +class HardwareLocality { + hwloc_topology_t _topo; + HardwareLocality(HardwareLocality const&); + HardwareLocality& operator=(HardwareLocality const&); +public: + HardwareLocality() { + hwloc_topology_init(&_topo); + hwloc_topology_load(_topo); + } + ~HardwareLocality() { + hwloc_topology_destroy(_topo); + } + int bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; + } +}; +#endif // BF_HWLOC_ENABLED + +class BoundThread { + #if BF_HWLOC_ENABLED + HardwareLocality _hwloc; + #endif +public: + BoundThread(int core) { + bfAffinitySetCore(core); + #if BF_HWLOC_ENABLED + assert(_hwloc.bind_memory_to_core(core) == 0); + #endif + } +}; + +class TBNReaderReader { + int _fd; + AlignedBuffer _buf; +public: + TBNReaderReader(int fd, size_t frm_size_max=TBN_FRAME_SIZE) + : _fd(fd), _buf(frm_size_max) + {} + inline int read_frame(uint8_t** frm_ptr, int flags=0) { + *frm_ptr = &_buf[0]; + return ::read(_fd, &_buf[0], _buf.size()); + } +}; + + +struct FrameDesc { + uint32_t sync; + uint64_t time_tag; + uint64_t seq; + int nsrc; + int src; + int tuning; + int decimation; + int valid_mode; + int payload_size; + const uint8_t* payload_ptr; +}; +struct FrameStats { + size_t ninvalid; + size_t ninvalid_bytes; + size_t nlate; + size_t nlate_bytes; + size_t nvalid; + size_t nvalid_bytes; +}; + +class TBNReaderThread : public BoundThread { + TBNReaderReader _disk; + FrameStats _stats; + std::vector _src_stats; + bool _have_frm; + FrameDesc _frm; +public: + enum { + READ_SUCCESS = 1 << 0, + READ_TIMEOUT = 1 << 1, + READ_INTERRUPTED = 1 << 2, + READ_ERROR = 1 << 3 + }; + TBNReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) + : BoundThread(core), _disk(fd, frm_size_max), _src_stats(nsrc), + _have_frm(false) { + this->reset_stats(); + } + // Reads, decodes and unpacks frames into the provided buffers + // Note: Read continues until the first frame that belongs + // beyond the end of the provided buffers. This frame is + // saved, accessible via get_last_frame(), and will be + // processed on the next call to run() if possible. + template + int run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + FrameDecoder* decode, + FrameProcessor* process) { + uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; + size_t local_ngood_bytes[2] = {0, 0}; + int ret; + while( true ) { + if( !_have_frm ) { + uint8_t* frm_ptr; + int frm_size = _disk.read_frame(&frm_ptr); + if( frm_size <= 0 ) { + if( errno == EAGAIN || errno == EWOULDBLOCK ) { + ret = READ_TIMEOUT; // Timed out + } else if( errno == EINTR ) { + ret = READ_INTERRUPTED; // Interrupted by signal + } else { + ret = READ_ERROR; // Socket error + } + break; + } + if( !(*decode)(frm_ptr, frm_size, &_frm) ) { + ++_stats.ninvalid; + _stats.ninvalid_bytes += frm_size; + continue; + } + _have_frm = true; + } + if( greater_equal(_frm.seq, seq_end) ) { + // Reached the end of this processing gulp, so leave this + // frame unprocessed and return. + ret = READ_SUCCESS; + break; + } + _have_frm = false; + if( less_than(_frm.seq, seq_beg) ) { + ++_stats.nlate; + _stats.nlate_bytes += _frm.payload_size; + ++_src_stats[_frm.src].nlate; + _src_stats[_frm.src].nlate_bytes += _frm.payload_size; + continue; + } + ++_stats.nvalid; + _stats.nvalid_bytes += _frm.payload_size; + ++_src_stats[_frm.src].nvalid; + _src_stats[_frm.src].nvalid_bytes += _frm.payload_size; + // HACK TODO: src_ngood_bytes should be accumulated locally and + // then atomically updated, like ngood_bytes. The + // current way is not thread-safe. + (*process)(&_frm, seq_beg, nseq_per_obuf, nbuf, obufs, + local_ngood_bytes, /*local_*/src_ngood_bytes); + } + if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } + if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } + return ret; + } + inline const FrameDesc* get_last_frame() const { + return _have_frm ? &_frm : NULL; + } + inline const FrameStats* get_stats() const { return &_stats; } + inline const FrameStats* get_stats(int src) const { return &_src_stats[src]; } + inline void reset_stats() { + ::memset(&_stats, 0, sizeof(_stats)); + ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(FrameStats)); + } +}; + +#pragma pack(1) +struct tbn_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t tuning_word; + uint16_t tbn_id; + uint16_t gain; + uint64_t time_tag; +}; + +class TBNDecoder { +protected: + int _nsrc; + int _src0; + inline bool valid_frame(const FrameDesc* frm) const { + return (frm->sync == 0x5CDEC0DE && + frm->src >= 0 && + frm->src < _nsrc && + frm->time_tag >= 0 && + frm->tuning >= 0 && + frm->valid_mode == 1); + } +public: + TBNDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} + inline bool operator()(const uint8_t* frm_ptr, + int frm_size, + FrameDesc* frm) const { + if( frm_size < (int)sizeof(tbn_hdr_type) ) { + return false; + } + const tbn_hdr_type* frm_hdr = (tbn_hdr_type*)frm_ptr; + const uint8_t* frm_pld = frm_ptr + sizeof(tbn_hdr_type); + int pld_size = frm_size - sizeof(tbn_hdr_type); + frm->sync = frm_hdr->sync_word; + frm->time_tag = be64toh(frm_hdr->time_tag); + frm->seq = frm->time_tag / 1960 / 512; + //frm->nsrc = frm_hdr->nroach; + frm->nsrc = _nsrc; + frm->src = (be16toh(frm_hdr->tbn_id) & 1023) - 1 - _src0; + frm->tuning = be32toh(frm_hdr->tuning_word); + frm->decimation = 1960; + frm->valid_mode = (be16toh(frm_hdr->tbn_id) >> 7) & 1; + frm->payload_size = pld_size; + frm->payload_ptr = frm_pld; + return this->valid_frame(frm); + } +}; + +class TBNProcessor { +public: + inline void operator()(const FrameDesc* frm, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + + (frm->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = frm->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][frm->src] += nbyte; + int payload_size = frm->payload_size; + + size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; + uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + int samp = 0; + for( ; samp<512; ++samp ) { // HACK TESTING + out[samp*frm->nsrc*2 + frm->src*2 + 0] = in[2*samp+0]; + out[samp*frm->nsrc*2 + frm->src*2 + 1] = in[2*samp+1]; + } + } + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nseq) { + uint8_t* __restrict__ aligned_data = (uint8_t*)data; + for( int t=0; t _process_time; + std::chrono::duration _reserve_time; + + int _nsrc; + int _nseq_per_buf; + int _slot_nframe; + BFoffset _seq; + BFoffset _time_tag; + int _chan0; + int _payload_size; + bool _active; + BFtbnreader_sequence_callback _sequence_callback; + + RingWrapper _ring; + RingWriter _oring; + std::queue > _bufs; + std::queue _buf_ngood_bytes; + std::queue > _buf_src_ngood_bytes; + std::shared_ptr _sequence; + size_t _ngood_bytes; + size_t _nmissing_bytes; + + inline size_t bufsize(int payload_size=-1) { + if( payload_size == -1 ) { + payload_size = _payload_size; + } + return _nseq_per_buf * _nsrc * payload_size; + } + inline void reserve_buf() { + _buf_ngood_bytes.push(0); + _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); + size_t size = this->bufsize(); + // TODO: Can make this simpler? + _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); + } + inline void commit_buf() { + size_t expected_bytes = _bufs.front()->size(); + + for( int src=0; src<_nsrc; ++src ) { + // TODO: This assumes all sources contribute equally; should really + // allow non-uniform partitioning. + size_t src_expected_bytes = expected_bytes / _nsrc; + size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; + size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; + // Detect >50% missing data from this source + if( src_nmissing_bytes > src_ngood_bytes ) { + // Zero-out this source's contribution to the buffer + uint8_t* data = (uint8_t*)_bufs.front()->data(); + _processor.blank_out_source(data, src, _nsrc, + _nseq_per_buf); + } + } + _buf_src_ngood_bytes.pop(); + + _ngood_bytes += _buf_ngood_bytes.front(); + _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); + _buf_ngood_bytes.pop(); + + _bufs.front()->commit(); + _bufs.pop(); + _seq += _nseq_per_buf; + } + inline void begin_sequence() { + BFoffset seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + const void* hdr; + size_t hdr_size; + BFoffset time_tag = _time_tag; + if( _sequence_callback ) { + int status = (*_sequence_callback)(seq0, + _time_tag, + _chan0, + _nsrc, + &hdr, + &hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + time_tag = _time_tag; + hdr = NULL; + hdr_size = 0; + } + const char* name = ""; + int nringlet = 1; + _sequence.reset(new WriteSequence(_oring, name, time_tag, + hdr_size, hdr, nringlet)); + } + inline void end_sequence() { + _sequence.reset(); // Note: This is releasing the shared_ptr + } +public: + inline BFtbnreader_impl(int fd, + BFring ring, + int nsrc, + int src0, + int buffer_nframe, + int slot_nframe, + BFtbnreader_sequence_callback sequence_callback, + int core) + : _reader(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor(), + _type_log("lwa_file/type"), + _bind_log("lwa_file/bind"), + _out_log("lwa_file/out"), + _size_log("lwa_file/sizes"), + _chan_log("lwa_file/chans"), + _stat_log("lwa_file/stats"), + _perf_log("lwa_file/perf"), + _nsrc(nsrc), _nseq_per_buf(buffer_nframe), _slot_nframe(slot_nframe), + _seq(0), _time_tag(0), _chan0(), _active(false), + _sequence_callback(sequence_callback), + _ring(ring), _oring(_ring), + // TODO: Add reset method for stats + _ngood_bytes(0), _nmissing_bytes(0) { + size_t contig_span = this->bufsize(TBN_FRAME_SIZE - sizeof(tbn_hdr_type)); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "tbn"); + _bind_log.update("ncore : %i\n" + "core0 : %i\n", + 1, core); + _out_log.update("nring : %i\n" + "ring0 : %s\n", + 1, _ring.name()); + _size_log.update("nsrc : %i\n" + "nseq_per_buf : %i\n" + "slot_nframe : %i\n", + _nsrc, _nseq_per_buf, _slot_nframe); + } + inline void flush() { + while( _bufs.size() ) { + this->commit_buf(); + } + if( _sequence ) { + this->end_sequence(); + } + } + inline void end_writing() { + this->flush(); + _oring.close(); + } + BFtbnreader_status read() { + _t0 = std::chrono::high_resolution_clock::now(); + + uint8_t* buf_ptrs[2]; + // Minor HACK to access the buffers in a 2-element queue + buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; + buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; + + size_t* ngood_bytes_ptrs[2]; + ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; + ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; + + size_t* src_ngood_bytes_ptrs[2]; + src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; + src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; + + int state = _reader.run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + &_decoder, + &_processor); + if( state & TBNReaderThread::READ_ERROR ) { + return BF_READ_ERROR; + } else if( state & TBNReaderThread::READ_INTERRUPTED ) { + return BF_READ_INTERRUPTED; + } + const FrameStats* stats = _reader.get_stats(); + _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" + << "nmissing_bytes : " << _nmissing_bytes << "\n" + << "ninvalid : " << stats->ninvalid << "\n" + << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" + << "nlate : " << stats->nlate << "\n" + << "nlate_bytes : " << stats->nlate_bytes << "\n" + << "nvalid : " << stats->nvalid << "\n" + << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; + + _t1 = std::chrono::high_resolution_clock::now(); + + BFtbnreader_status ret; + bool was_active = _active; + _active = state & TBNReaderThread::READ_SUCCESS; + if( _active ) { + const FrameDesc* frm = _reader.get_last_frame(); + if( frm ) { + //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; + } + else { + //cout << "No latest frame" << endl; + } + if( !was_active ) { + _seq = round_nearest(frm->seq, _nseq_per_buf); + _time_tag = frm->time_tag; + _chan0 = frm->tuning; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->begin_sequence(); + ret = BF_READ_STARTED; + } else { + //cout << "Continuing data, seq = " << seq << endl; + if( frm->tuning != _chan0 ) { + _time_tag = frm->time_tag; + _chan0 = frm->tuning; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->end_sequence(); + this->begin_sequence(); + ret = BF_READ_CHANGED; + } else { + ret = BF_READ_CONTINUED; + } + } + if( _bufs.size() == 2 ) { + this->commit_buf(); + } + this->reserve_buf(); + } else { + + if( was_active ) { + this->flush(); + ret = BF_READ_ENDED; + } else { + ret = BF_READ_NO_DATA; + } + } + + _t2 = std::chrono::high_resolution_clock::now(); + _process_time = std::chrono::duration_cast>(_t1-_t0); + _reserve_time = std::chrono::duration_cast>(_t2-_t1); + _perf_log.update() << "acquire_time : " << -1.0 << "\n" + << "process_time : " << _process_time.count() << "\n" + << "reserve_time : " << _reserve_time.count() << "\n"; + + return ret; + } +}; + +BFstatus bfTbnReaderCreate(BFtbnreader* obj, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_nframe, + BFsize slot_nframe, + BFtbnreader_sequence_callback sequence_callback, + int core) { + BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); + BF_TRY_RETURN_ELSE(*obj = new BFtbnreader_impl(fd, ring, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core), + *obj = 0); +} +BFstatus bfTbnReaderDestroy(BFtbnreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} +BFstatus bfTbnReaderRead(BFtbnreader obj, BFtbnreader_status* result) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN_ELSE(*result = obj->read(), + *result = BF_READ_ERROR); +} +BFstatus bfTbnReaderFlush(BFtbnreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->flush()); +} +BFstatus bfTbnReaderEnd(BFtbnreader obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->end_writing()); +} \ No newline at end of file From e30c7ecc8d19fef85eaee1d43f2cd65ca71570d2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 16 May 2018 13:05:38 -0600 Subject: [PATCH 002/424] Worked on merging the DRX and TBN readers into a single module. --- python/bifrost/{drx.py => disk_reader.py} | 0 python/bifrost/tbn.py | 53 -- src/Makefile | 3 +- src/bifrost/{drx_reader.h => disk_reader.h} | 43 +- src/{drx_reader.cpp => disk_reader.cpp} | 421 ++++++++--- .../tbn_reader.h => packet_formats.h} | 84 ++- src/tbn_reader.cpp | 711 ------------------ 7 files changed, 403 insertions(+), 912 deletions(-) rename python/bifrost/{drx.py => disk_reader.py} (100%) delete mode 100644 python/bifrost/tbn.py rename src/bifrost/{drx_reader.h => disk_reader.h} (61%) rename src/{drx_reader.cpp => disk_reader.cpp} (64%) rename src/{bifrost/tbn_reader.h => packet_formats.h} (54%) delete mode 100644 src/tbn_reader.cpp diff --git a/python/bifrost/drx.py b/python/bifrost/disk_reader.py similarity index 100% rename from python/bifrost/drx.py rename to python/bifrost/disk_reader.py diff --git a/python/bifrost/tbn.py b/python/bifrost/tbn.py deleted file mode 100644 index 81ec96d54..000000000 --- a/python/bifrost/tbn.py +++ /dev/null @@ -1,53 +0,0 @@ - -# Copyright (c) 2017, The Bifrost Authors. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of The Bifrost Authors nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# **TODO: Write tests for this class - -from libbifrost import _bf, _check, _get, BifrostObject - -class TbnReader(BifrostObject): - def __init__(self, fh, ring, nsrc, src0, - buffer_nframe, slot_nframe, sequence_callback, core=None): - if core is None: - core = -1 - BifrostObject.__init__( - self, _bf.bfTbnReaderCreate, _bf.bfTbnReaderDestroy, - fh.fileno(), ring.obj, nsrc, src0, - buffer_nframe, slot_nframe, - sequence_callback, core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.end() - def read(self): - status = _bf.BFtbnreader_status() - _check(_bf.bfTbnReaderRead(self.obj, status)) - return status - def flush(self): - _check(_bf.bfTbnReaderFlush(self.obj)) - def end(self): - _check(_bf.bfTbnReaderEnd(self.obj)) diff --git a/src/Makefile b/src/Makefile index ff994a37e..8d419af33 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,8 +16,7 @@ LIBBIFROST_OBJS = \ udp_socket.o \ udp_capture.o \ udp_transmit.o \ - drx_reader.o \ - tbn_reader.o \ + disk_reader.o \ unpack.o \ quantize.o \ proclog.o diff --git a/src/bifrost/drx_reader.h b/src/bifrost/disk_reader.h similarity index 61% rename from src/bifrost/drx_reader.h rename to src/bifrost/disk_reader.h index 00ce79ae8..1a28ea8d9 100644 --- a/src/bifrost/drx_reader.h +++ b/src/bifrost/disk_reader.h @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BF_DRX_READER_H_INCLUDE_GUARD_ -#define BF_DRX_READER_H_INCLUDE_GUARD_ +#ifndef BF_DISK_READER_H_INCLUDE_GUARD_ +#define BF_DISK_READER_H_INCLUDE_GUARD_ #ifdef __cplusplus extern "C" { @@ -35,12 +35,12 @@ extern "C" { #include - typedef struct BFdrxreader_impl* BFdrxreader; + typedef struct BFdiskreader_impl* BFdiskreader; - typedef int (*BFdrxreader_sequence_callback)(BFoffset, BFoffset, int, int, int, - void const**, size_t*); + typedef int (*BFdiskreader_sequence_callback)(BFoffset, BFoffset, int, int, int, + void const**, size_t*); - typedef enum BFdrxreader_status_ { + typedef enum BFdiskreader_status_ { BF_READ_STARTED, BF_READ_ENDED, BF_READ_CONTINUED, @@ -48,24 +48,25 @@ extern "C" { BF_READ_NO_DATA, BF_READ_INTERRUPTED, BF_READ_ERROR - } BFdrxreader_status; + } BFdiskreader_status; - BFstatus bfDrxReaderCreate(BFdrxreader* obj, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdrxreader_sequence_callback sequence_callback, - int core); - BFstatus bfDrxReaderDestroy(BFdrxreader obj); - BFstatus bfDrxReaderRead(BFdrxreader obj, BFdrxreader_status* result); - BFstatus bfDrxReaderFlush(BFdrxreader obj); - BFstatus bfDrxReaderEnd(BFdrxreader obj); + BFstatus bfDiskReaderCreate(BFdiskreader* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdiskreader_sequence_callback sequence_callback, + int core); + BFstatus bfDiskReaderDestroy(BFdiskreader obj); + BFstatus bfDiskReaderRead(BFdiskreader obj, BFdiskreader_status* result); + BFstatus bfDiskReaderFlush(BFdiskreader obj); + BFstatus bfDiskReaderEnd(BFdiskreader obj); #ifdef __cplusplus } // extern "C" #endif -#endif // BF_DRX_READER_H_INCLUDE_GUARD_ +#endif // BF_DISK_READER_H_INCLUDE_GUARD_ diff --git a/src/drx_reader.cpp b/src/disk_reader.cpp similarity index 64% rename from src/drx_reader.cpp rename to src/disk_reader.cpp index b3dd0a749..30b5303f4 100644 --- a/src/drx_reader.cpp +++ b/src/disk_reader.cpp @@ -27,7 +27,7 @@ */ #include "assert.hpp" -#include +#include #include #include using bifrost::ring::RingWrapper; @@ -35,6 +35,7 @@ using bifrost::ring::RingWriter; using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" +#include "packet_formats.h" #include // For ntohs #include // For recvfrom @@ -56,10 +57,6 @@ using bifrost::ring::WriteSequence; //#define BF_HWLOC_ENABLED 1 #endif -enum { - DRX_FRAME_SIZE = 4128 -}; - template inline T atomic_add_and_fetch(T* dst, T val) { return __sync_add_and_fetch(dst, val); // GCC builtin @@ -120,7 +117,7 @@ class AlignedBuffer { ~AlignedBuffer() { this->free(); } - inline void swap(AlignedBuffer const& other) { + inline void swap(AlignedBuffer & other) { std::swap(_buf, other._buf); std::swap(_size, other._size); std::swap(_alignment, other._alignment); @@ -184,11 +181,11 @@ class BoundThread { } }; -class DRXReaderReader { +class DiskFrameReader { int _fd; AlignedBuffer _buf; public: - DRXReaderReader(int fd, size_t frm_size_max=DRX_FRAME_SIZE) + DiskFrameReader(int fd, size_t frm_size_max=9000) : _fd(fd), _buf(frm_size_max) {} inline int read_frame(uint8_t** frm_ptr, int flags=0) { @@ -197,13 +194,14 @@ class DRXReaderReader { } }; - struct FrameDesc { - uint32_t sync; - uint64_t time_tag; uint64_t seq; int nsrc; int src; + int nchan; + int chan0; + uint32_t sync; + uint64_t time_tag; int tuning; int decimation; int valid_mode; @@ -219,8 +217,8 @@ struct FrameStats { size_t nvalid_bytes; }; -class DRXReaderThread : public BoundThread { - DRXReaderReader _disk; +class DiskReaderThread : public BoundThread { + DiskFrameReader _disk; FrameStats _stats; std::vector _src_stats; bool _have_frm; @@ -232,7 +230,7 @@ class DRXReaderThread : public BoundThread { READ_INTERRUPTED = 1 << 2, READ_ERROR = 1 << 3 }; - DRXReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) + DiskReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) : BoundThread(core), _disk(fd, frm_size_max), _src_stats(nsrc), _have_frm(false) { this->reset_stats(); @@ -317,22 +315,20 @@ class DRXReaderThread : public BoundThread { } }; -#pragma pack(1) -struct drx_hdr_type { - uint32_t sync_word; - uint32_t frame_count_word; - uint32_t seconds_count; - uint16_t decimation; - uint16_t time_offset; - uint64_t time_tag; - uint32_t tuning_word; - uint32_t flags; -}; - -class DRXDecoder { +class DiskDecoder { protected: int _nsrc; int _src0; +public: + DiskDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} + virtual inline bool operator()(const uint8_t* frm_ptr, + int frm_size, + FrameDesc* frm) const { + return false; + } +}; + +class DRXDecoder:DiskDecoder { inline bool valid_frame(const FrameDesc* frm) const { return (frm->sync == 0x5CDEC0DE && frm->src >= 0 && @@ -341,7 +337,7 @@ class DRXDecoder { frm->tuning >= 0); } public: - DRXDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} + DRXDecoder(int nsrc, int src0) : DiskDecoder(nsrc, src0) {} inline bool operator()(const uint8_t* frm_ptr, int frm_size, FrameDesc* frm) const { @@ -372,7 +368,57 @@ class DRXDecoder { } }; -class DRXProcessor { +class TBNDecoder:DiskDecoder { + inline bool valid_frame(const FrameDesc* frm) const { + return (frm->sync == 0x5CDEC0DE && + frm->src >= 0 && + frm->src < _nsrc && + frm->time_tag >= 0 && + frm->tuning >= 0 && + frm->valid_mode == 1); + } +public: + TBNDecoder(int nsrc, int src0) : DiskDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* frm_ptr, + int frm_size, + FrameDesc* frm) const { + if( frm_size < (int)sizeof(tbn_hdr_type) ) { + return false; + } + const tbn_hdr_type* frm_hdr = (tbn_hdr_type*)frm_ptr; + const uint8_t* frm_pld = frm_ptr + sizeof(tbn_hdr_type); + int pld_size = frm_size - sizeof(tbn_hdr_type); + frm->sync = frm_hdr->sync_word; + frm->time_tag = be64toh(frm_hdr->time_tag); + frm->seq = frm->time_tag / 1960 / 512; + //frm->nsrc = frm_hdr->nroach; + frm->nsrc = _nsrc; + frm->src = (be16toh(frm_hdr->tbn_id) & 1023) - 1 - _src0; + frm->tuning = be32toh(frm_hdr->tuning_word); + frm->decimation = 1960; + frm->valid_mode = (be16toh(frm_hdr->tbn_id) >> 7) & 1; + frm->payload_size = pld_size; + frm->payload_ptr = frm_pld; + return this->valid_frame(frm); + } +}; + +class DiskProcessor { +public: + virtual inline void operator()(const FrameDesc* frm, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) {} + virtual inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nseq) {} +}; + +class DRXProcessor:DiskProcessor { public: inline void operator()(const FrameDesc* frm, uint64_t seq0, @@ -415,6 +461,50 @@ class DRXProcessor { } }; +class TBNProcessor:DiskProcessor { +public: + inline void operator()(const FrameDesc* frm, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + + (frm->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = frm->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][frm->src] += nbyte; + int payload_size = frm->payload_size; + + size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; + uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + int samp = 0; + for( ; samp<512; ++samp ) { // HACK TESTING + out[samp*frm->nsrc*2 + frm->src*2 + 0] = in[2*samp+0]; + out[samp*frm->nsrc*2 + frm->src*2 + 1] = in[2*samp+1]; + } + } + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nseq) { + uint8_t* __restrict__ aligned_data = (uint8_t*)data; + for( int t=0; tcommit_buf(); + } + if( _sequence ) { + this->end_sequence(); + } + } + inline void end_writing() { + this->flush(); + _oring.close(); + } + virtual BFdiskreader_status read() { + return BF_READ_NO_DATA; + } +}; + +class BFdrxreader_impl:public BFdiskreader_impl { + DiskReaderThread _reader; + DRXDecoder _decoder; + DRXProcessor _processor; public: inline BFdrxreader_impl(int fd, BFring ring, @@ -542,22 +675,10 @@ class BFdrxreader_impl { int src0, int buffer_nframe, int slot_nframe, - BFdrxreader_sequence_callback sequence_callback, + BFdiskreader_sequence_callback sequence_callback, int core) - : _reader(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor(), - _type_log("lwa_file/type"), - _bind_log("lwa_file/bind"), - _out_log("lwa_file/out"), - _size_log("lwa_file/sizes"), - _chan_log("lwa_file/chans"), - _stat_log("lwa_file/stats"), - _perf_log("lwa_file/perf"), - _nsrc(nsrc), _nseq_per_buf(buffer_nframe), _slot_nframe(slot_nframe), - _seq(0), _time_tag(0), _chan0(), _active(false), _tstate(0), - _sequence_callback(sequence_callback), - _ring(ring), _oring(_ring), - // TODO: Add reset method for stats - _ngood_bytes(0), _nmissing_bytes(0) { + : BFdiskreader_impl(fd, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core), + _reader(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor() { size_t contig_span = this->bufsize(DRX_FRAME_SIZE - sizeof(drx_hdr_type)); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; @@ -575,19 +696,7 @@ class BFdrxreader_impl { "slot_nframe : %i\n", _nsrc, _nseq_per_buf, _slot_nframe); } - inline void flush() { - while( _bufs.size() ) { - this->commit_buf(); - } - if( _sequence ) { - this->end_sequence(); - } - } - inline void end_writing() { - this->flush(); - _oring.close(); - } - BFdrxreader_status read() { + BFdiskreader_status read() { _t0 = std::chrono::high_resolution_clock::now(); uint8_t* buf_ptrs[2]; @@ -611,9 +720,9 @@ class BFdrxreader_impl { src_ngood_bytes_ptrs, &_decoder, &_processor); - if( state & DRXReaderThread::READ_ERROR ) { + if( state & DiskReaderThread::READ_ERROR ) { return BF_READ_ERROR; - } else if( state & DRXReaderThread::READ_INTERRUPTED ) { + } else if( state & DiskReaderThread::READ_INTERRUPTED ) { return BF_READ_INTERRUPTED; } const FrameStats* stats = _reader.get_stats(); @@ -628,9 +737,9 @@ class BFdrxreader_impl { _t1 = std::chrono::high_resolution_clock::now(); - BFdrxreader_status ret; + BFdiskreader_status ret; bool was_active = _active; - _active = state & DRXReaderThread::READ_SUCCESS; + _active = state & DiskReaderThread::READ_SUCCESS; if( _active ) { const FrameDesc* frm = _reader.get_last_frame(); if( frm ) { @@ -716,36 +825,180 @@ class BFdrxreader_impl { } }; -BFstatus bfDrxReaderCreate(BFdrxreader* obj, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_nframe, - BFsize slot_nframe, - BFdrxreader_sequence_callback sequence_callback, - int core) { +class BFtbnreader_impl:public BFdiskreader_impl { + DiskReaderThread _reader; + TBNDecoder _decoder; + TBNProcessor _processor; +public: + inline BFtbnreader_impl(int fd, + BFring ring, + int nsrc, + int src0, + int buffer_nframe, + int slot_nframe, + BFdiskreader_sequence_callback sequence_callback, + int core) + : BFdiskreader_impl(fd, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core), + _reader(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor() { + size_t contig_span = this->bufsize(TBN_FRAME_SIZE - sizeof(tbn_hdr_type)); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "tbn"); + _bind_log.update("ncore : %i\n" + "core0 : %i\n", + 1, core); + _out_log.update("nring : %i\n" + "ring0 : %s\n", + 1, _ring.name()); + _size_log.update("nsrc : %i\n" + "nseq_per_buf : %i\n" + "slot_nframe : %i\n", + _nsrc, _nseq_per_buf, _slot_nframe); + } + BFdiskreader_status read() { + _t0 = std::chrono::high_resolution_clock::now(); + + uint8_t* buf_ptrs[2]; + // Minor HACK to access the buffers in a 2-element queue + buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; + buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; + + size_t* ngood_bytes_ptrs[2]; + ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; + ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; + + size_t* src_ngood_bytes_ptrs[2]; + src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; + src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; + + int state = _reader.run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + &_decoder, + &_processor); + if( state & DiskReaderThread::READ_ERROR ) { + return BF_READ_ERROR; + } else if( state & DiskReaderThread::READ_INTERRUPTED ) { + return BF_READ_INTERRUPTED; + } + const FrameStats* stats = _reader.get_stats(); + _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" + << "nmissing_bytes : " << _nmissing_bytes << "\n" + << "ninvalid : " << stats->ninvalid << "\n" + << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" + << "nlate : " << stats->nlate << "\n" + << "nlate_bytes : " << stats->nlate_bytes << "\n" + << "nvalid : " << stats->nvalid << "\n" + << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; + + _t1 = std::chrono::high_resolution_clock::now(); + + BFdiskreader_status ret; + bool was_active = _active; + _active = state & DiskReaderThread::READ_SUCCESS; + if( _active ) { + const FrameDesc* frm = _reader.get_last_frame(); + if( frm ) { + //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; + } + else { + //cout << "No latest frame" << endl; + } + if( !was_active ) { + _seq = round_nearest(frm->seq, _nseq_per_buf); + _time_tag = frm->time_tag; + _chan0 = frm->tuning; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->begin_sequence(); + ret = BF_READ_STARTED; + } else { + //cout << "Continuing data, seq = " << seq << endl; + if( frm->tuning != _chan0 ) { + _time_tag = frm->time_tag; + _chan0 = frm->tuning; + _payload_size = frm->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + this->end_sequence(); + this->begin_sequence(); + ret = BF_READ_CHANGED; + } else { + ret = BF_READ_CONTINUED; + } + } + if( _bufs.size() == 2 ) { + this->commit_buf(); + } + this->reserve_buf(); + } else { + + if( was_active ) { + this->flush(); + ret = BF_READ_ENDED; + } else { + ret = BF_READ_NO_DATA; + } + } + + _t2 = std::chrono::high_resolution_clock::now(); + _process_time = std::chrono::duration_cast>(_t1-_t0); + _reserve_time = std::chrono::duration_cast>(_t2-_t1); + _perf_log.update() << "acquire_time : " << -1.0 << "\n" + << "process_time : " << _process_time.count() << "\n" + << "reserve_time : " << _reserve_time.count() << "\n"; + + return ret; + } +}; + +BFstatus bfDiskReaderCreate(BFdiskreader* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_nframe, + BFsize slot_nframe, + BFdiskreader_sequence_callback sequence_callback, + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - BF_TRY_RETURN_ELSE(*obj = new BFdrxreader_impl(fd, ring, nsrc, src0, - buffer_nframe, slot_nframe, - sequence_callback, core), - *obj = 0); + if( format == std::string("drx") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdrxreader_impl(fd, ring, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core), + *obj = 0); + } else if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFtbnreader_impl(fd, ring, nsrc, src0, + buffer_nframe, slot_nframe, + sequence_callback, core), + *obj = 0); + } else { + return BF_STATUS_UNSUPPORTED; + } } -BFstatus bfDrxReaderDestroy(BFdrxreader obj) { + +BFstatus bfDiskReaderDestroy(BFdiskreader obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; return BF_STATUS_SUCCESS; } -BFstatus bfDrxReaderRead(BFdrxreader obj, BFdrxreader_status* result) { +BFstatus bfDiskReaderRead(BFdiskreader obj, BFdiskreader_status* result) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN_ELSE(*result = obj->read(), *result = BF_READ_ERROR); } -BFstatus bfDrxReaderFlush(BFdrxreader obj) { +BFstatus bfDiskReaderFlush(BFdiskreader obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->flush()); } -BFstatus bfDrxReaderEnd(BFdrxreader obj) { +BFstatus bfDiskReaderEnd(BFdiskreader obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->end_writing()); -} \ No newline at end of file +} diff --git a/src/bifrost/tbn_reader.h b/src/packet_formats.h similarity index 54% rename from src/bifrost/tbn_reader.h rename to src/packet_formats.h index 557b474af..a905793a3 100644 --- a/src/bifrost/tbn_reader.h +++ b/src/packet_formats.h @@ -26,46 +26,48 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BF_TBN_READER_H_INCLUDE_GUARD_ -#define BF_TBN_READER_H_INCLUDE_GUARD_ +#ifndef BF_PACKET_FORMATS_H_INCLUDE_GUARD_ +#define BF_PACKET_FORMATS_H_INCLUDE_GUARD_ -#ifdef __cplusplus -extern "C" { - #endif - - #include - - typedef struct BFtbnreader_impl* BFtbnreader; - - typedef int (*BFtbnreader_sequence_callback)(BFoffset, BFoffset, int, int, - void const**, size_t*); - - typedef enum BFtbnreader_status_ { - BF_READ_STARTED, - BF_READ_ENDED, - BF_READ_CONTINUED, - BF_READ_CHANGED, - BF_READ_NO_DATA, - BF_READ_INTERRUPTED, - BF_READ_ERROR - } BFtbnreader_status; - - BFstatus bfTbnReaderCreate(BFtbnreader* obj, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFtbnreader_sequence_callback sequence_callback, - int core); - BFstatus bfTbnReaderDestroy(BFtbnreader obj); - BFstatus bfTbnReaderRead(BFtbnreader obj, BFtbnreader_status* result); - BFstatus bfTbnReaderFlush(BFtbnreader obj); - BFstatus bfTbnReaderEnd(BFtbnreader obj); - - #ifdef __cplusplus -} // extern "C" -#endif +enum { + JUMBO_FRAME_SIZE = 9000, + DRX_FRAME_SIZE = 4128, + TBN_FRAME_SIZE = 1048 +}; -#endif // BF_TBN_READER_H_INCLUDE_GUARD_ +#pragma pack(1) +struct chips_hdr_type { + uint8_t roach; // Note: 1-based + uint8_t gbe; // (AKA tuning) + uint8_t nchan; // 109 + uint8_t nsubband; // 11 + uint8_t subband; // 0-11 + uint8_t nroach; // 16 + // Note: Big endian + uint16_t chan0; // First chan in packet + uint64_t seq; // Note: 1-based +}; + +#pragma pack(1) +struct drx_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t seconds_count; + uint16_t decimation; + uint16_t time_offset; + uint64_t time_tag; + uint32_t tuning_word; + uint32_t flags; +}; + +#pragma pack(1) +struct tbn_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t tuning_word; + uint16_t tbn_id; + uint16_t gain; + uint64_t time_tag; +}; + +#endif // BF_PACKET_FORMATS_H_INCLUDE_GUARD_ \ No newline at end of file diff --git a/src/tbn_reader.cpp b/src/tbn_reader.cpp deleted file mode 100644 index 24d301ab9..000000000 --- a/src/tbn_reader.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include -using bifrost::ring::RingWrapper; -using bifrost::ring::RingWriter; -using bifrost::ring::WriteSpan; -using bifrost::ring::WriteSequence; -#include "proclog.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include -#include - -#ifndef BF_HWLOC_ENABLED -#define BF_HWLOC_ENABLED 0 -//#define BF_HWLOC_ENABLED 1 -#endif - -enum { - TBN_FRAME_SIZE = 1048 -}; - -template -inline T atomic_add_and_fetch(T* dst, T val) { - return __sync_add_and_fetch(dst, val); // GCC builtin -} -template -inline T atomic_fetch_and_add(T* dst, T val) { - return __sync_fetch_and_add(dst, val); // GCC builtin -} - -// Wrap-safe comparisons -inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } -inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } - -template -class AlignedBuffer { - enum { DEFAULT_ALIGNMENT = 4096 }; - T* _buf; - size_t _size; - size_t _alignment; - void alloc() { - int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); - if( err ) { - throw std::runtime_error("Allocation failed"); - } - } - void copy(T const* srcbuf, size_t n) { - ::memcpy(_buf, srcbuf, n*sizeof(T)); - } - void free() { - if( _buf ) { - ::free(_buf); - _buf = 0; - _size = 0; - } - } -public: - //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) - // : _buf(0), _size(0), _alignment(alignment) {} - AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) - : _buf(0), _size(size), _alignment(alignment) { - this->alloc(); - } - AlignedBuffer(AlignedBuffer const& other) - : _buf(0), _size(other._size), _alignment(other._alignment) { - this->alloc(); - this->copy(other._buf, other._size); - } - AlignedBuffer& operator=(AlignedBuffer const& other) { - if( &other != this ) { - this->free(); - _size = other.size; - _alignment = other.alignment; - this->alloc(); - this->copy(other._buf, other._size); - } - return *this; - } - ~AlignedBuffer() { - this->free(); - } - inline void swap(AlignedBuffer const& other) { - std::swap(_buf, other._buf); - std::swap(_size, other._size); - std::swap(_alignment, other._alignment); - } - inline void resize(size_t n) { - if( n <= _size ) { - _size = n; - } else { - AlignedBuffer tmp(n, _alignment); - tmp.copy(&_buf[0], _size); - tmp.swap(*this); - } - } - inline size_t size() const { return _size; } - inline T & operator[](size_t i) { return _buf[i]; } - inline T const& operator[](size_t i) const { return _buf[i]; } -}; - -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; - } -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { - #if BF_HWLOC_ENABLED - HardwareLocality _hwloc; - #endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); - #if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); - #endif - } -}; - -class TBNReaderReader { - int _fd; - AlignedBuffer _buf; -public: - TBNReaderReader(int fd, size_t frm_size_max=TBN_FRAME_SIZE) - : _fd(fd), _buf(frm_size_max) - {} - inline int read_frame(uint8_t** frm_ptr, int flags=0) { - *frm_ptr = &_buf[0]; - return ::read(_fd, &_buf[0], _buf.size()); - } -}; - - -struct FrameDesc { - uint32_t sync; - uint64_t time_tag; - uint64_t seq; - int nsrc; - int src; - int tuning; - int decimation; - int valid_mode; - int payload_size; - const uint8_t* payload_ptr; -}; -struct FrameStats { - size_t ninvalid; - size_t ninvalid_bytes; - size_t nlate; - size_t nlate_bytes; - size_t nvalid; - size_t nvalid_bytes; -}; - -class TBNReaderThread : public BoundThread { - TBNReaderReader _disk; - FrameStats _stats; - std::vector _src_stats; - bool _have_frm; - FrameDesc _frm; -public: - enum { - READ_SUCCESS = 1 << 0, - READ_TIMEOUT = 1 << 1, - READ_INTERRUPTED = 1 << 2, - READ_ERROR = 1 << 3 - }; - TBNReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) - : BoundThread(core), _disk(fd, frm_size_max), _src_stats(nsrc), - _have_frm(false) { - this->reset_stats(); - } - // Reads, decodes and unpacks frames into the provided buffers - // Note: Read continues until the first frame that belongs - // beyond the end of the provided buffers. This frame is - // saved, accessible via get_last_frame(), and will be - // processed on the next call to run() if possible. - template - int run(uint64_t seq_beg, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t* ngood_bytes[], - size_t* src_ngood_bytes[], - FrameDecoder* decode, - FrameProcessor* process) { - uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; - size_t local_ngood_bytes[2] = {0, 0}; - int ret; - while( true ) { - if( !_have_frm ) { - uint8_t* frm_ptr; - int frm_size = _disk.read_frame(&frm_ptr); - if( frm_size <= 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK ) { - ret = READ_TIMEOUT; // Timed out - } else if( errno == EINTR ) { - ret = READ_INTERRUPTED; // Interrupted by signal - } else { - ret = READ_ERROR; // Socket error - } - break; - } - if( !(*decode)(frm_ptr, frm_size, &_frm) ) { - ++_stats.ninvalid; - _stats.ninvalid_bytes += frm_size; - continue; - } - _have_frm = true; - } - if( greater_equal(_frm.seq, seq_end) ) { - // Reached the end of this processing gulp, so leave this - // frame unprocessed and return. - ret = READ_SUCCESS; - break; - } - _have_frm = false; - if( less_than(_frm.seq, seq_beg) ) { - ++_stats.nlate; - _stats.nlate_bytes += _frm.payload_size; - ++_src_stats[_frm.src].nlate; - _src_stats[_frm.src].nlate_bytes += _frm.payload_size; - continue; - } - ++_stats.nvalid; - _stats.nvalid_bytes += _frm.payload_size; - ++_src_stats[_frm.src].nvalid; - _src_stats[_frm.src].nvalid_bytes += _frm.payload_size; - // HACK TODO: src_ngood_bytes should be accumulated locally and - // then atomically updated, like ngood_bytes. The - // current way is not thread-safe. - (*process)(&_frm, seq_beg, nseq_per_obuf, nbuf, obufs, - local_ngood_bytes, /*local_*/src_ngood_bytes); - } - if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } - if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } - return ret; - } - inline const FrameDesc* get_last_frame() const { - return _have_frm ? &_frm : NULL; - } - inline const FrameStats* get_stats() const { return &_stats; } - inline const FrameStats* get_stats(int src) const { return &_src_stats[src]; } - inline void reset_stats() { - ::memset(&_stats, 0, sizeof(_stats)); - ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(FrameStats)); - } -}; - -#pragma pack(1) -struct tbn_hdr_type { - uint32_t sync_word; - uint32_t frame_count_word; - uint32_t tuning_word; - uint16_t tbn_id; - uint16_t gain; - uint64_t time_tag; -}; - -class TBNDecoder { -protected: - int _nsrc; - int _src0; - inline bool valid_frame(const FrameDesc* frm) const { - return (frm->sync == 0x5CDEC0DE && - frm->src >= 0 && - frm->src < _nsrc && - frm->time_tag >= 0 && - frm->tuning >= 0 && - frm->valid_mode == 1); - } -public: - TBNDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} - inline bool operator()(const uint8_t* frm_ptr, - int frm_size, - FrameDesc* frm) const { - if( frm_size < (int)sizeof(tbn_hdr_type) ) { - return false; - } - const tbn_hdr_type* frm_hdr = (tbn_hdr_type*)frm_ptr; - const uint8_t* frm_pld = frm_ptr + sizeof(tbn_hdr_type); - int pld_size = frm_size - sizeof(tbn_hdr_type); - frm->sync = frm_hdr->sync_word; - frm->time_tag = be64toh(frm_hdr->time_tag); - frm->seq = frm->time_tag / 1960 / 512; - //frm->nsrc = frm_hdr->nroach; - frm->nsrc = _nsrc; - frm->src = (be16toh(frm_hdr->tbn_id) & 1023) - 1 - _src0; - frm->tuning = be32toh(frm_hdr->tuning_word); - frm->decimation = 1960; - frm->valid_mode = (be16toh(frm_hdr->tbn_id) >> 7) & 1; - frm->payload_size = pld_size; - frm->payload_ptr = frm_pld; - return this->valid_frame(frm); - } -}; - -class TBNProcessor { -public: - inline void operator()(const FrameDesc* frm, - uint64_t seq0, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t ngood_bytes[], - size_t* src_ngood_bytes[]) { - int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + - (frm->seq - seq0 >= 2*nseq_per_obuf)); - size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; - size_t nbyte = frm->payload_size; - ngood_bytes[obuf_idx] += nbyte; - src_ngood_bytes[obuf_idx][frm->src] += nbyte; - int payload_size = frm->payload_size; - - size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; - - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) - uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; - uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - - int samp = 0; - for( ; samp<512; ++samp ) { // HACK TESTING - out[samp*frm->nsrc*2 + frm->src*2 + 0] = in[2*samp+0]; - out[samp*frm->nsrc*2 + frm->src*2 + 1] = in[2*samp+1]; - } - } - inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; - for( int t=0; t _process_time; - std::chrono::duration _reserve_time; - - int _nsrc; - int _nseq_per_buf; - int _slot_nframe; - BFoffset _seq; - BFoffset _time_tag; - int _chan0; - int _payload_size; - bool _active; - BFtbnreader_sequence_callback _sequence_callback; - - RingWrapper _ring; - RingWriter _oring; - std::queue > _bufs; - std::queue _buf_ngood_bytes; - std::queue > _buf_src_ngood_bytes; - std::shared_ptr _sequence; - size_t _ngood_bytes; - size_t _nmissing_bytes; - - inline size_t bufsize(int payload_size=-1) { - if( payload_size == -1 ) { - payload_size = _payload_size; - } - return _nseq_per_buf * _nsrc * payload_size; - } - inline void reserve_buf() { - _buf_ngood_bytes.push(0); - _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); - size_t size = this->bufsize(); - // TODO: Can make this simpler? - _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); - } - inline void commit_buf() { - size_t expected_bytes = _bufs.front()->size(); - - for( int src=0; src<_nsrc; ++src ) { - // TODO: This assumes all sources contribute equally; should really - // allow non-uniform partitioning. - size_t src_expected_bytes = expected_bytes / _nsrc; - size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; - size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; - // Detect >50% missing data from this source - if( src_nmissing_bytes > src_ngood_bytes ) { - // Zero-out this source's contribution to the buffer - uint8_t* data = (uint8_t*)_bufs.front()->data(); - _processor.blank_out_source(data, src, _nsrc, - _nseq_per_buf); - } - } - _buf_src_ngood_bytes.pop(); - - _ngood_bytes += _buf_ngood_bytes.front(); - _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); - _buf_ngood_bytes.pop(); - - _bufs.front()->commit(); - _bufs.pop(); - _seq += _nseq_per_buf; - } - inline void begin_sequence() { - BFoffset seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - const void* hdr; - size_t hdr_size; - BFoffset time_tag = _time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(seq0, - _time_tag, - _chan0, - _nsrc, - &hdr, - &hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - time_tag = _time_tag; - hdr = NULL; - hdr_size = 0; - } - const char* name = ""; - int nringlet = 1; - _sequence.reset(new WriteSequence(_oring, name, time_tag, - hdr_size, hdr, nringlet)); - } - inline void end_sequence() { - _sequence.reset(); // Note: This is releasing the shared_ptr - } -public: - inline BFtbnreader_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_nframe, - int slot_nframe, - BFtbnreader_sequence_callback sequence_callback, - int core) - : _reader(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor(), - _type_log("lwa_file/type"), - _bind_log("lwa_file/bind"), - _out_log("lwa_file/out"), - _size_log("lwa_file/sizes"), - _chan_log("lwa_file/chans"), - _stat_log("lwa_file/stats"), - _perf_log("lwa_file/perf"), - _nsrc(nsrc), _nseq_per_buf(buffer_nframe), _slot_nframe(slot_nframe), - _seq(0), _time_tag(0), _chan0(), _active(false), - _sequence_callback(sequence_callback), - _ring(ring), _oring(_ring), - // TODO: Add reset method for stats - _ngood_bytes(0), _nmissing_bytes(0) { - size_t contig_span = this->bufsize(TBN_FRAME_SIZE - sizeof(tbn_hdr_type)); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "tbn"); - _bind_log.update("ncore : %i\n" - "core0 : %i\n", - 1, core); - _out_log.update("nring : %i\n" - "ring0 : %s\n", - 1, _ring.name()); - _size_log.update("nsrc : %i\n" - "nseq_per_buf : %i\n" - "slot_nframe : %i\n", - _nsrc, _nseq_per_buf, _slot_nframe); - } - inline void flush() { - while( _bufs.size() ) { - this->commit_buf(); - } - if( _sequence ) { - this->end_sequence(); - } - } - inline void end_writing() { - this->flush(); - _oring.close(); - } - BFtbnreader_status read() { - _t0 = std::chrono::high_resolution_clock::now(); - - uint8_t* buf_ptrs[2]; - // Minor HACK to access the buffers in a 2-element queue - buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; - buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; - - size_t* ngood_bytes_ptrs[2]; - ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; - ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; - - size_t* src_ngood_bytes_ptrs[2]; - src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; - src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - - int state = _reader.run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - &_decoder, - &_processor); - if( state & TBNReaderThread::READ_ERROR ) { - return BF_READ_ERROR; - } else if( state & TBNReaderThread::READ_INTERRUPTED ) { - return BF_READ_INTERRUPTED; - } - const FrameStats* stats = _reader.get_stats(); - _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" - << "nmissing_bytes : " << _nmissing_bytes << "\n" - << "ninvalid : " << stats->ninvalid << "\n" - << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" - << "nlate : " << stats->nlate << "\n" - << "nlate_bytes : " << stats->nlate_bytes << "\n" - << "nvalid : " << stats->nvalid << "\n" - << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; - - _t1 = std::chrono::high_resolution_clock::now(); - - BFtbnreader_status ret; - bool was_active = _active; - _active = state & TBNReaderThread::READ_SUCCESS; - if( _active ) { - const FrameDesc* frm = _reader.get_last_frame(); - if( frm ) { - //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; - } - else { - //cout << "No latest frame" << endl; - } - if( !was_active ) { - _seq = round_nearest(frm->seq, _nseq_per_buf); - _time_tag = frm->time_tag; - _chan0 = frm->tuning; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->begin_sequence(); - ret = BF_READ_STARTED; - } else { - //cout << "Continuing data, seq = " << seq << endl; - if( frm->tuning != _chan0 ) { - _time_tag = frm->time_tag; - _chan0 = frm->tuning; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->end_sequence(); - this->begin_sequence(); - ret = BF_READ_CHANGED; - } else { - ret = BF_READ_CONTINUED; - } - } - if( _bufs.size() == 2 ) { - this->commit_buf(); - } - this->reserve_buf(); - } else { - - if( was_active ) { - this->flush(); - ret = BF_READ_ENDED; - } else { - ret = BF_READ_NO_DATA; - } - } - - _t2 = std::chrono::high_resolution_clock::now(); - _process_time = std::chrono::duration_cast>(_t1-_t0); - _reserve_time = std::chrono::duration_cast>(_t2-_t1); - _perf_log.update() << "acquire_time : " << -1.0 << "\n" - << "process_time : " << _process_time.count() << "\n" - << "reserve_time : " << _reserve_time.count() << "\n"; - - return ret; - } -}; - -BFstatus bfTbnReaderCreate(BFtbnreader* obj, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_nframe, - BFsize slot_nframe, - BFtbnreader_sequence_callback sequence_callback, - int core) { - BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - BF_TRY_RETURN_ELSE(*obj = new BFtbnreader_impl(fd, ring, nsrc, src0, - buffer_nframe, slot_nframe, - sequence_callback, core), - *obj = 0); -} -BFstatus bfTbnReaderDestroy(BFtbnreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - delete obj; - return BF_STATUS_SUCCESS; -} -BFstatus bfTbnReaderRead(BFtbnreader obj, BFtbnreader_status* result) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN_ELSE(*result = obj->read(), - *result = BF_READ_ERROR); -} -BFstatus bfTbnReaderFlush(BFtbnreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->flush()); -} -BFstatus bfTbnReaderEnd(BFtbnreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->end_writing()); -} \ No newline at end of file From 9a4a917414a0610f74b33587c8e344bbdfd10e5e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 16 May 2018 13:10:28 -0600 Subject: [PATCH 003/424] Updated bifrost.disk_reader to be what it claims to be. --- python/bifrost/disk_reader.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/bifrost/disk_reader.py b/python/bifrost/disk_reader.py index 234a8e1ec..023d230a7 100644 --- a/python/bifrost/disk_reader.py +++ b/python/bifrost/disk_reader.py @@ -29,14 +29,14 @@ from libbifrost import _bf, _check, _get, BifrostObject -class DrxReader(BifrostObject): - def __init__(self, fh, ring, nsrc, src0, +class DiskReader(BifrostObject): + def __init__(self, fmt, fh, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core=None): if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfDrxReaderCreate, _bf.bfDrxReaderDestroy, - fh.fileno(), ring.obj, nsrc, src0, + self, _bf.bfDiskReaderCreate, _bf.bfDiskReaderDestroy, + fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core) def __enter__(self): @@ -44,10 +44,10 @@ def __enter__(self): def __exit__(self, type, value, tb): self.end() def read(self): - status = _bf.BFdrxreader_status() - _check(_bf.bfDrxReaderRead(self.obj, status)) + status = _bf.BFdiskreader_status() + _check(_bf.bfDiskReaderRead(self.obj, status)) return status def flush(self): - _check(_bf.bfDrxReaderFlush(self.obj)) + _check(_bf.bfDiskReaderFlush(self.obj)) def end(self): - _check(_bf.bfDrxReaderEnd(self.obj)) + _check(_bf.bfDiskReaderEnd(self.obj)) From c36e072a7602ab6f73c6aaeebbfc3fb80d2d4613 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 May 2019 13:18:18 -0600 Subject: [PATCH 004/424] Started working on unifing the disk reader and UDP capture modules. This is done through new base classes in data_capture.cpp. Also, added a new formats directory to store packet format information and processing. --- src/Makefile | 1 + .../data_capture.h} | 72 +- src/bifrost/disk_reader.h | 59 +- src/bifrost/udp_capture.h | 36 +- src/data_capture.cpp | 160 +++ src/data_capture.hpp | 368 ++++++ src/disk_reader.cpp | 1049 ++++------------- src/formats/base.hpp | 96 ++ src/formats/chips.hpp | 166 +++ src/formats/drx.hpp | 131 ++ src/formats/formats.hpp | 33 + src/formats/tbn.hpp | 124 ++ src/udp_capture.cpp | 831 ++++--------- 13 files changed, 1595 insertions(+), 1531 deletions(-) rename src/{packet_formats.h => bifrost/data_capture.h} (60%) create mode 100644 src/data_capture.cpp create mode 100644 src/data_capture.hpp create mode 100644 src/formats/base.hpp create mode 100644 src/formats/chips.hpp create mode 100644 src/formats/drx.hpp create mode 100644 src/formats/formats.hpp create mode 100644 src/formats/tbn.hpp diff --git a/src/Makefile b/src/Makefile index 8d419af33..43d1cee35 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ LIBBIFROST_OBJS = \ ring_impl.o \ array.o \ address.o \ + data_capture.o \ udp_socket.o \ udp_capture.o \ udp_transmit.o \ diff --git a/src/packet_formats.h b/src/bifrost/data_capture.h similarity index 60% rename from src/packet_formats.h rename to src/bifrost/data_capture.h index a905793a3..c0def94a4 100644 --- a/src/packet_formats.h +++ b/src/bifrost/data_capture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,48 +26,38 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BF_PACKET_FORMATS_H_INCLUDE_GUARD_ -#define BF_PACKET_FORMATS_H_INCLUDE_GUARD_ +#ifndef BF_DATA_CAPTURE_H_INCLUDE_GUARD_ +#define BF_DATA_CAPTURE_H_INCLUDE_GUARD_ -enum { - JUMBO_FRAME_SIZE = 9000, - DRX_FRAME_SIZE = 4128, - TBN_FRAME_SIZE = 1048 -}; +#ifdef __cplusplus +extern "C" { +#endif -#pragma pack(1) -struct chips_hdr_type { - uint8_t roach; // Note: 1-based - uint8_t gbe; // (AKA tuning) - uint8_t nchan; // 109 - uint8_t nsubband; // 11 - uint8_t subband; // 0-11 - uint8_t nroach; // 16 - // Note: Big endian - uint16_t chan0; // First chan in packet - uint64_t seq; // Note: 1-based -}; +#include +#include -#pragma pack(1) -struct drx_hdr_type { - uint32_t sync_word; - uint32_t frame_count_word; - uint32_t seconds_count; - uint16_t decimation; - uint16_t time_offset; - uint64_t time_tag; - uint32_t tuning_word; - uint32_t flags; -}; +typedef struct BFdatacapture_impl* BFdatacapture; -#pragma pack(1) -struct tbn_hdr_type { - uint32_t sync_word; - uint32_t frame_count_word; - uint32_t tuning_word; - uint16_t tbn_id; - uint16_t gain; - uint64_t time_tag; -}; +typedef enum BFdatacapture_status_ { + BF_CAPTURE_STARTED, + BF_CAPTURE_ENDED, + BF_CAPTURE_CONTINUED, + BF_CAPTURE_CHANGED, + BF_CAPTURE_NO_DATA, + BF_CAPTURE_INTERRUPTED, + BF_CAPTURE_ERROR +} BFdatacapture_status; -#endif // BF_PACKET_FORMATS_H_INCLUDE_GUARD_ \ No newline at end of file + + +BFstatus bfDataCaptureDestroy(BFdatacapture obj); +BFstatus bfDataCaptureRecv(BFdatacapture obj, BFdatacapture_status* result); +BFstatus bfDataCaptureFlush(BFdatacapture obj); +BFstatus bfDataCaptureEnd(BFdatacapture obj); +// TODO: bfDataCaptureGetXX + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_DATA_CAPTURE_H_INCLUDE_GUARD_ diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index 1a28ea8d9..580fb383d 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,41 +31,30 @@ #ifdef __cplusplus extern "C" { - #endif - - #include - - typedef struct BFdiskreader_impl* BFdiskreader; - - typedef int (*BFdiskreader_sequence_callback)(BFoffset, BFoffset, int, int, int, - void const**, size_t*); - - typedef enum BFdiskreader_status_ { - BF_READ_STARTED, - BF_READ_ENDED, - BF_READ_CONTINUED, - BF_READ_CHANGED, - BF_READ_NO_DATA, - BF_READ_INTERRUPTED, - BF_READ_ERROR - } BFdiskreader_status; - - BFstatus bfDiskReaderCreate(BFdiskreader* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdiskreader_sequence_callback sequence_callback, - int core); - BFstatus bfDiskReaderDestroy(BFdiskreader obj); - BFstatus bfDiskReaderRead(BFdiskreader obj, BFdiskreader_status* result); - BFstatus bfDiskReaderFlush(BFdiskreader obj); - BFstatus bfDiskReaderEnd(BFdiskreader obj); +#endif - #ifdef __cplusplus +#include +#include +#include + +typedef struct BFdiskreader_impl* BFdiskreader; + +typedef int (*BFdiskreader_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); + +BFstatus bfDiskReaderCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdiskreader_sequence_callback sequence_callback, + int core); + +#ifdef __cplusplus } // extern "C" #endif diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index 5b8fda741..5d25ad6e1 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -33,6 +33,7 @@ extern "C" { #endif +#include #include #include @@ -41,32 +42,17 @@ typedef struct BFudpcapture_impl* BFudpcapture; typedef int (*BFudpcapture_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); -typedef enum BFudpcapture_status_ { - BF_CAPTURE_STARTED, - BF_CAPTURE_ENDED, - BF_CAPTURE_CONTINUED, - BF_CAPTURE_CHANGED, - BF_CAPTURE_NO_DATA, - BF_CAPTURE_INTERRUPTED, - BF_CAPTURE_ERROR -} BFudpcapture_status; - -BFstatus bfUdpCaptureCreate(BFudpcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, +BFstatus bfUdpCaptureCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, BFudpcapture_sequence_callback sequence_callback, - int core); -BFstatus bfUdpCaptureDestroy(BFudpcapture obj); -BFstatus bfUdpCaptureRecv(BFudpcapture obj, BFudpcapture_status* result); -BFstatus bfUdpCaptureFlush(BFudpcapture obj); -BFstatus bfUdpCaptureEnd(BFudpcapture obj); -// TODO: bfUdpCaptureGetXX + int core); #ifdef __cplusplus } // extern "C" diff --git a/src/data_capture.cpp b/src/data_capture.cpp new file mode 100644 index 000000000..8b184390c --- /dev/null +++ b/src/data_capture.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "data_capture.hpp" + +#if BF_HWLOC_ENABLED +int HardwareLocality::bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; +} +#endif // BF_HWLOC_ENABLED + +BFdatacapture_status BFdatacapture_impl::recv() { + _t0 = std::chrono::high_resolution_clock::now(); + + uint8_t* buf_ptrs[2]; + // Minor HACK to access the buffers in a 2-element queue + buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; + buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; + + size_t* ngood_bytes_ptrs[2]; + ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; + ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; + + size_t* src_ngood_bytes_ptrs[2]; + src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; + src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; + + int state = _capture.run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + &_decoder, + &_processor); + if( state & DataCaptureThread::CAPTURE_ERROR ) { + return BF_CAPTURE_ERROR; + } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { + return BF_CAPTURE_INTERRUPTED; + } + const PacketStats* stats = _capture.get_stats(); + _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" + << "nmissing_bytes : " << _nmissing_bytes << "\n" + << "ninvalid : " << stats->ninvalid << "\n" + << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" + << "nlate : " << stats->nlate << "\n" + << "nlate_bytes : " << stats->nlate_bytes << "\n" + << "nvalid : " << stats->nvalid << "\n" + << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; + + _t1 = std::chrono::high_resolution_clock::now(); + + BFoffset seq0, time_tag; + const void* hdr; + size_t hdr_size; + + BFdatacapture_status ret; + bool was_active = _active; + _active = state & DataCaptureThread::CAPTURE_SUCCESS; + if( _active ) { + const PacketDesc* pkt = _capture.get_last_packet(); + this->on_sequence_active(pkt); + if( !was_active ) { + //cout << "Beginning of sequence, first pkt seq = " << pkt->seq << endl; + this->on_sequence_start(pkt, &seq0, &time_tag, &hdr, &hdr_size); + this->begin_sequence(seq0, time_tag, hdr, hdr_size); + ret = BF_CAPTURE_STARTED; + } else { + //cout << "Continuing data, seq = " << seq << endl; + if( this->has_sequence_changed(pkt) ) { + this->on_sequence_changed(pkt, &seq0, &time_tag, &hdr, &hdr_size); + this->end_sequence(); + this->begin_sequence(seq0, time_tag, hdr, hdr_size); + ret = BF_CAPTURE_CHANGED; + } else { + ret = BF_CAPTURE_CONTINUED; + } + } + if( _bufs.size() == 2 ) { + this->commit_buf(); + } + this->reserve_buf(); + } else { + + if( was_active ) { + this->flush(); + ret = BF_CAPTURE_ENDED; + } else { + ret = BF_CAPTURE_NO_DATA; + } + } + + _t2 = std::chrono::high_resolution_clock::now(); + _process_time = std::chrono::duration_cast>(_t1-_t0); + _reserve_time = std::chrono::duration_cast>(_t2-_t1); + _perf_log.update() << "acquire_time : " << -1.0 << "\n" + << "process_time : " << _process_time.count() << "\n" + << "reserve_time : " << _reserve_time.count() << "\n"; + + return ret; +} + +BFstatus bfDataCaptureDestroy(BFdatacapture obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + +BFstatus bfDataCaptureRecv(BFdatacapture obj, BFdatacapture_status* result) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN_ELSE(*result = obj->recv(), + *result = BF_CAPTURE_ERROR); +} + +BFstatus bfDataCaptureFlush(BFdatacapture obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->flush()); +} + +BFstatus bfDataCaptureEnd(BFdatacapture obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->end_writing()); +} diff --git a/src/data_capture.hpp b/src/data_capture.hpp new file mode 100644 index 000000000..31d063f32 --- /dev/null +++ b/src/data_capture.hpp @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "assert.hpp" +#include +#include +#include +using bifrost::ring::RingWrapper; +using bifrost::ring::RingWriter; +using bifrost::ring::WriteSpan; +using bifrost::ring::WriteSequence; +#include "proclog.hpp" +#include "formats/formats.hpp" + +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include + +#ifndef BF_HWLOC_ENABLED +#define BF_HWLOC_ENABLED 0 +//#define BF_HWLOC_ENABLED 1 +#endif + +template +inline T atomic_add_and_fetch(T* dst, T val) { + return __sync_add_and_fetch(dst, val); // GCC builtin +} +template +inline T atomic_fetch_and_add(T* dst, T val) { + return __sync_fetch_and_add(dst, val); // GCC builtin +} + +// Wrap-safe comparisons +inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } +inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } + +template +class AlignedBuffer { + enum { DEFAULT_ALIGNMENT = 4096 }; + T* _buf; + size_t _size; + size_t _alignment; + void alloc() { + int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); + if( err ) { + throw std::runtime_error("Allocation failed"); + } + } + void copy(T const* srcbuf, size_t n) { + ::memcpy(_buf, srcbuf, n*sizeof(T)); + } + void free() { + if( _buf ) { + ::free(_buf); + _buf = 0; + _size = 0; + } + } +public: + //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) + // : _buf(0), _size(0), _alignment(alignment) {} + AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) + : _buf(0), _size(size), _alignment(alignment) { + this->alloc(); + } + AlignedBuffer(AlignedBuffer const& other) + : _buf(0), _size(other.size), _alignment(other.alignment) { + this->alloc(); + this->copy(other._buf, other._size); + } + AlignedBuffer& operator=(AlignedBuffer const& other) { + if( &other != this ) { + this->free(); + _size = other.size; + _alignment = other.alignment; + this->alloc(); + this->copy(other._buf, other._size); + } + return *this; + } + ~AlignedBuffer() { + this->free(); + } + inline void swap(AlignedBuffer & other) { + std::swap(_buf, other._buf); + std::swap(_size, other._size); + std::swap(_alignment, other._alignment); + } + inline void resize(size_t n) { + if( n <= _size ) { + _size = n; + } else { + AlignedBuffer tmp(n, _alignment); + tmp.copy(&_buf[0], _size); + tmp.swap(*this); + } + } + inline size_t size() const { return _size; } + inline T & operator[](size_t i) { return _buf[i]; } + inline T const& operator[](size_t i) const { return _buf[i]; } +}; + +#if BF_HWLOC_ENABLED +#include +class HardwareLocality { + hwloc_topology_t _topo; + HardwareLocality(HardwareLocality const&); + HardwareLocality& operator=(HardwareLocality const&); +public: + HardwareLocality() { + hwloc_topology_init(&_topo); + hwloc_topology_load(_topo); + } + ~HardwareLocality() { + hwloc_topology_destroy(_topo); + } + int bind_memory_to_core(int core); +}; +#endif // BF_HWLOC_ENABLED + +class BoundThread { +#if BF_HWLOC_ENABLED + HardwareLocality _hwloc; +#endif +public: + BoundThread(int core) { + bfAffinitySetCore(core); +#if BF_HWLOC_ENABLED + assert(_hwloc.bind_memory_to_core(core) == 0); +#endif + } +}; + +class DataCaptureMethod { +protected: + int _fd; + AlignedBuffer _buf; +public: + DataCaptureMethod(int fd, size_t pkt_size_max=9000) + : _fd(fd), _buf(pkt_size_max) + {} + virtual inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + return 0; + } +}; + +struct PacketStats { + size_t ninvalid; + size_t ninvalid_bytes; + size_t nlate; + size_t nlate_bytes; + size_t nvalid; + size_t nvalid_bytes; +}; + +class DataCaptureThread : public BoundThread { +protected: + DataCaptureMethod _mthd; + PacketStats _stats; + std::vector _src_stats; + bool _have_pkt; + PacketDesc _pkt; +public: + enum { + CAPTURE_SUCCESS = 1 << 0, + CAPTURE_TIMEOUT = 1 << 1, + CAPTURE_INTERRUPTED = 1 << 2, + CAPTURE_ERROR = 1 << 3 + }; + DataCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) + : BoundThread(core), _mthd(fd, pkt_size_max), _src_stats(nsrc), + _have_pkt(false) { + this->reset_stats(); + } + virtual int run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + PacketDecoder* decode, + PacketProcessor* process) { + return CAPTURE_ERROR; + } + inline const PacketDesc* get_last_packet() const { + return _have_pkt ? &_pkt : NULL; + } + inline void reset_last_packet() { + _have_pkt = false; + } + inline const PacketStats* get_stats() const { return &_stats; } + inline const PacketStats* get_stats(int src) const { return &_src_stats[src]; } + inline void reset_stats() { + ::memset(&_stats, 0, sizeof(_stats)); + ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(PacketStats)); + } +}; + +inline uint64_t round_up(uint64_t val, uint64_t mult) { + return (val == 0 ? + 0 : + ((val-1)/mult+1)*mult); +} +inline uint64_t round_nearest(uint64_t val, uint64_t mult) { + return (2*val/mult+1)/2*mult; +} + +class BFdatacapture_impl { +protected: + std::string _name; + DataCaptureThread _capture; + PacketDecoder _decoder; + PacketProcessor _processor; + ProcLog _bind_log; + ProcLog _out_log; + ProcLog _size_log; + ProcLog _stat_log; + ProcLog _perf_log; + pid_t _pid; + + std::chrono::high_resolution_clock::time_point _t0; + std::chrono::high_resolution_clock::time_point _t1; + std::chrono::high_resolution_clock::time_point _t2; + std::chrono::duration _process_time; + std::chrono::duration _reserve_time; + + int _nsrc; + int _nseq_per_buf; + int _slot_ntime; + BFoffset _seq; + int _chan0; + int _nchan; + int _payload_size; + bool _active; + + RingWrapper _ring; + RingWriter _oring; + std::queue > _bufs; + std::queue _buf_ngood_bytes; + std::queue > _buf_src_ngood_bytes; + std::shared_ptr _sequence; + size_t _ngood_bytes; + size_t _nmissing_bytes; + + inline size_t bufsize(int payload_size=-1) { + if( payload_size == -1 ) { + payload_size = _payload_size; + } + return _nseq_per_buf * _nsrc * payload_size * BF_UNPACK_FACTOR; + } + inline void reserve_buf() { + _buf_ngood_bytes.push(0); + _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); + size_t size = this->bufsize(); + // TODO: Can make this simpler? + _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); + } + inline void commit_buf() { + size_t expected_bytes = _bufs.front()->size(); + + for( int src=0; src<_nsrc; ++src ) { + // TODO: This assumes all sources contribute equally; should really + // allow non-uniform partitioning. + size_t src_expected_bytes = expected_bytes / _nsrc; + size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; + size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; + // Detect >50% missing data from this source + if( src_nmissing_bytes > src_ngood_bytes ) { + // Zero-out this source's contribution to the buffer + uint8_t* data = (uint8_t*)_bufs.front()->data(); + _processor.blank_out_source(data, src, _nsrc, + _nchan, _nseq_per_buf); + } + } + _buf_src_ngood_bytes.pop(); + + _ngood_bytes += _buf_ngood_bytes.front(); + //_nmissing_bytes += _bufs.front()->size() - _buf_ngood_bytes.front(); + //// HACK TESTING 15/16 correction for missing roach11 + //_nmissing_bytes += _bufs.front()->size()*15/16 - _buf_ngood_bytes.front(); + _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); + _buf_ngood_bytes.pop(); + + _bufs.front()->commit(); + _bufs.pop(); + _seq += _nseq_per_buf; + } + inline void begin_sequence(BFoffset seq0, BFoffset time_tag, const void* hdr, size_t hdr_size) { + const char* name = ""; + int nringlet = 1; + _sequence.reset(new WriteSequence(_oring, name, time_tag, + hdr_size, hdr, nringlet)); + } + inline void end_sequence() { + _sequence.reset(); // Note: This is releasing the shared_ptr + } + virtual void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} + virtual void on_sequence_active(const PacketDesc* pkt) {} + virtual inline bool has_sequence_changed(const PacketDesc* pkt) { + return false; + } + virtual void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} +public: + inline BFdatacapture_impl(std::string name, + int fd, + BFring ring, + int nsrc, + int src0, + int max_payload_size, + int buffer_ntime, + int slot_ntime, + int core) + : _name(name), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + _bind_log(_name+"/bind"), + _out_log(_name+"/out"), + _size_log(_name+"/sizes"), + _stat_log(_name+"/stats"), + _perf_log(_name+"/perf"), + _nsrc(nsrc), _nseq_per_buf(buffer_ntime), _slot_ntime(slot_ntime), + _seq(), _chan0(), _nchan(), _active(false), + _ring(ring), _oring(_ring), + // TODO: Add reset method for stats + _ngood_bytes(0), _nmissing_bytes(0) {} + virtual ~BFdatacapture_impl() {} + inline void flush() { + while( _bufs.size() ) { + this->commit_buf(); + } + if( _sequence ) { + this->end_sequence(); + } + } + inline void end_writing() { + this->flush(); + _oring.close(); + } + BFdatacapture_status recv(); +}; diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 30b5303f4..392e09960 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -27,6 +27,7 @@ */ #include "assert.hpp" +#include #include #include #include @@ -35,7 +36,8 @@ using bifrost::ring::RingWriter; using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" -#include "packet_formats.h" +#include "formats/formats.hpp" +#include "data_capture.hpp" #include // For ntohs #include // For recvfrom @@ -52,187 +54,34 @@ using bifrost::ring::WriteSequence; #include #include -#ifndef BF_HWLOC_ENABLED -#define BF_HWLOC_ENABLED 0 -//#define BF_HWLOC_ENABLED 1 -#endif - -template -inline T atomic_add_and_fetch(T* dst, T val) { - return __sync_add_and_fetch(dst, val); // GCC builtin -} -template -inline T atomic_fetch_and_add(T* dst, T val) { - return __sync_fetch_and_add(dst, val); // GCC builtin -} - -// Wrap-safe comparisons -inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } -inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } - -template -class AlignedBuffer { - enum { DEFAULT_ALIGNMENT = 4096 }; - T* _buf; - size_t _size; - size_t _alignment; - void alloc() { - int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); - if( err ) { - throw std::runtime_error("Allocation failed"); - } - } - void copy(T const* srcbuf, size_t n) { - ::memcpy(_buf, srcbuf, n*sizeof(T)); - } - void free() { - if( _buf ) { - ::free(_buf); - _buf = 0; - _size = 0; - } - } -public: - //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) - // : _buf(0), _size(0), _alignment(alignment) {} - AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) - : _buf(0), _size(size), _alignment(alignment) { - this->alloc(); - } - AlignedBuffer(AlignedBuffer const& other) - : _buf(0), _size(other._size), _alignment(other._alignment) { - this->alloc(); - this->copy(other._buf, other._size); - } - AlignedBuffer& operator=(AlignedBuffer const& other) { - if( &other != this ) { - this->free(); - _size = other.size; - _alignment = other.alignment; - this->alloc(); - this->copy(other._buf, other._size); - } - return *this; - } - ~AlignedBuffer() { - this->free(); - } - inline void swap(AlignedBuffer & other) { - std::swap(_buf, other._buf); - std::swap(_size, other._size); - std::swap(_alignment, other._alignment); - } - inline void resize(size_t n) { - if( n <= _size ) { - _size = n; - } else { - AlignedBuffer tmp(n, _alignment); - tmp.copy(&_buf[0], _size); - tmp.swap(*this); - } - } - inline size_t size() const { return _size; } - inline T & operator[](size_t i) { return _buf[i]; } - inline T const& operator[](size_t i) const { return _buf[i]; } -}; - -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; - } -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { - #if BF_HWLOC_ENABLED - HardwareLocality _hwloc; - #endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); - #if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); - #endif - } -}; - -class DiskFrameReader { +class DiskPacketReader : public DataCaptureMethod { int _fd; AlignedBuffer _buf; public: - DiskFrameReader(int fd, size_t frm_size_max=9000) - : _fd(fd), _buf(frm_size_max) - {} - inline int read_frame(uint8_t** frm_ptr, int flags=0) { - *frm_ptr = &_buf[0]; + DiskPacketReader(int fd, size_t pkt_size_max=9000) + : DataCaptureMethod(fd, pkt_size_max), _fd(fd), _buf(pkt_size_max) {} + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); } }; -struct FrameDesc { - uint64_t seq; - int nsrc; - int src; - int nchan; - int chan0; - uint32_t sync; - uint64_t time_tag; - int tuning; - int decimation; - int valid_mode; - int payload_size; - const uint8_t* payload_ptr; -}; -struct FrameStats { - size_t ninvalid; - size_t ninvalid_bytes; - size_t nlate; - size_t nlate_bytes; - size_t nvalid; - size_t nvalid_bytes; -}; - -class DiskReaderThread : public BoundThread { - DiskFrameReader _disk; - FrameStats _stats; - std::vector _src_stats; - bool _have_frm; - FrameDesc _frm; +class DiskReaderThread : public DataCaptureThread { + DiskPacketReader _disk; + PacketStats _stats; + std::vector _src_stats; + bool _have_pkt; + PacketDesc _pkt; public: enum { - READ_SUCCESS = 1 << 0, - READ_TIMEOUT = 1 << 1, - READ_INTERRUPTED = 1 << 2, - READ_ERROR = 1 << 3 + CAPTURE_SUCCESS = 1 << 0, + CAPTURE_TIMEOUT = 1 << 1, + CAPTURE_INTERRUPTED = 1 << 2, + CAPTURE_ERROR = 1 << 3 }; - DiskReaderThread(int fd, int nsrc, int core=0, size_t frm_size_max=9000) - : BoundThread(core), _disk(fd, frm_size_max), _src_stats(nsrc), - _have_frm(false) { + DiskReaderThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) + : DataCaptureThread(fd, nsrc, core, pkt_size_max), _disk(fd, pkt_size_max), _src_stats(nsrc), + _have_pkt(false) { this->reset_stats(); } // Reads, decodes and unpacks frames into the provided buffers @@ -240,765 +89,269 @@ class DiskReaderThread : public BoundThread { // beyond the end of the provided buffers. This frame is // saved, accessible via get_last_frame(), and will be // processed on the next call to run() if possible. - template + template int run(uint64_t seq_beg, uint64_t nseq_per_obuf, int nbuf, uint8_t* obufs[], size_t* ngood_bytes[], size_t* src_ngood_bytes[], - FrameDecoder* decode, - FrameProcessor* process) { + PacketDecoder* decode, + PacketProcessor* process) { uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; size_t local_ngood_bytes[2] = {0, 0}; int ret; while( true ) { - if( !_have_frm ) { - uint8_t* frm_ptr; - int frm_size = _disk.read_frame(&frm_ptr); - if( frm_size <= 0 ) { + if( !_have_pkt ) { + uint8_t* pkt_ptr; + int pkt_size = _disk.recv_packet(&pkt_ptr); + if( pkt_size <= 0 ) { if( errno == EAGAIN || errno == EWOULDBLOCK ) { - ret = READ_TIMEOUT; // Timed out + ret = CAPTURE_TIMEOUT; // Timed out } else if( errno == EINTR ) { - ret = READ_INTERRUPTED; // Interrupted by signal + ret = CAPTURE_INTERRUPTED; // Interrupted by signal } else { - ret = READ_ERROR; // Socket error + ret = CAPTURE_ERROR; // Socket error } break; } - if( !(*decode)(frm_ptr, frm_size, &_frm) ) { + if( !(*decode)(pkt_ptr, pkt_size, &_pkt) ) { ++_stats.ninvalid; - _stats.ninvalid_bytes += frm_size; + _stats.ninvalid_bytes += pkt_size; continue; } - _have_frm = true; + _have_pkt = true; } - if( greater_equal(_frm.seq, seq_end) ) { + if( greater_equal(_pkt.seq, seq_end) ) { // Reached the end of this processing gulp, so leave this // frame unprocessed and return. - ret = READ_SUCCESS; + ret = CAPTURE_SUCCESS; break; } - _have_frm = false; - if( less_than(_frm.seq, seq_beg) ) { + _have_pkt = false; + if( less_than(_pkt.seq, seq_beg) ) { ++_stats.nlate; - _stats.nlate_bytes += _frm.payload_size; - ++_src_stats[_frm.src].nlate; - _src_stats[_frm.src].nlate_bytes += _frm.payload_size; + _stats.nlate_bytes += _pkt.payload_size; + ++_src_stats[_pkt.src].nlate; + _src_stats[_pkt.src].nlate_bytes += _pkt.payload_size; continue; } ++_stats.nvalid; - _stats.nvalid_bytes += _frm.payload_size; - ++_src_stats[_frm.src].nvalid; - _src_stats[_frm.src].nvalid_bytes += _frm.payload_size; + _stats.nvalid_bytes += _pkt.payload_size; + ++_src_stats[_pkt.src].nvalid; + _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; // HACK TODO: src_ngood_bytes should be accumulated locally and // then atomically updated, like ngood_bytes. The // current way is not thread-safe. - (*process)(&_frm, seq_beg, nseq_per_obuf, nbuf, obufs, + (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, local_ngood_bytes, /*local_*/src_ngood_bytes); } if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } return ret; } - inline const FrameDesc* get_last_frame() const { - return _have_frm ? &_frm : NULL; - } - inline void reset_last_frame() { - _have_frm = false; - } - inline const FrameStats* get_stats() const { return &_stats; } - inline const FrameStats* get_stats(int src) const { return &_src_stats[src]; } - inline void reset_stats() { - ::memset(&_stats, 0, sizeof(_stats)); - ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(FrameStats)); - } }; -class DiskDecoder { -protected: - int _nsrc; - int _src0; -public: - DiskDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} - virtual inline bool operator()(const uint8_t* frm_ptr, - int frm_size, - FrameDesc* frm) const { - return false; - } -}; +typedef int (*BFdiskreader_tbn_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); -class DRXDecoder:DiskDecoder { - inline bool valid_frame(const FrameDesc* frm) const { - return (frm->sync == 0x5CDEC0DE && - frm->src >= 0 && - frm->src < _nsrc && - frm->time_tag >= 0 && - frm->tuning >= 0); - } -public: - DRXDecoder(int nsrc, int src0) : DiskDecoder(nsrc, src0) {} - inline bool operator()(const uint8_t* frm_ptr, - int frm_size, - FrameDesc* frm) const { - if( frm_size < (int)sizeof(drx_hdr_type) ) { - return false; +class BFdiskreader_tbn_impl : public BFdatacapture_impl { + DiskReaderThread _capture; + TBNDecoder _decoder; + TBNProcessor _processor; + ProcLog _type_log; + ProcLog _chan_log; + + BFdiskreader_tbn_sequence_callback _sequence_callback; + + BFoffset _time_tag; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; } - const drx_hdr_type* frm_hdr = (drx_hdr_type*)frm_ptr; - const uint8_t* frm_pld = frm_ptr + sizeof(drx_hdr_type); - int pld_size = frm_size - sizeof(drx_hdr_type); - int frm_id = frm_hdr->frame_count_word & 0xFF; - //uint8_t frm_beam = (frm_id & 0x7) - 1; - int frm_tune = ((frm_id >> 3) & 0x7) - 1; - int frm_pol = ((frm_id >> 7) & 0x1); - frm_id = (frm_tune << 1) | frm_pol; - frm->sync = frm_hdr->sync_word; - frm->time_tag = be64toh(frm_hdr->time_tag) - be16toh(frm_hdr->time_offset); - frm->seq = frm->time_tag / be16toh(frm_hdr->decimation) / 4096; - //frm->nsrc = frm_hdr->nroach; - frm->nsrc = _nsrc; - frm->src = frm_id - _src0; - frm->tuning = be32toh(frm_hdr->tuning_word); - frm->decimation = be16toh(frm_hdr->decimation); - frm->valid_mode = 1; - frm->payload_size = pld_size; - frm->payload_ptr = frm_pld; -// cout << frm_id << frm->src << "valid? " << this->valid_frame(frm) << endl; - return this->valid_frame(frm); - } -}; - -class TBNDecoder:DiskDecoder { - inline bool valid_frame(const FrameDesc* frm) const { - return (frm->sync == 0x5CDEC0DE && - frm->src >= 0 && - frm->src < _nsrc && - frm->time_tag >= 0 && - frm->tuning >= 0 && - frm->valid_mode == 1); - } -public: - TBNDecoder(int nsrc, int src0) : DiskDecoder(nsrc, src0) {} - inline bool operator()(const uint8_t* frm_ptr, - int frm_size, - FrameDesc* frm) const { - if( frm_size < (int)sizeof(tbn_hdr_type) ) { - return false; + else { + //cout << "No latest packet" << endl; } - const tbn_hdr_type* frm_hdr = (tbn_hdr_type*)frm_ptr; - const uint8_t* frm_pld = frm_ptr + sizeof(tbn_hdr_type); - int pld_size = frm_size - sizeof(tbn_hdr_type); - frm->sync = frm_hdr->sync_word; - frm->time_tag = be64toh(frm_hdr->time_tag); - frm->seq = frm->time_tag / 1960 / 512; - //frm->nsrc = frm_hdr->nroach; - frm->nsrc = _nsrc; - frm->src = (be16toh(frm_hdr->tbn_id) & 1023) - 1 - _src0; - frm->tuning = be32toh(frm_hdr->tuning_word); - frm->decimation = 1960; - frm->valid_mode = (be16toh(frm_hdr->tbn_id) >> 7) & 1; - frm->payload_size = pld_size; - frm->payload_ptr = frm_pld; - return this->valid_frame(frm); } -}; - -class DiskProcessor { -public: - virtual inline void operator()(const FrameDesc* frm, - uint64_t seq0, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t ngood_bytes[], - size_t* src_ngood_bytes[]) {} - virtual inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nseq) {} -}; - -class DRXProcessor:DiskProcessor { -public: - inline void operator()(const FrameDesc* frm, - uint64_t seq0, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t ngood_bytes[], - size_t* src_ngood_bytes[]) { - int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + - (frm->seq - seq0 >= 2*nseq_per_obuf)); - size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; - size_t nbyte = frm->payload_size; - ngood_bytes[obuf_idx] += nbyte; - src_ngood_bytes[obuf_idx][frm->src] += nbyte; - int payload_size = frm->payload_size; - - size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; - - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) - uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; - uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - - int samp = 0; - for( ; samp<4096; ++samp ) { // HACK TESTING - out[samp*frm->nsrc + frm->src] = in[samp]; - } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->tuning != _chan0); } - inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; - for( int t=0; ttime_tag; + _chan0 = pkt->tuning; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + } public: - inline void operator()(const FrameDesc* frm, - uint64_t seq0, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t ngood_bytes[], - size_t* src_ngood_bytes[]) { - int obuf_idx = ((frm->seq - seq0 >= 1*nseq_per_obuf) + - (frm->seq - seq0 >= 2*nseq_per_obuf)); - size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; - size_t nbyte = frm->payload_size; - ngood_bytes[obuf_idx] += nbyte; - src_ngood_bytes[obuf_idx][frm->src] += nbyte; - int payload_size = frm->payload_size; - - size_t obuf_offset = (frm->seq-obuf_seq0)*frm->nsrc*payload_size; - - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) - uint8_t const* __restrict__ in = (uint8_t const*)frm->payload_ptr; - uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - - int samp = 0; - for( ; samp<512; ++samp ) { // HACK TESTING - out[samp*frm->nsrc*2 + frm->src*2 + 0] = in[2*samp+0]; - out[samp*frm->nsrc*2 + frm->src*2 + 1] = in[2*samp+1]; - } - } - inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; - for( int t=0; tbufsize(max_payload_size); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "tbn"); } }; -inline uint64_t round_up(uint64_t val, uint64_t mult) { - return (val == 0 ? - 0 : - ((val-1)/mult+1)*mult); -} -inline uint64_t round_nearest(uint64_t val, uint64_t mult) { - return (2*val/mult+1)/2*mult; -} - -class BFdiskreader_impl { -protected: - DiskProcessor _processor; - ProcLog _type_log; - ProcLog _bind_log; - ProcLog _out_log; - ProcLog _size_log; - ProcLog _chan_log; - ProcLog _stat_log; - ProcLog _perf_log; - pid_t _pid; +typedef int (*BFdiskreader_drx_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); + +class BFdiskreader_drx_impl : public BFdatacapture_impl { + DiskReaderThread _capture; + DRXDecoder _decoder; + DRXProcessor _processor; + ProcLog _type_log; + ProcLog _chan_log; - std::chrono::high_resolution_clock::time_point _t0; - std::chrono::high_resolution_clock::time_point _t1; - std::chrono::high_resolution_clock::time_point _t2; - std::chrono::duration _process_time; - std::chrono::duration _reserve_time; + BFdiskreader_drx_sequence_callback _sequence_callback; - int _nsrc; - int _nseq_per_buf; - int _slot_nframe; - BFoffset _seq; BFoffset _time_tag; - int _chan0; int _chan1; - int _payload_size; - bool _active; uint8_t _tstate; - BFdiskreader_sequence_callback _sequence_callback; - - RingWrapper _ring; - RingWriter _oring; - std::queue > _bufs; - std::queue _buf_ngood_bytes; - std::queue > _buf_src_ngood_bytes; - std::shared_ptr _sequence; - size_t _ngood_bytes; - size_t _nmissing_bytes; - inline size_t bufsize(int payload_size=-1) { - if( payload_size == -1 ) { - payload_size = _payload_size; + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; } - return _nseq_per_buf * _nsrc * payload_size; - } - inline void reserve_buf() { - _buf_ngood_bytes.push(0); - _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); - size_t size = this->bufsize(); - // TODO: Can make this simpler? - _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); - } - inline void commit_buf() { - size_t expected_bytes = _bufs.front()->size(); - for( int src=0; src<_nsrc; ++src ) { - // TODO: This assumes all sources contribute equally; should really - // allow non-uniform partitioning. - size_t src_expected_bytes = expected_bytes / _nsrc; - size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; - size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; - // Detect >50% missing data from this source - if( src_nmissing_bytes > src_ngood_bytes ) { - // Zero-out this source's contribution to the buffer - uint8_t* data = (uint8_t*)_bufs.front()->data(); - _processor.blank_out_source(data, src, _nsrc, - _nseq_per_buf); + if( pkt->src / 2 == 0 ) { + if( pkt->tuning != _chan0 ) { + _tstate |= 1; + _chan0 = pkt->tuning; + } + } else { + if( pkt->tuning != _chan1 ) { + _tstate |= 2; + _chan1 = pkt->tuning; } } - _buf_src_ngood_bytes.pop(); - - _ngood_bytes += _buf_ngood_bytes.front(); - _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); - _buf_ngood_bytes.pop(); - - _bufs.front()->commit(); - _bufs.pop(); - _seq += _nseq_per_buf; } - inline void begin_sequence() { - BFoffset seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - const void* hdr; - size_t hdr_size; - BFoffset time_tag = _time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(seq0, - _time_tag, + inline bool has_sequence_changed(const PacketDesc* pkt) { + return ( (_tstate == 3 && _nsrc == 4) + || (_tstate != 0 && _nsrc == 2) ); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, _chan0, - _chan1, + _nchan, _nsrc, - &hdr, - &hdr_size); + time_tag, + hdr, + hdr_size); if( status != 0 ) { - // TODO: What to do here? Needed? + // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); } } else { // Simple default for easy testing - time_tag = _time_tag; - hdr = NULL; - hdr_size = 0; + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; } - const char* name = ""; - int nringlet = 1; - _sequence.reset(new WriteSequence(_oring, name, time_tag, - hdr_size, hdr, nringlet)); - } - inline void end_sequence() { - _sequence.reset(); // Note: This is releasing the shared_ptr - } + + _time_tag = pkt->time_tag; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + } public: - inline BFdiskreader_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_nframe, - int slot_nframe, - BFdiskreader_sequence_callback sequence_callback, - int core) - : _processor(), - _type_log("disk_reader/type"), - _bind_log("disk_reader/bind"), - _out_log("disk_reader/out"), - _size_log("disk_reader/sizes"), - _chan_log("disk_reader/chans"), - _stat_log("disk_reader/stats"), - _perf_log("disk_reader/perf"), - _nsrc(nsrc), _nseq_per_buf(buffer_nframe), _slot_nframe(slot_nframe), - _seq(0), _time_tag(0), _chan0(), _active(false), _tstate(0), - _sequence_callback(sequence_callback), - _ring(ring), _oring(_ring), - // TODO: Add reset method for stats - _ngood_bytes(0), _nmissing_bytes(0) {} - inline void flush() { - while( _bufs.size() ) { - this->commit_buf(); - } - if( _sequence ) { - this->end_sequence(); - } - } - inline void end_writing() { - this->flush(); - _oring.close(); - } - virtual BFdiskreader_status read() { - return BF_READ_NO_DATA; - } -}; - -class BFdrxreader_impl:public BFdiskreader_impl { - DiskReaderThread _reader; - DRXDecoder _decoder; - DRXProcessor _processor; -public: - inline BFdrxreader_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_nframe, - int slot_nframe, - BFdiskreader_sequence_callback sequence_callback, - int core) - : BFdiskreader_impl(fd, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core), - _reader(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor() { - size_t contig_span = this->bufsize(DRX_FRAME_SIZE - sizeof(drx_hdr_type)); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "drx"); - _bind_log.update("ncore : %i\n" - "core0 : %i\n", - 1, core); - _out_log.update("nring : %i\n" - "ring0 : %s\n", - 1, _ring.name()); - _size_log.update("nsrc : %i\n" - "nseq_per_buf : %i\n" - "slot_nframe : %i\n", - _nsrc, _nseq_per_buf, _slot_nframe); - } - BFdiskreader_status read() { - _t0 = std::chrono::high_resolution_clock::now(); - - uint8_t* buf_ptrs[2]; - // Minor HACK to access the buffers in a 2-element queue - buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; - buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; - - size_t* ngood_bytes_ptrs[2]; - ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; - ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; - - size_t* src_ngood_bytes_ptrs[2]; - src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; - src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - - int state = _reader.run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - &_decoder, - &_processor); - if( state & DiskReaderThread::READ_ERROR ) { - return BF_READ_ERROR; - } else if( state & DiskReaderThread::READ_INTERRUPTED ) { - return BF_READ_INTERRUPTED; - } - const FrameStats* stats = _reader.get_stats(); - _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" - << "nmissing_bytes : " << _nmissing_bytes << "\n" - << "ninvalid : " << stats->ninvalid << "\n" - << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" - << "nlate : " << stats->nlate << "\n" - << "nlate_bytes : " << stats->nlate_bytes << "\n" - << "nvalid : " << stats->nvalid << "\n" - << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; - - _t1 = std::chrono::high_resolution_clock::now(); - - BFdiskreader_status ret; - bool was_active = _active; - _active = state & DiskReaderThread::READ_SUCCESS; - if( _active ) { - const FrameDesc* frm = _reader.get_last_frame(); - if( frm ) { - //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; - } - else { - //cout << "No latest frame" << endl; - } - - if( frm->src / 2 == 0 ) { - if( frm->tuning != _chan0 ) { - _tstate |= 1; - _chan0 = frm->tuning; - } - } else { - if( frm->tuning != _chan1 ) { - _tstate |= 2; - _chan1 = frm->tuning; - } - } - //cout << "State is now " << int(_tstate) << " with " << _chan0 << " and " << _chan1 << " with " << _seq << endl; - //cout << " " << frm->time_tag << endl; - - if( !was_active ) { - if( (_tstate == 3 && _nsrc == 4) || - (_tstate != 0 && _nsrc == 2) ) { - _seq = round_nearest(frm->seq, _nseq_per_buf); - _time_tag = frm->time_tag; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "chan1 : " << _chan1 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->begin_sequence(); - ret = BF_READ_STARTED; - _tstate = 0; - } else { - ret = BF_READ_NO_DATA; - _active = false; - _reader.reset_last_frame(); - } - } else { - //cout << "Continuing data, seq = " << seq << endl; - if( (_tstate == 3 && _nsrc == 4) || - (_tstate != 0 && _nsrc == 2) ) { - _time_tag = frm->time_tag; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "chan1 : " << _chan1 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->end_sequence(); - this->begin_sequence(); - ret = BF_READ_CHANGED; - _tstate = 0; - } else { - ret = BF_READ_CONTINUED; - } - } - - if( ret != BF_READ_NO_DATA ) { - if( _bufs.size() == 2 ) { - this->commit_buf(); - } - this->reserve_buf(); - } - } else { - - if( was_active ) { - this->flush(); - ret = BF_READ_ENDED; - } else { - ret = BF_READ_NO_DATA; - } - } - - _t2 = std::chrono::high_resolution_clock::now(); - _process_time = std::chrono::duration_cast>(_t1-_t0); - _reserve_time = std::chrono::duration_cast>(_t2-_t1); - _perf_log.update() << "acquire_time : " << -1.0 << "\n" - << "process_time : " << _process_time.count() << "\n" - << "reserve_time : " << _reserve_time.count() << "\n"; - - return ret; - } -}; - -class BFtbnreader_impl:public BFdiskreader_impl { - DiskReaderThread _reader; - TBNDecoder _decoder; - TBNProcessor _processor; -public: - inline BFtbnreader_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_nframe, - int slot_nframe, - BFdiskreader_sequence_callback sequence_callback, - int core) - : BFdiskreader_impl(fd, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core), - _reader(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor() { - size_t contig_span = this->bufsize(TBN_FRAME_SIZE - sizeof(tbn_hdr_type)); + inline BFdiskreader_drx_impl(int fd, + BFring ring, + int nsrc, + int src0, + int max_payload_size, + int buffer_ntime, + int slot_ntime, + BFdiskreader_tbn_sequence_callback sequence_callback, + int core) + : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + _type_log("disk_reader/type"), + _chan_log("disk_reader/chans"), + _sequence_callback(sequence_callback), + _chan1(), _tstate(0) { + size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; size_t nringlet_max = 1; _ring.resize(contig_span, total_span, nringlet_max); _type_log.update("type : %s", "tbn"); - _bind_log.update("ncore : %i\n" - "core0 : %i\n", - 1, core); - _out_log.update("nring : %i\n" - "ring0 : %s\n", - 1, _ring.name()); - _size_log.update("nsrc : %i\n" - "nseq_per_buf : %i\n" - "slot_nframe : %i\n", - _nsrc, _nseq_per_buf, _slot_nframe); - } - BFdiskreader_status read() { - _t0 = std::chrono::high_resolution_clock::now(); - - uint8_t* buf_ptrs[2]; - // Minor HACK to access the buffers in a 2-element queue - buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; - buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; - - size_t* ngood_bytes_ptrs[2]; - ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; - ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; - - size_t* src_ngood_bytes_ptrs[2]; - src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; - src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - - int state = _reader.run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - &_decoder, - &_processor); - if( state & DiskReaderThread::READ_ERROR ) { - return BF_READ_ERROR; - } else if( state & DiskReaderThread::READ_INTERRUPTED ) { - return BF_READ_INTERRUPTED; - } - const FrameStats* stats = _reader.get_stats(); - _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" - << "nmissing_bytes : " << _nmissing_bytes << "\n" - << "ninvalid : " << stats->ninvalid << "\n" - << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" - << "nlate : " << stats->nlate << "\n" - << "nlate_bytes : " << stats->nlate_bytes << "\n" - << "nvalid : " << stats->nvalid << "\n" - << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; - - _t1 = std::chrono::high_resolution_clock::now(); - - BFdiskreader_status ret; - bool was_active = _active; - _active = state & DiskReaderThread::READ_SUCCESS; - if( _active ) { - const FrameDesc* frm = _reader.get_last_frame(); - if( frm ) { - //cout << "Latest nchan, chan0 = " << frm->nchan << ", " << frm->chan0 << endl; - } - else { - //cout << "No latest frame" << endl; - } - if( !was_active ) { - _seq = round_nearest(frm->seq, _nseq_per_buf); - _time_tag = frm->time_tag; - _chan0 = frm->tuning; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->begin_sequence(); - ret = BF_READ_STARTED; - } else { - //cout << "Continuing data, seq = " << seq << endl; - if( frm->tuning != _chan0 ) { - _time_tag = frm->time_tag; - _chan0 = frm->tuning; - _payload_size = frm->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - this->end_sequence(); - this->begin_sequence(); - ret = BF_READ_CHANGED; - } else { - ret = BF_READ_CONTINUED; - } - } - if( _bufs.size() == 2 ) { - this->commit_buf(); - } - this->reserve_buf(); - } else { - - if( was_active ) { - this->flush(); - ret = BF_READ_ENDED; - } else { - ret = BF_READ_NO_DATA; - } - } - - _t2 = std::chrono::high_resolution_clock::now(); - _process_time = std::chrono::duration_cast>(_t1-_t0); - _reserve_time = std::chrono::duration_cast>(_t2-_t1); - _perf_log.update() << "acquire_time : " << -1.0 << "\n" - << "process_time : " << _process_time.count() << "\n" - << "reserve_time : " << _reserve_time.count() << "\n"; - - return ret; } }; -BFstatus bfDiskReaderCreate(BFdiskreader* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_nframe, - BFsize slot_nframe, - BFdiskreader_sequence_callback sequence_callback, - int core) { +BFstatus bfDiskReaderCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdiskreader_sequence_callback sequence_callback, + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdrxreader_impl(fd, ring, nsrc, src0, - buffer_nframe, slot_nframe, - sequence_callback, core), + if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_tbn_impl(fd, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, + sequence_callback, core), *obj = 0); - } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFtbnreader_impl(fd, ring, nsrc, src0, - buffer_nframe, slot_nframe, - sequence_callback, core), + } else if( format == std::string("drx") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_drx_impl(fd, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, + sequence_callback, core), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } } -BFstatus bfDiskReaderDestroy(BFdiskreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - delete obj; - return BF_STATUS_SUCCESS; -} -BFstatus bfDiskReaderRead(BFdiskreader obj, BFdiskreader_status* result) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN_ELSE(*result = obj->read(), - *result = BF_READ_ERROR); -} -BFstatus bfDiskReaderFlush(BFdiskreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->flush()); -} -BFstatus bfDiskReaderEnd(BFdiskreader obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->end_writing()); -} diff --git a/src/formats/base.hpp b/src/formats/base.hpp new file mode 100644 index 000000000..16f700066 --- /dev/null +++ b/src/formats/base.hpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include // For ntohs + +#define BF_UNPACK_FACTOR 1 + +#define JUMBO_FRAME_SIZE 9000 + +struct __attribute__((aligned(32))) aligned256_type { + uint8_t data[32]; +}; +struct __attribute__((aligned(64))) aligned512_type { + uint8_t data[64]; +}; + + +struct PacketDesc { + uint64_t seq; + int nsrc; + int src; + int nchan; + int chan0; + uint32_t sync; + uint64_t time_tag; + int tuning; + int decimation; + int valid_mode; + int payload_size; + const uint8_t* payload_ptr; +}; + + +class PacketDecoder { +protected: + int _nsrc; + int _src0; + virtual inline bool valid_packet(const PacketDesc* pkt) const { + return false; + } +public: + PacketDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} + virtual inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + return false; + } +}; + + +class PacketProcessor { +public: + virtual inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) {} + virtual inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) {} +}; diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp new file mode 100644 index 000000000..d76fcf2c4 --- /dev/null +++ b/src/formats/chips.hpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +//#include // SSE + +#pragma pack(1) +struct chips_hdr_type { + uint8_t roach; // Note: 1-based + uint8_t gbe; // (AKA tuning) + uint8_t nchan; // 109 + uint8_t nsubband; // 11 + uint8_t subband; // 0-11 + uint8_t nroach; // 16 + // Note: Big endian + uint16_t chan0; // First chan in packet + uint64_t seq; // Note: 1-based +}; + +class CHIPSDecoder : public PacketDecoder { + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->seq >= 0 && + pkt->src >= 0 && pkt->src < _nsrc && + pkt->chan0 >= 0); + } +public: + CHIPSDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(chips_hdr_type) ) { + return false; + } + const chips_hdr_type* pkt_hdr = (chips_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(chips_hdr_type); + int pld_size = pkt_size - sizeof(chips_hdr_type); + pkt->seq = be64toh(pkt_hdr->seq) - 1; + //pkt->nsrc = pkt_hdr->nroach; + pkt->nsrc = _nsrc; + pkt->src = (pkt_hdr->roach - 1) - _src0; + pkt->nchan = pkt_hdr->nchan; + pkt->chan0 = ntohs(pkt_hdr->chan0); + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + +class CHIPSProcessor : public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + enum { + PKT_NINPUT = 32, + PKT_NBIT = 4 + }; + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + // **CHANGED RECENTLY + int payload_size = pkt->payload_size;//pkt->nchan*(PKT_NINPUT*2*PKT_NBIT/8); + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef aligned256_type itype; + typedef aligned256_type otype; + + obuf_offset *= BF_UNPACK_FACTOR; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + int chan = 0; + //cout << pkt->src << ", " << pkt->nsrc << endl; + //cout << pkt->nchan << endl; + /* + // HACK TESTING disabled + for( ; channchan/4*4; chan+=4 ) { + __m128i tmp0 = ((__m128i*)&in[chan])[0]; + __m128i tmp1 = ((__m128i*)&in[chan])[1]; + __m128i tmp2 = ((__m128i*)&in[chan+1])[0]; + __m128i tmp3 = ((__m128i*)&in[chan+1])[1]; + __m128i tmp4 = ((__m128i*)&in[chan+2])[0]; + __m128i tmp5 = ((__m128i*)&in[chan+2])[1]; + __m128i tmp6 = ((__m128i*)&in[chan+3])[0]; + __m128i tmp7 = ((__m128i*)&in[chan+3])[1]; + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[0], tmp2); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[1], tmp3); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[0], tmp4); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[1], tmp5); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[0], tmp6); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[1], tmp7); + } + */ + //for( ; channchan; ++chan ) { + /* + for( ; chan<10; ++chan ) { // HACK TESTING + __m128i tmp0 = ((__m128i*)&in[chan])[0]; + __m128i tmp1 = ((__m128i*)&in[chan])[1]; + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); + _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); + } + */ + //if( pkt->src < 8 ) { // HACK TESTING + //for( ; chan<32; ++chan ) { // HACK TESTING + for( ; channchan; ++chan ) { // HACK TESTING + out[pkt->src + pkt->nsrc*chan] = in[chan]; + //::memset( + } + //} + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + typedef aligned256_type otype; + otype* __restrict__ aligned_data = (otype*)data; + for( int t=0; tsync == 0x5CDEC0DE && + pkt->src >= 0 && + pkt->src < _nsrc && + pkt->time_tag >= 0 && + pkt->tuning >= 0); + } +public: + DRXDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(drx_hdr_type) ) { + return false; + } + const drx_hdr_type* pkt_hdr = (drx_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(drx_hdr_type); + int pld_size = pkt_size - sizeof(drx_hdr_type); + int pkt_id = pkt_hdr->frame_count_word & 0xFF; + //uint8_t pkt_beam = (pkt_id & 0x7) - 1; + int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; + int pkt_pol = ((pkt_id >> 7) & 0x1); + pkt_id = (pkt_tune << 1) | pkt_pol; + pkt->sync = pkt_hdr->sync_word; + pkt->time_tag = be64toh(pkt_hdr->time_tag) - be16toh(pkt_hdr->time_offset); + pkt->seq = pkt->time_tag / be16toh(pkt_hdr->decimation) / 4096; + //pkt->nsrc = pkt_hdr->nroach; + pkt->nsrc = _nsrc; + pkt->src = pkt_id - _src0; + pkt->tuning = be32toh(pkt_hdr->tuning_word); + pkt->decimation = be16toh(pkt_hdr->decimation); + pkt->valid_mode = 1; + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + // cout << pkt_id << pkt->src << "valid? " << this->valid_packet(pkt) << endl; + return this->valid_packet(pkt); + } +}; + + +class DRXProcessor : public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; + uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + int samp = 0; + for( ; samp<4096; ++samp ) { // HACK TESTING + out[samp*pkt->nsrc + pkt->src] = in[samp]; + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + uint8_t* __restrict__ aligned_data = (uint8_t*)data; + for( int t=0; tsync == 0x5CDEC0DE && + pkt->src >= 0 && + pkt->src < _nsrc && + pkt->time_tag >= 0 && + pkt->tuning >= 0 && + pkt->valid_mode == 1); + } +public: + TBNDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(tbn_hdr_type) ) { + return false; + } + const tbn_hdr_type* pkt_hdr = (tbn_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(tbn_hdr_type); + int pld_size = pkt_size - sizeof(tbn_hdr_type); + pkt->sync = pkt_hdr->sync_word; + pkt->time_tag = be64toh(pkt_hdr->time_tag); + pkt->seq = pkt->time_tag / 1960 / 512; + //pkt->nsrc = pkt_hdr->nroach; + pkt->nsrc = _nsrc; + pkt->src = (be16toh(pkt_hdr->tbn_id) & 1023) - 1 - _src0; + pkt->tuning = be32toh(pkt_hdr->tuning_word); + pkt->decimation = 1960; + pkt->valid_mode = (be16toh(pkt_hdr->tbn_id) >> 7) & 1; + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + +class TBNProcessor : public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; + uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + int samp = 0; + for( ; samp<512; ++samp ) { // HACK TESTING + out[samp*pkt->nsrc*2 + pkt->src*2 + 0] = in[2*samp+0]; + out[samp*pkt->nsrc*2 + pkt->src*2 + 1] = in[2*samp+1]; + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + uint8_t* __restrict__ aligned_data = (uint8_t*)data; + for( int t=0; t #include #include #include @@ -35,6 +36,8 @@ using bifrost::ring::RingWriter; using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" +#include "formats/formats.hpp" +#include "data_capture.hpp" #include // For ntohs #include // For recvfrom @@ -51,38 +54,12 @@ using bifrost::ring::WriteSequence; #include #include -//#include // SSE - // TODO: The VMA API is returning unaligned buffers, which prevents use of SSE #ifndef BF_VMA_ENABLED #define BF_VMA_ENABLED 0 //#define BF_VMA_ENABLED 1 #endif -#ifndef BF_HWLOC_ENABLED -#define BF_HWLOC_ENABLED 0 -//#define BF_HWLOC_ENABLED 1 -#endif - -#define BF_UNPACK_FACTOR 1 - -enum { - JUMBO_FRAME_SIZE = 9000 -}; - -template -inline T atomic_add_and_fetch(T* dst, T val) { - return __sync_add_and_fetch(dst, val); // GCC builtin -} -template -inline T atomic_fetch_and_add(T* dst, T val) { - return __sync_fetch_and_add(dst, val); // GCC builtin -} - -// Wrap-safe comparisons -inline bool greater_equal(uint64_t a, uint64_t b) { return int64_t(a-b) >= 0; } -inline bool less_than( uint64_t a, uint64_t b) { return int64_t(a-b) < 0; } - #if BF_VMA_ENABLED #include class VMAReceiver { @@ -127,118 +104,7 @@ class VMAReceiver { }; #endif // BF_VMA_ENABLED -template -class AlignedBuffer { - enum { DEFAULT_ALIGNMENT = 4096 }; - T* _buf; - size_t _size; - size_t _alignment; - void alloc() { - int err = ::posix_memalign((void**)&_buf, _alignment, _size*sizeof(T)); - if( err ) { - throw std::runtime_error("Allocation failed"); - } - } - void copy(T const* srcbuf, size_t n) { - ::memcpy(_buf, srcbuf, n*sizeof(T)); - } - void free() { - if( _buf ) { - ::free(_buf); - _buf = 0; - _size = 0; - } - } -public: - //explicit AlignedBuffer(size_t alignment=DEFAULT_ALIGNMENT) - // : _buf(0), _size(0), _alignment(alignment) {} - AlignedBuffer(size_t size=0, size_t alignment=DEFAULT_ALIGNMENT) - : _buf(0), _size(size), _alignment(alignment) { - this->alloc(); - } - AlignedBuffer(AlignedBuffer const& other) - : _buf(0), _size(other.size), _alignment(other.alignment) { - this->alloc(); - this->copy(other._buf, other._size); - } - AlignedBuffer& operator=(AlignedBuffer const& other) { - if( &other != this ) { - this->free(); - _size = other.size; - _alignment = other.alignment; - this->alloc(); - this->copy(other._buf, other._size); - } - return *this; - } - ~AlignedBuffer() { - this->free(); - } - inline void swap(AlignedBuffer & other) { - std::swap(_buf, other._buf); - std::swap(_size, other._size); - std::swap(_alignment, other._alignment); - } - inline void resize(size_t n) { - if( n <= _size ) { - _size = n; - } else { - AlignedBuffer tmp(n, _alignment); - tmp.copy(&_buf[0], _size); - tmp.swap(*this); - } - } - inline size_t size() const { return _size; } - inline T & operator[](size_t i) { return _buf[i]; } - inline T const& operator[](size_t i) const { return _buf[i]; } -}; - -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; - } -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { -#if BF_HWLOC_ENABLED - HardwareLocality _hwloc; -#endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); -#if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); -#endif - } -}; - -class UDPPacketReceiver { +class UDPPacketReceiver : public DataCaptureMethod { int _fd; AlignedBuffer _buf; #if BF_VMA_ENABLED @@ -246,7 +112,7 @@ class UDPPacketReceiver { #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : _fd(fd), _buf(pkt_size_max) + : DataCaptureMethod(fd, pkt_size_max), _fd(fd), _buf(pkt_size_max) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -266,25 +132,7 @@ class UDPPacketReceiver { } }; -struct PacketDesc { - uint64_t seq; - int nsrc; - int src; - int nchan; - int chan0; - int payload_size; - const uint8_t* payload_ptr; -}; -struct PacketStats { - size_t ninvalid; - size_t ninvalid_bytes; - size_t nlate; - size_t nlate_bytes; - size_t nvalid; - size_t nvalid_bytes; -}; - -class UDPCaptureThread : public BoundThread { +class UDPCaptureThread : public DataCaptureThread { UDPPacketReceiver _udp; PacketStats _stats; std::vector _src_stats; @@ -298,7 +146,7 @@ class UDPCaptureThread : public BoundThread { CAPTURE_ERROR = 1 << 3 }; UDPCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : BoundThread(core), _udp(fd, pkt_size_max), _src_stats(nsrc), + : DataCaptureThread(fd, nsrc, core, pkt_size_max), _udp(fd, pkt_size_max), _src_stats(nsrc), _have_pkt(false) { this->reset_stats(); } @@ -368,478 +216,297 @@ class UDPCaptureThread : public BoundThread { if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } return ret; } - inline const PacketDesc* get_last_packet() const { - return _have_pkt ? &_pkt : NULL; - } - inline const PacketStats* get_stats() const { return &_stats; } - inline const PacketStats* get_stats(int src) const { return &_src_stats[src]; } - inline void reset_stats() { - ::memset(&_stats, 0, sizeof(_stats)); - ::memset(&_src_stats[0], 0, _src_stats.size()*sizeof(PacketStats)); - } }; -#pragma pack(1) -struct chips_hdr_type { - uint8_t roach; // Note: 1-based - uint8_t gbe; // (AKA tuning) - uint8_t nchan; // 109 - uint8_t nsubband; // 11 - uint8_t subband; // 0-11 - uint8_t nroach; // 16 - // Note: Big endian - uint16_t chan0; // First chan in packet - uint64_t seq; // Note: 1-based -}; +typedef int (*BFudpcapture_chips_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); -class CHIPSDecoder { - // TODO: See if can remove these once firmware supports per-GbE nroach - int _nsrc; - int _src0; - inline bool valid_packet(const PacketDesc* pkt) const { - return (pkt->seq >= 0 && - pkt->src >= 0 && pkt->src < _nsrc && - pkt->chan0 >= 0); - } -public: - CHIPSDecoder(int nsrc, int src0) : _nsrc(nsrc), _src0(src0) {} - inline bool operator()(const uint8_t* pkt_ptr, - int pkt_size, - PacketDesc* pkt) const { - if( pkt_size < (int)sizeof(chips_hdr_type) ) { - return false; - } - const chips_hdr_type* pkt_hdr = (chips_hdr_type*)pkt_ptr; - const uint8_t* pkt_pld = pkt_ptr + sizeof(chips_hdr_type); - int pld_size = pkt_size - sizeof(chips_hdr_type); - pkt->seq = be64toh(pkt_hdr->seq) - 1; - //pkt->nsrc = pkt_hdr->nroach; - pkt->nsrc = _nsrc; - pkt->src = (pkt_hdr->roach - 1) - _src0; - pkt->nchan = pkt_hdr->nchan; - pkt->chan0 = ntohs(pkt_hdr->chan0); - pkt->payload_size = pld_size; - pkt->payload_ptr = pkt_pld; - return this->valid_packet(pkt); - } -}; - -struct __attribute__((aligned(32))) aligned256_type { - uint8_t data[32]; -}; -struct __attribute__((aligned(64))) aligned512_type { - uint8_t data[64]; -}; - -class CHIPSProcessor8bit { -public: - inline void operator()(const PacketDesc* pkt, - uint64_t seq0, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t ngood_bytes[], - size_t* src_ngood_bytes[]) { - enum { - PKT_NINPUT = 32, - PKT_NBIT = 4 - }; - int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + - (pkt->seq - seq0 >= 2*nseq_per_obuf)); - size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; - size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; - ngood_bytes[obuf_idx] += nbyte; - src_ngood_bytes[obuf_idx][pkt->src] += nbyte; - // **CHANGED RECENTLY - int payload_size = pkt->payload_size;//pkt->nchan*(PKT_NINPUT*2*PKT_NBIT/8); - - size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; - typedef aligned256_type itype; - typedef aligned256_type otype; - - obuf_offset *= BF_UNPACK_FACTOR; - - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) - itype const* __restrict__ in = (itype const*)pkt->payload_ptr; - otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; - - int chan = 0; - //cout << pkt->src << ", " << pkt->nsrc << endl; - //cout << pkt->nchan << endl; - /* - // HACK TESTING disabled - for( ; channchan/4*4; chan+=4 ) { - __m128i tmp0 = ((__m128i*)&in[chan])[0]; - __m128i tmp1 = ((__m128i*)&in[chan])[1]; - __m128i tmp2 = ((__m128i*)&in[chan+1])[0]; - __m128i tmp3 = ((__m128i*)&in[chan+1])[1]; - __m128i tmp4 = ((__m128i*)&in[chan+2])[0]; - __m128i tmp5 = ((__m128i*)&in[chan+2])[1]; - __m128i tmp6 = ((__m128i*)&in[chan+3])[0]; - __m128i tmp7 = ((__m128i*)&in[chan+3])[1]; - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[0], tmp2); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[1], tmp3); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[0], tmp4); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[1], tmp5); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[0], tmp6); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[1], tmp7); - } - */ - //for( ; channchan; ++chan ) { - /* - for( ; chan<10; ++chan ) { // HACK TESTING - __m128i tmp0 = ((__m128i*)&in[chan])[0]; - __m128i tmp1 = ((__m128i*)&in[chan])[1]; - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); +class BFudpcapture_chips_impl : public BFdatacapture_impl { + UDPCaptureThread _capture; + CHIPSDecoder _decoder; + CHIPSProcessor _processor; + ProcLog _type_log; + ProcLog _chan_log; + + BFudpcapture_chips_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; } - */ - //if( pkt->src < 8 ) { // HACK TESTING - //for( ; chan<32; ++chan ) { // HACK TESTING - for( ; channchan; ++chan ) { // HACK TESTING - out[pkt->src + pkt->nsrc*chan] = in[chan]; - //::memset( + else { + //cout << "No latest packet" << endl; } - //} } - inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nchan, - int nseq) { - typedef aligned256_type otype; - otype* __restrict__ aligned_data = (otype*)data; - for( int t=0; tchan0 != _chan0) \ + || (pkt->nchan != _nchan); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; } + + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFudpcapture_chips_impl(int fd, + BFring ring, + int nsrc, + int src0, + int max_payload_size, + int buffer_ntime, + int slot_ntime, + BFudpcapture_chips_sequence_callback sequence_callback, + int core) + : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + _type_log("udp_capture/type"), + _chan_log("udp_capture/chans"), + _sequence_callback(sequence_callback) { + size_t contig_span = this->bufsize(max_payload_size); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "chips"); } }; -inline uint64_t round_up(uint64_t val, uint64_t mult) { - return (val == 0 ? - 0 : - ((val-1)/mult+1)*mult); -} -inline uint64_t round_nearest(uint64_t val, uint64_t mult) { - return (2*val/mult+1)/2*mult; -} +typedef int (*BFudpcapture_tbn_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); -class BFudpcapture_impl { - UDPCaptureThread _capture; - CHIPSDecoder _decoder; - CHIPSProcessor8bit _processor; - ProcLog _type_log; - ProcLog _bind_log; - ProcLog _out_log; - ProcLog _size_log; - ProcLog _chan_log; - ProcLog _stat_log; - ProcLog _perf_log; - pid_t _pid; - - std::chrono::high_resolution_clock::time_point _t0; - std::chrono::high_resolution_clock::time_point _t1; - std::chrono::high_resolution_clock::time_point _t2; - std::chrono::duration _process_time; - std::chrono::duration _reserve_time; +class BFudpcapture_tbn_impl : public BFdatacapture_impl { + UDPCaptureThread _capture; + TBNDecoder _decoder; + TBNProcessor _processor; + ProcLog _type_log; + ProcLog _chan_log; - int _nsrc; - int _nseq_per_buf; - int _slot_ntime; - BFoffset _seq; - int _chan0; - int _nchan; - int _payload_size; - bool _active; - BFudpcapture_sequence_callback _sequence_callback; + BFudpcapture_tbn_sequence_callback _sequence_callback; - RingWrapper _ring; - RingWriter _oring; - std::queue > _bufs; - std::queue _buf_ngood_bytes; - std::queue > _buf_src_ngood_bytes; - std::shared_ptr _sequence; - size_t _ngood_bytes; - size_t _nmissing_bytes; + BFoffset _time_tag; - inline size_t bufsize(int payload_size=-1) { - if( payload_size == -1 ) { - payload_size = _payload_size; + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; } - return _nseq_per_buf * _nsrc * payload_size * BF_UNPACK_FACTOR; - } - inline void reserve_buf() { - _buf_ngood_bytes.push(0); - _buf_src_ngood_bytes.push(std::vector(_nsrc, 0)); - size_t size = this->bufsize(); - // TODO: Can make this simpler? - _bufs.push(std::shared_ptr(new bifrost::ring::WriteSpan(_oring, size))); - } - inline void commit_buf() { - size_t expected_bytes = _bufs.front()->size(); - - for( int src=0; src<_nsrc; ++src ) { - // TODO: This assumes all sources contribute equally; should really - // allow non-uniform partitioning. - size_t src_expected_bytes = expected_bytes / _nsrc; - size_t src_ngood_bytes = _buf_src_ngood_bytes.front()[src]; - size_t src_nmissing_bytes = src_expected_bytes - src_ngood_bytes; - // Detect >50% missing data from this source - if( src_nmissing_bytes > src_ngood_bytes ) { - // Zero-out this source's contribution to the buffer - uint8_t* data = (uint8_t*)_bufs.front()->data(); - _processor.blank_out_source(data, src, _nsrc, - _nchan, _nseq_per_buf); - } + else { + //cout << "No latest packet" << endl; } - _buf_src_ngood_bytes.pop(); - - _ngood_bytes += _buf_ngood_bytes.front(); - //_nmissing_bytes += _bufs.front()->size() - _buf_ngood_bytes.front(); - //// HACK TESTING 15/16 correction for missing roach11 - //_nmissing_bytes += _bufs.front()->size()*15/16 - _buf_ngood_bytes.front(); - _nmissing_bytes += expected_bytes - _buf_ngood_bytes.front(); - _buf_ngood_bytes.pop(); - - _bufs.front()->commit(); - _bufs.pop(); - _seq += _nseq_per_buf; } - inline void begin_sequence() { - BFoffset seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - const void* hdr; - size_t hdr_size; - BFoffset time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(seq0, - _chan0, - _nchan, - _nsrc, - &time_tag, - &hdr, - &hdr_size); + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->tuning != _chan0); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); if( status != 0 ) { - // TODO: What to do here? Needed? + // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); } } else { // Simple default for easy testing - time_tag = seq0; - hdr = NULL; - hdr_size = 0; + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; } - const char* name = ""; - int nringlet = 1; - _sequence.reset(new WriteSequence(_oring, name, time_tag, - hdr_size, hdr, nringlet)); - } - inline void end_sequence() { - _sequence.reset(); // Note: This is releasing the shared_ptr - } + + _time_tag = pkt->time_tag; + _chan0 = pkt->tuning; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + } public: - inline BFudpcapture_impl(int fd, - BFring ring, - int nsrc, - int src0, - int max_payload_size, - int buffer_ntime, - int slot_ntime, - BFudpcapture_sequence_callback sequence_callback, - int core) - : _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + inline BFudpcapture_tbn_impl(int fd, + BFring ring, + int nsrc, + int src0, + int max_payload_size, + int buffer_ntime, + int slot_ntime, + BFudpcapture_chips_sequence_callback sequence_callback, + int core) + : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), - _bind_log("udp_capture/bind"), - _out_log("udp_capture/out"), - _size_log("udp_capture/sizes"), _chan_log("udp_capture/chans"), - _stat_log("udp_capture/stats"), - _perf_log("udp_capture/perf"), - _nsrc(nsrc), _nseq_per_buf(buffer_ntime), _slot_ntime(slot_ntime), - _seq(), _chan0(), _nchan(), _active(false), - _sequence_callback(sequence_callback), - _ring(ring), _oring(_ring), - // TODO: Add reset method for stats - _ngood_bytes(0), _nmissing_bytes(0) { + _sequence_callback(sequence_callback) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; size_t nringlet_max = 1; _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "chips"); - _bind_log.update("ncore : %i\n" - "core0 : %i\n", - 1, core); - _out_log.update("nring : %i\n" - "ring0 : %s\n", - 1, _ring.name()); - _size_log.update("nsrc : %i\n" - "nseq_per_buf : %i\n" - "slot_ntime : %i\n", - _nsrc, _nseq_per_buf, _slot_ntime); + _type_log.update("type : %s", "tbn"); } - inline void flush() { - while( _bufs.size() ) { - this->commit_buf(); +}; + +typedef int (*BFudpcapture_drx_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); + +class BFudpcapture_drx_impl : public BFdatacapture_impl { + UDPCaptureThread _capture; + DRXDecoder _decoder; + DRXProcessor _processor; + ProcLog _type_log; + ProcLog _chan_log; + + BFudpcapture_drx_sequence_callback _sequence_callback; + + BFoffset _time_tag; + int _chan1; + uint8_t _tstate; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; } - if( _sequence ) { - this->end_sequence(); + else { + //cout << "No latest packet" << endl; } - } - inline void end_writing() { - this->flush(); - _oring.close(); - } - BFudpcapture_status recv() { - _t0 = std::chrono::high_resolution_clock::now(); - - uint8_t* buf_ptrs[2]; - // Minor HACK to access the buffers in a 2-element queue - buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; - buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; - - size_t* ngood_bytes_ptrs[2]; - ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; - ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; - size_t* src_ngood_bytes_ptrs[2]; - src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; - src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - - int state = _capture.run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - &_decoder, - &_processor); - if( state & UDPCaptureThread::CAPTURE_ERROR ) { - return BF_CAPTURE_ERROR; - } else if( state & UDPCaptureThread::CAPTURE_INTERRUPTED ) { - return BF_CAPTURE_INTERRUPTED; - } - const PacketStats* stats = _capture.get_stats(); - _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" - << "nmissing_bytes : " << _nmissing_bytes << "\n" - << "ninvalid : " << stats->ninvalid << "\n" - << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" - << "nlate : " << stats->nlate << "\n" - << "nlate_bytes : " << stats->nlate_bytes << "\n" - << "nvalid : " << stats->nvalid << "\n" - << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; - - _t1 = std::chrono::high_resolution_clock::now(); - - BFudpcapture_status ret; - bool was_active = _active; - _active = state & UDPCaptureThread::CAPTURE_SUCCESS; - if( _active ) { - const PacketDesc* pkt = _capture.get_last_packet(); - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + if( pkt->src / 2 == 0 ) { + if( pkt->tuning != _chan0 ) { + _tstate |= 1; + _chan0 = pkt->tuning; } - else { - //cout << "No latest packet" << endl; - } - if( !was_active ) { - //cout << "Beginning of sequence, first pkt seq = " << pkt->seq << endl; - // TODO: Might be safer to round to nearest here, but the current firmware - // always starts things ~3 seq's before the 1sec boundary anyway. - //seq = round_up(pkt->seq, _slot_ntime); - //*_seq = round_nearest(pkt->seq, _slot_ntime); - _seq = round_up(pkt->seq, _slot_ntime); - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "nchan : " << _nchan << "\n" - << "payload_size : " << _payload_size << "\n"; - this->begin_sequence(); - ret = BF_CAPTURE_STARTED; - } else { - //cout << "Continuing data, seq = " << seq << endl; - if( pkt->chan0 != _chan0 || - pkt->nchan != _nchan ) { - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "nchan : " << _nchan << "\n" - << "payload_size : " << _payload_size << "\n"; - this->end_sequence(); - this->begin_sequence(); - ret = BF_CAPTURE_CHANGED; - } else { - ret = BF_CAPTURE_CONTINUED; - } + } else { + if( pkt->tuning != _chan1 ) { + _tstate |= 2; + _chan1 = pkt->tuning; } - if( _bufs.size() == 2 ) { - this->commit_buf(); + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return ( (_tstate == 3 && _nsrc == 4) + || (_tstate != 0 && _nsrc == 2) ); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); } - this->reserve_buf(); } else { - - if( was_active ) { - this->flush(); - ret = BF_CAPTURE_ENDED; - } else { - ret = BF_CAPTURE_NO_DATA; - } + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; } - - _t2 = std::chrono::high_resolution_clock::now(); - _process_time = std::chrono::duration_cast>(_t1-_t0); - _reserve_time = std::chrono::duration_cast>(_t2-_t1); - _perf_log.update() << "acquire_time : " << -1.0 << "\n" - << "process_time : " << _process_time.count() << "\n" - << "reserve_time : " << _reserve_time.count() << "\n"; - - return ret; + + _time_tag = pkt->time_tag; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFudpcapture_drx_impl(int fd, + BFring ring, + int nsrc, + int src0, + int max_payload_size, + int buffer_ntime, + int slot_ntime, + BFudpcapture_chips_sequence_callback sequence_callback, + int core) + : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + _type_log("udp_capture/type"), + _chan_log("udp_capture/chans"), + _sequence_callback(sequence_callback), + _chan1(), _tstate(0) { + size_t contig_span = this->bufsize(max_payload_size); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _type_log.update("type : %s", "tbn"); } }; -BFstatus bfUdpCaptureCreate(BFudpcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, +BFstatus bfUdpCaptureCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, BFudpcapture_sequence_callback sequence_callback, - int core) { + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_impl(fd, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, - sequence_callback, core), + BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_chips_impl(fd, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, + sequence_callback, core), + *obj = 0); + } else if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_tbn_impl(fd, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, + sequence_callback, core), + *obj = 0); + } else if( format == std::string("drx") ) { + BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_drx_impl(fd, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, + sequence_callback, core), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } } -BFstatus bfUdpCaptureDestroy(BFudpcapture obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - delete obj; - return BF_STATUS_SUCCESS; -} -BFstatus bfUdpCaptureRecv(BFudpcapture obj, BFudpcapture_status* result) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN_ELSE(*result = obj->recv(), - *result = BF_CAPTURE_ERROR); -} -BFstatus bfUdpCaptureFlush(BFudpcapture obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->flush()); -} -BFstatus bfUdpCaptureEnd(BFudpcapture obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->end_writing()); -} + From ffd7d03ec506007f650611b527e6b1febd1732d8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 May 2019 13:27:09 -0600 Subject: [PATCH 005/424] Updated the Python interface to match the C++ interface. --- python/bifrost/disk_reader.py | 18 +++++++++--------- python/bifrost/udp_capture.py | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/python/bifrost/disk_reader.py b/python/bifrost/disk_reader.py index 023d230a7..768d6706b 100644 --- a/python/bifrost/disk_reader.py +++ b/python/bifrost/disk_reader.py @@ -1,5 +1,5 @@ -# Copyright (c) 2017, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -31,23 +31,23 @@ class DiskReader(BifrostObject): def __init__(self, fmt, fh, ring, nsrc, src0, - buffer_nframe, slot_nframe, sequence_callback, core=None): + buffer_ntime, slot_ntime, sequence_callback, core=None): if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfDiskReaderCreate, _bf.bfDiskReaderDestroy, + self, _bf.bfDiskReaderCreate, _bf.bfDataCaptureDestroy, fmt, fh.fileno(), ring.obj, nsrc, src0, - buffer_nframe, slot_nframe, + buffer_ntime, slot_ntime, sequence_callback, core) def __enter__(self): return self def __exit__(self, type, value, tb): self.end() - def read(self): - status = _bf.BFdiskreader_status() - _check(_bf.bfDiskReaderRead(self.obj, status)) + def recv(self): + status = _bf.BFdatacapture_status() + _check(_bf.bfDataCaptureRecv(self.obj, status)) return status def flush(self): - _check(_bf.bfDiskReaderFlush(self.obj)) + _check(_bf.bfDataCaptureFlush(self.obj)) def end(self): - _check(_bf.bfDiskReaderEnd(self.obj)) + _check(_bf.bfDataCaptureEnd(self.obj)) diff --git a/python/bifrost/udp_capture.py b/python/bifrost/udp_capture.py index 312c3c35a..0c440fd41 100644 --- a/python/bifrost/udp_capture.py +++ b/python/bifrost/udp_capture.py @@ -35,7 +35,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfUdpCaptureDestroy, + self, _bf.bfUdpCaptureCreate, _bf.bfDataCaptureDestroy, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core) @@ -44,10 +44,10 @@ def __enter__(self): def __exit__(self, type, value, tb): self.end() def recv(self): - status = _bf.BFudpcapture_status() - _check(_bf.bfUdpCaptureRecv(self.obj, status)) + status = _bf.BFdatacapture_status() + _check(_bf.bfDataCaptureRecv(self.obj, status)) return status def flush(self): - _check(_bf.bfUdpCaptureFlush(self.obj)) + _check(_bf.bfDataCaptureFlush(self.obj)) def end(self): - _check(_bf.bfUdpCaptureEnd(self.obj)) + _check(_bf.bfDataCaptureEnd(self.obj)) From 2b9f62cf2318eeefe60866f5c16ffa87ad6a84a0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 21 May 2019 11:04:40 -0600 Subject: [PATCH 006/424] Worked on getting the sequence change callbacks cleaned up in the new unified framework. --- src/bifrost/data_capture.h | 16 +++++++-- src/bifrost/disk_reader.h | 5 +-- src/bifrost/udp_capture.h | 5 +-- src/data_capture.cpp | 21 ++++++++++++ src/data_capture.hpp | 28 ++++++++++++++++ src/disk_reader.cpp | 47 ++++++++++++-------------- src/udp_capture.cpp | 68 +++++++++++++++++--------------------- 7 files changed, 116 insertions(+), 74 deletions(-) diff --git a/src/bifrost/data_capture.h b/src/bifrost/data_capture.h index c0def94a4..8b1556c27 100644 --- a/src/bifrost/data_capture.h +++ b/src/bifrost/data_capture.h @@ -48,14 +48,26 @@ typedef enum BFdatacapture_status_ { BF_CAPTURE_ERROR } BFdatacapture_status; - - BFstatus bfDataCaptureDestroy(BFdatacapture obj); BFstatus bfDataCaptureRecv(BFdatacapture obj, BFdatacapture_status* result); BFstatus bfDataCaptureFlush(BFdatacapture obj); BFstatus bfDataCaptureEnd(BFdatacapture obj); // TODO: bfDataCaptureGetXX +typedef int (*BFdatacapture_chips_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); +typedef int (*BFdatacapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, + void const**, size_t*); +typedef int (*BFdatacapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, + void const**, size_t*); + +typedef struct BFdatacapture_callback_impl* BFdatacapture_callback; + +BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj); +BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback); +BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback); +BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index 580fb383d..405d08db2 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -39,9 +39,6 @@ extern "C" { typedef struct BFdiskreader_impl* BFdiskreader; -typedef int (*BFdiskreader_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); - BFstatus bfDiskReaderCreate(BFdatacapture* obj, const char* format, int fd, @@ -51,7 +48,7 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdiskreader_sequence_callback sequence_callback, + BFdatacapture_callback sequence_callback, int core); #ifdef __cplusplus diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index 5d25ad6e1..0577e79cf 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -39,9 +39,6 @@ extern "C" { typedef struct BFudpcapture_impl* BFudpcapture; -typedef int (*BFudpcapture_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); - BFstatus bfUdpCaptureCreate(BFdatacapture* obj, const char* format, int fd, @@ -51,7 +48,7 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFudpcapture_sequence_callback sequence_callback, + BFdatacapture_callback sequence_callback, int core); #ifdef __cplusplus diff --git a/src/data_capture.cpp b/src/data_capture.cpp index 8b184390c..8497c411f 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -158,3 +158,24 @@ BFstatus bfDataCaptureEnd(BFdatacapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->end_writing()); } + +BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_callback_impl(), + *obj = 0); +} + +BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback) { + obj->set_chips(callback); + return BF_STATUS_SUCCESS; +} + +BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback) { + obj->set_tbn(callback); + return BF_STATUS_SUCCESS; +} + +BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback) { + obj->set_drx(callback); + return BF_STATUS_SUCCESS; +} + diff --git a/src/data_capture.hpp b/src/data_capture.hpp index 31d063f32..7b4bd5f94 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -235,6 +235,34 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { return (2*val/mult+1)/2*mult; } +class BFdatacapture_callback_impl { + BFdatacapture_chips_sequence_callback _chips_callback; + BFdatacapture_tbn_sequence_callback _tbn_callback; + BFdatacapture_drx_sequence_callback _drx_callback; +public: + BFdatacapture_callback_impl() + : _chips_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} + inline void set_chips(BFdatacapture_chips_sequence_callback callback) { + _chips_callback = callback; + } + inline BFdatacapture_chips_sequence_callback get_chips() { + return _chips_callback; + } + inline void set_tbn(BFdatacapture_tbn_sequence_callback callback) { + _tbn_callback = callback; + } + inline BFdatacapture_tbn_sequence_callback get_tbn() { + return _tbn_callback; + } + inline void set_drx(BFdatacapture_drx_sequence_callback callback) { + _drx_callback = callback; + } + inline BFdatacapture_drx_sequence_callback get_drx() { + return _drx_callback; + } + +}; + class BFdatacapture_impl { protected: std::string _name; diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 392e09960..2fa0a9d6d 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -152,9 +152,6 @@ class DiskReaderThread : public DataCaptureThread { } }; -typedef int (*BFdiskreader_tbn_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); - class BFdiskreader_tbn_impl : public BFdatacapture_impl { DiskReaderThread _capture; TBNDecoder _decoder; @@ -162,7 +159,7 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdiskreader_tbn_sequence_callback _sequence_callback; + BFdatacapture_tbn_sequence_callback _sequence_callback; BFoffset _time_tag; @@ -183,14 +180,14 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + *time_tag, + _chan0, + _nsrc, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -216,13 +213,13 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFdiskreader_tbn_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("disk_reader/type"), _chan_log("disk_reader/chans"), - _sequence_callback(sequence_callback) { + _sequence_callback((*sequence_callback)->get_tbn()) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; @@ -231,9 +228,6 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { _type_log.update("type : %s", "tbn"); } }; - -typedef int (*BFdiskreader_drx_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); class BFdiskreader_drx_impl : public BFdatacapture_impl { DiskReaderThread _capture; @@ -242,7 +236,7 @@ class BFdiskreader_drx_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdiskreader_drx_sequence_callback _sequence_callback; + BFdatacapture_drx_sequence_callback _sequence_callback; BFoffset _time_tag; int _chan1; @@ -278,14 +272,15 @@ class BFdiskreader_drx_impl : public BFdatacapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + *time_tag, + _chan0, + _chan1, + _nsrc, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -311,20 +306,20 @@ class BFdiskreader_drx_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFdiskreader_tbn_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("disk_reader/type"), _chan_log("disk_reader/chans"), - _sequence_callback(sequence_callback), + _sequence_callback((*sequence_callback)->get_drx()), _chan1(), _tstate(0) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; size_t nringlet_max = 1; _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "tbn"); + _type_log.update("type : %s", "drx"); } }; @@ -337,7 +332,7 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdiskreader_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); if( format == std::string("tbn") ) { diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index 013be453c..6b61d8ba6 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -218,9 +218,6 @@ class UDPCaptureThread : public DataCaptureThread { } }; -typedef int (*BFudpcapture_chips_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); - class BFudpcapture_chips_impl : public BFdatacapture_impl { UDPCaptureThread _capture; CHIPSDecoder _decoder; @@ -228,7 +225,7 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFudpcapture_chips_sequence_callback _sequence_callback; + BFdatacapture_chips_sequence_callback _sequence_callback; void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { // TODO: Might be safer to round to nearest here, but the current firmware @@ -254,12 +251,12 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -286,13 +283,13 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFudpcapture_chips_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback) { + _sequence_callback((*sequence_callback)->get_chips()) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; @@ -302,9 +299,6 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { } }; -typedef int (*BFudpcapture_tbn_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); - class BFudpcapture_tbn_impl : public BFdatacapture_impl { UDPCaptureThread _capture; TBNDecoder _decoder; @@ -312,7 +306,7 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFudpcapture_tbn_sequence_callback _sequence_callback; + BFdatacapture_tbn_sequence_callback _sequence_callback; BFoffset _time_tag; @@ -333,14 +327,14 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + *time_tag, + _chan0, + _nsrc, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -366,13 +360,13 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFudpcapture_chips_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback) { + _sequence_callback((*sequence_callback)->get_tbn()) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; @@ -381,9 +375,6 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { _type_log.update("type : %s", "tbn"); } }; - -typedef int (*BFudpcapture_drx_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); class BFudpcapture_drx_impl : public BFdatacapture_impl { UDPCaptureThread _capture; @@ -392,7 +383,7 @@ class BFudpcapture_drx_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFudpcapture_drx_sequence_callback _sequence_callback; + BFdatacapture_drx_sequence_callback _sequence_callback; BFoffset _time_tag; int _chan1; @@ -428,14 +419,15 @@ class BFudpcapture_drx_impl : public BFdatacapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + *time_tag, + _chan0, + _chan1, + _nsrc, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -461,20 +453,20 @@ class BFudpcapture_drx_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFudpcapture_chips_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback), + _sequence_callback((*sequence_callback)->get_drx()), _chan1(), _tstate(0) { size_t contig_span = this->bufsize(max_payload_size); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; size_t nringlet_max = 1; _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "tbn"); + _type_log.update("type : %s", "drx"); } }; @@ -487,7 +479,7 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFudpcapture_sequence_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); if( format == std::string("chips") ) { From 21e3f40d8aba76380fea2f8cf89bfabe95f64002 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 21 May 2019 11:16:46 -0600 Subject: [PATCH 007/424] Moved udp_capture.py and disk_reader.py into a new data_capture.py module. Also, added a missing destructore for the BFdatacapture_callback_impl class. --- .../{disk_reader.py => data_capture.py} | 39 +++++++++++++- python/bifrost/udp_capture.py | 53 ------------------- src/bifrost/data_capture.h | 1 + src/data_capture.cpp | 9 ++++ 4 files changed, 48 insertions(+), 54 deletions(-) rename python/bifrost/{disk_reader.py => data_capture.py} (59%) delete mode 100644 python/bifrost/udp_capture.py diff --git a/python/bifrost/disk_reader.py b/python/bifrost/data_capture.py similarity index 59% rename from python/bifrost/disk_reader.py rename to python/bifrost/data_capture.py index 768d6706b..ab25688ba 100644 --- a/python/bifrost/disk_reader.py +++ b/python/bifrost/data_capture.py @@ -27,7 +27,44 @@ # **TODO: Write tests for this class -from libbifrost import _bf, _check, _get, BifrostObject +from libbifrost import _bf, _check, _get, BifrostObject, BFdatacapture_chips_sequence_callback, BFdatacapture_tbn_sequence_callback, BFdatacapture_drx_sequence_callback + +class SequenceCallback(BifrostObject): + def __init__(self): + BifrostObject.__init__( + self, _bf.bfDataCaptureCallbackCreate, _bf.bfDataCaptureCallbackDestroy) + def set_chips(self, fnc): + _check(_bf.bfDataCaptureCallbackSetCHIPS( + BFdatacapture_chips_sequence_callback(fnc))) + def set_tbn(self, fnc): + _check(_bf.bfDataCaptureCallbackSetTBN( + BFdatacapture_tbn_sequence_callback(fnc))) + def set_drx(self, fnc): + _check(_bf.bfDataCaptureCallbackSetDRX( + BFdatacapture_drx_sequence_callback(fnc))) + +class UDPCapture(BifrostObject): + def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpCaptureCreate, _bf.bfDataCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback, core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.end() + def recv(self): + status = _bf.BFdatacapture_status() + _check(_bf.bfDataCaptureRecv(self.obj, status)) + return status + def flush(self): + _check(_bf.bfDataCaptureFlush(self.obj)) + def end(self): + _check(_bf.bfDataCaptureEnd(self.obj)) class DiskReader(BifrostObject): def __init__(self, fmt, fh, ring, nsrc, src0, diff --git a/python/bifrost/udp_capture.py b/python/bifrost/udp_capture.py deleted file mode 100644 index 0c440fd41..000000000 --- a/python/bifrost/udp_capture.py +++ /dev/null @@ -1,53 +0,0 @@ - -# Copyright (c) 2016, The Bifrost Authors. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of The Bifrost Authors nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# **TODO: Write tests for this class - -from libbifrost import _bf, _check, _get, BifrostObject - -class UDPCapture(BifrostObject): - def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): - if core is None: - core = -1 - BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfDataCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, - max_payload_size, buffer_ntime, slot_ntime, - sequence_callback, core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.end() - def recv(self): - status = _bf.BFdatacapture_status() - _check(_bf.bfDataCaptureRecv(self.obj, status)) - return status - def flush(self): - _check(_bf.bfDataCaptureFlush(self.obj)) - def end(self): - _check(_bf.bfDataCaptureEnd(self.obj)) diff --git a/src/bifrost/data_capture.h b/src/bifrost/data_capture.h index 8b1556c27..29f119ba4 100644 --- a/src/bifrost/data_capture.h +++ b/src/bifrost/data_capture.h @@ -64,6 +64,7 @@ typedef int (*BFdatacapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, typedef struct BFdatacapture_callback_impl* BFdatacapture_callback; BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj); +BFstatus bfDataCaptureCallbackDestroy(BFdatacapture_callback obj); BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback); BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback); BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback); diff --git a/src/data_capture.cpp b/src/data_capture.cpp index 8497c411f..fd0ffc7fc 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -164,17 +164,26 @@ BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj) { *obj = 0); } +BFstatus bfDataCaptureCallbackDestroy(BFdatacapture_callback obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_chips(callback); return BF_STATUS_SUCCESS; } BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_tbn(callback); return BF_STATUS_SUCCESS; } BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_drx(callback); return BF_STATUS_SUCCESS; } From 320b453d3bb4fc988affadd5c42f51e2d8d6c3a1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 21 May 2019 11:22:08 -0600 Subject: [PATCH 008/424] A few more tweaks to the Python interface for data capture. --- python/bifrost/data_capture.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index ab25688ba..9ac99b1b6 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -29,19 +29,19 @@ from libbifrost import _bf, _check, _get, BifrostObject, BFdatacapture_chips_sequence_callback, BFdatacapture_tbn_sequence_callback, BFdatacapture_drx_sequence_callback -class SequenceCallback(BifrostObject): +class DataCaptureCallback(BifrostObject): def __init__(self): BifrostObject.__init__( self, _bf.bfDataCaptureCallbackCreate, _bf.bfDataCaptureCallbackDestroy) def set_chips(self, fnc): _check(_bf.bfDataCaptureCallbackSetCHIPS( - BFdatacapture_chips_sequence_callback(fnc))) + self.obj, BFdatacapture_chips_sequence_callback(fnc))) def set_tbn(self, fnc): _check(_bf.bfDataCaptureCallbackSetTBN( - BFdatacapture_tbn_sequence_callback(fnc))) + self.obj, BFdatacapture_tbn_sequence_callback(fnc))) def set_drx(self, fnc): _check(_bf.bfDataCaptureCallbackSetDRX( - BFdatacapture_drx_sequence_callback(fnc))) + self.obj, BFdatacapture_drx_sequence_callback(fnc))) class UDPCapture(BifrostObject): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, @@ -68,13 +68,13 @@ def end(self): class DiskReader(BifrostObject): def __init__(self, fmt, fh, ring, nsrc, src0, - buffer_ntime, slot_ntime, sequence_callback, core=None): + buffer_nframe, slot_nframe, sequence_callback, core=None): if core is None: core = -1 BifrostObject.__init__( self, _bf.bfDiskReaderCreate, _bf.bfDataCaptureDestroy, fmt, fh.fileno(), ring.obj, nsrc, src0, - buffer_ntime, slot_ntime, + buffer_nframe, slot_nframe, sequence_callback, core) def __enter__(self): return self From 03990566455ffa691ef7499f5db02fbfe12978ce Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 21 May 2019 16:07:41 -0600 Subject: [PATCH 009/424] Fixed a few problems in the new header files and the data_capture.py module. --- python/bifrost/data_capture.py | 8 ++++---- src/bifrost/data_capture.h | 1 - src/bifrost/disk_reader.h | 5 +---- src/bifrost/udp_capture.h | 5 +---- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index 9ac99b1b6..cddfe6cd8 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -27,7 +27,7 @@ # **TODO: Write tests for this class -from libbifrost import _bf, _check, _get, BifrostObject, BFdatacapture_chips_sequence_callback, BFdatacapture_tbn_sequence_callback, BFdatacapture_drx_sequence_callback +from libbifrost import _bf, _check, _get, BifrostObject class DataCaptureCallback(BifrostObject): def __init__(self): @@ -35,13 +35,13 @@ def __init__(self): self, _bf.bfDataCaptureCallbackCreate, _bf.bfDataCaptureCallbackDestroy) def set_chips(self, fnc): _check(_bf.bfDataCaptureCallbackSetCHIPS( - self.obj, BFdatacapture_chips_sequence_callback(fnc))) + self.obj, _bf.BFdatacapture_chips_sequence_callback(fnc))) def set_tbn(self, fnc): _check(_bf.bfDataCaptureCallbackSetTBN( - self.obj, BFdatacapture_tbn_sequence_callback(fnc))) + self.obj, _bf.BFdatacapture_tbn_sequence_callback(fnc))) def set_drx(self, fnc): _check(_bf.bfDataCaptureCallbackSetDRX( - self.obj, BFdatacapture_drx_sequence_callback(fnc))) + self.obj, _bf.BFdatacapture_drx_sequence_callback(fnc))) class UDPCapture(BifrostObject): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, diff --git a/src/bifrost/data_capture.h b/src/bifrost/data_capture.h index 29f119ba4..564e6624a 100644 --- a/src/bifrost/data_capture.h +++ b/src/bifrost/data_capture.h @@ -33,7 +33,6 @@ extern "C" { #endif -#include #include typedef struct BFdatacapture_impl* BFdatacapture; diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index 405d08db2..f3a5a5f0e 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -34,11 +34,8 @@ extern "C" { #endif #include -#include #include -typedef struct BFdiskreader_impl* BFdiskreader; - BFstatus bfDiskReaderCreate(BFdatacapture* obj, const char* format, int fd, @@ -48,7 +45,7 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core); #ifdef __cplusplus diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index 0577e79cf..aae3c9cc5 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -34,11 +34,8 @@ extern "C" { #endif #include -#include #include -typedef struct BFudpcapture_impl* BFudpcapture; - BFstatus bfUdpCaptureCreate(BFdatacapture* obj, const char* format, int fd, @@ -48,7 +45,7 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback sequence_callback, + BFdatacapture_callback* sequence_callback, int core); #ifdef __cplusplus From bbb1f1654221990eed96fae96f935058ac1ce268 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 22 May 2019 12:17:19 -0600 Subject: [PATCH 010/424] Acutally got the new interface working, at least with TBN. Quite a few debugging statements in there still. --- python/bifrost/data_capture.py | 2 +- src/bifrost/disk_reader.h | 3 +- src/bifrost/udp_capture.h | 2 +- src/data_capture.cpp | 113 ++++++++++++++++++++--- src/data_capture.hpp | 89 +++++++++++------- src/disk_reader.cpp | 161 ++++++++++----------------------- src/formats/base.hpp | 7 +- src/formats/chips.hpp | 4 +- src/formats/drx.hpp | 31 +++---- src/formats/tbn.hpp | 12 +-- src/udp_capture.cpp | 149 ++++++++++-------------------- 11 files changed, 280 insertions(+), 293 deletions(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index cddfe6cd8..667976a97 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -75,7 +75,7 @@ def __init__(self, fmt, fh, ring, nsrc, src0, self, _bf.bfDiskReaderCreate, _bf.bfDataCaptureDestroy, fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, - sequence_callback, core) + sequence_callback.obj, core) def __enter__(self): return self def __exit__(self, type, value, tb): diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index f3a5a5f0e..3c551799a 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -42,10 +42,9 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFring ring, BFsize nsrc, BFsize src0, - BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core); #ifdef __cplusplus diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index aae3c9cc5..83249101d 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -45,7 +45,7 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core); #ifdef __cplusplus diff --git a/src/data_capture.cpp b/src/data_capture.cpp index fd0ffc7fc..f4244e78e 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -28,6 +28,9 @@ #include "data_capture.hpp" +#define BF_PRINTD(stmt) \ + std::cout << stmt << std::endl + #if BF_HWLOC_ENABLED int HardwareLocality::bind_memory_to_core(int core) { int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); @@ -46,6 +49,81 @@ int HardwareLocality::bind_memory_to_core(int core) { } #endif // BF_HWLOC_ENABLED +// Reads, decodes and unpacks frames into the provided buffers +// Note: Read continues until the first frame that belongs +// beyond the end of the provided buffers. This frame is +// saved, accessible via get_last_frame(), and will be +// processed on the next call to run() if possible. +template +int DataCaptureThread::run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + PDC* decode, + PPC* process) { + uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; + size_t local_ngood_bytes[2] = {0, 0}; + int ret; + while( true ) { + if( !_have_pkt ) { + uint8_t* pkt_ptr; + int pkt_size = (this->get_method())->recv_packet(&pkt_ptr); + if( pkt_size <= 0 ) { + if( errno == EAGAIN || errno == EWOULDBLOCK ) { + ret = CAPTURE_TIMEOUT; // Timed out + } else if( errno == EINTR ) { + ret = CAPTURE_INTERRUPTED; // Interrupted by signal + } else { + ret = CAPTURE_ERROR; // Socket error + } + break; + } + BF_PRINTD("HERE"); + if( !(*decode)(pkt_ptr, pkt_size, &_pkt) ) { + BF_PRINTD("INVALID " << std::hex << _pkt.sync << " " << std::dec << _pkt.src << " " << _pkt.src << " " << _pkt.time_tag << " " << _pkt.tuning << " " << _pkt.valid_mode); + ++_stats.ninvalid; + _stats.ninvalid_bytes += pkt_size; + continue; + } + BF_PRINTD("VALID " << std::hex << _pkt.sync << " " << std::dec << _pkt.src << " " << _pkt.src << " " << _pkt.time_tag << " " << _pkt.tuning << " " << _pkt.valid_mode); + _have_pkt = true; + } + BF_PRINTD("NOW" << " " << _pkt.seq << " >= " << seq_end); + if( greater_equal(_pkt.seq, seq_end) ) { + // Reached the end of this processing gulp, so leave this + // packet unprocessed and return. + ret = CAPTURE_SUCCESS; + BF_PRINTD("BREAK NOW"); + break; + } + BF_PRINTD("HERE" << " " << _pkt.seq << " < " << seq_beg); + _have_pkt = false; + if( less_than(_pkt.seq, seq_beg) ) { + ++_stats.nlate; + _stats.nlate_bytes += _pkt.payload_size; + ++_src_stats[_pkt.src].nlate; + _src_stats[_pkt.src].nlate_bytes += _pkt.payload_size; + BF_PRINTD("CONTINUE HERE"); + continue; + } + BF_PRINTD("FINALLY"); + ++_stats.nvalid; + _stats.nvalid_bytes += _pkt.payload_size; + ++_src_stats[_pkt.src].nvalid; + _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; + // HACK TODO: src_ngood_bytes should be accumulated locally and + // then atomically updated, like ngood_bytes. The + // current way is not thread-safe. + (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, + local_ngood_bytes, /*local_*/src_ngood_bytes); + } + if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } + if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } + return ret; +} + BFdatacapture_status BFdatacapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); @@ -62,20 +140,21 @@ BFdatacapture_status BFdatacapture_impl::recv() { src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - int state = _capture.run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - &_decoder, - &_processor); + int state = (this->get_capture())->run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + this->get_decoder(), + this->get_processor()); + BF_PRINTD("OUTSIDE"); if( state & DataCaptureThread::CAPTURE_ERROR ) { - return BF_CAPTURE_ERROR; + return BF_CAPTURE_ERROR; } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { return BF_CAPTURE_INTERRUPTED; } - const PacketStats* stats = _capture.get_stats(); + const PacketStats* stats = (this->get_capture())->get_stats(); _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" << "nmissing_bytes : " << _nmissing_bytes << "\n" << "ninvalid : " << stats->ninvalid << "\n" @@ -87,18 +166,22 @@ BFdatacapture_status BFdatacapture_impl::recv() { _t1 = std::chrono::high_resolution_clock::now(); - BFoffset seq0, time_tag; - const void* hdr; - size_t hdr_size; + BFoffset seq0, time_tag=0; + const void* hdr=NULL; + size_t hdr_size=0; BFdatacapture_status ret; bool was_active = _active; _active = state & DataCaptureThread::CAPTURE_SUCCESS; + BF_PRINTD("ACTIVE: " << _active << " WAS ACTIVE: " << was_active); if( _active ) { - const PacketDesc* pkt = _capture.get_last_packet(); + BF_PRINTD("START"); + const PacketDesc* pkt = (this->get_capture())->get_last_packet(); + BF_PRINTD("PRE-CALL"); this->on_sequence_active(pkt); + BF_PRINTD("POST-CALL"); if( !was_active ) { - //cout << "Beginning of sequence, first pkt seq = " << pkt->seq << endl; + BF_PRINTD("Beginning of sequence, first pkt seq = " << pkt->seq); this->on_sequence_start(pkt, &seq0, &time_tag, &hdr, &hdr_size); this->begin_sequence(seq0, time_tag, hdr, hdr_size); ret = BF_CAPTURE_STARTED; diff --git a/src/data_capture.hpp b/src/data_capture.hpp index 7b4bd5f94..8c4bf3c9d 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -125,9 +125,10 @@ class AlignedBuffer { tmp.swap(*this); } } - inline size_t size() const { return _size; } - inline T & operator[](size_t i) { return _buf[i]; } - inline T const& operator[](size_t i) const { return _buf[i]; } + inline size_t size() const { return _size; } + inline size_t alignment() const { return _alignment; } + inline T & operator[](size_t i) { return _buf[i]; } + inline T const& operator[](size_t i) const { return _buf[i]; } }; #if BF_HWLOC_ENABLED @@ -167,9 +168,8 @@ class DataCaptureMethod { AlignedBuffer _buf; public: DataCaptureMethod(int fd, size_t pkt_size_max=9000) - : _fd(fd), _buf(pkt_size_max) - {} - virtual inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + : _fd(fd), _buf(pkt_size_max) {} + virtual int recv_packet(uint8_t** pkt_ptr, int flags=0) { return 0; } }; @@ -184,12 +184,16 @@ struct PacketStats { }; class DataCaptureThread : public BoundThread { -protected: - DataCaptureMethod _mthd; +private: + DataCaptureMethod _method; PacketStats _stats; std::vector _src_stats; bool _have_pkt; PacketDesc _pkt; + + virtual DataCaptureMethod* get_method() { + return &_method; + } public: enum { CAPTURE_SUCCESS = 1 << 0, @@ -198,20 +202,19 @@ class DataCaptureThread : public BoundThread { CAPTURE_ERROR = 1 << 3 }; DataCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : BoundThread(core), _mthd(fd, pkt_size_max), _src_stats(nsrc), - _have_pkt(false) { + : BoundThread(core), _method(fd, pkt_size_max), _src_stats(nsrc), + _have_pkt(false) { this->reset_stats(); } - virtual int run(uint64_t seq_beg, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t* ngood_bytes[], - size_t* src_ngood_bytes[], - PacketDecoder* decode, - PacketProcessor* process) { - return CAPTURE_ERROR; - } + template + int run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + PDC* decode, + PPC* process); inline const PacketDesc* get_last_packet() const { return _have_pkt ? &_pkt : NULL; } @@ -276,12 +279,6 @@ class BFdatacapture_impl { ProcLog _perf_log; pid_t _pid; - std::chrono::high_resolution_clock::time_point _t0; - std::chrono::high_resolution_clock::time_point _t1; - std::chrono::high_resolution_clock::time_point _t2; - std::chrono::duration _process_time; - std::chrono::duration _reserve_time; - int _nsrc; int _nseq_per_buf; int _slot_ntime; @@ -290,6 +287,13 @@ class BFdatacapture_impl { int _nchan; int _payload_size; bool _active; + +private: + std::chrono::high_resolution_clock::time_point _t0; + std::chrono::high_resolution_clock::time_point _t1; + std::chrono::high_resolution_clock::time_point _t2; + std::chrono::duration _process_time; + std::chrono::duration _reserve_time; RingWrapper _ring; RingWriter _oring; @@ -300,6 +304,15 @@ class BFdatacapture_impl { size_t _ngood_bytes; size_t _nmissing_bytes; + virtual DataCaptureThread* get_capture() { + return &_capture; + } + virtual PacketDecoder* get_decoder() { + return &_decoder; + } + virtual PacketProcessor* get_processor() { + return &_processor; + } inline size_t bufsize(int payload_size=-1) { if( payload_size == -1 ) { payload_size = _payload_size; @@ -354,9 +367,7 @@ class BFdatacapture_impl { } virtual void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} virtual void on_sequence_active(const PacketDesc* pkt) {} - virtual inline bool has_sequence_changed(const PacketDesc* pkt) { - return false; - } + virtual inline bool has_sequence_changed(const PacketDesc* pkt) { return false; } virtual void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} public: inline BFdatacapture_impl(std::string name, @@ -378,9 +389,25 @@ class BFdatacapture_impl { _seq(), _chan0(), _nchan(), _active(false), _ring(ring), _oring(_ring), // TODO: Add reset method for stats - _ngood_bytes(0), _nmissing_bytes(0) {} + _ngood_bytes(0), _nmissing_bytes(0) { + size_t contig_span = this->bufsize(max_payload_size); + // Note: 2 write bufs may be open for writing at one time + size_t total_span = contig_span * 4; + size_t nringlet_max = 1; + _ring.resize(contig_span, total_span, nringlet_max); + _bind_log.update("ncore : %i\n" + "core0 : %i\n", + 1, core); + _out_log.update("nring : %i\n" + "ring0 : %s\n", + 1, _ring.name()); + _size_log.update("nsrc : %i\n" + "nseq_per_buf : %i\n" + "slot_ntime : %i\n", + _nsrc, _nseq_per_buf, _slot_ntime); + } virtual ~BFdatacapture_impl() {} - inline void flush() { + inline void flush() { while( _bufs.size() ) { this->commit_buf(); } diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 2fa0a9d6d..049b40c19 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -54,105 +54,30 @@ using bifrost::ring::WriteSequence; #include #include -class DiskPacketReader : public DataCaptureMethod { - int _fd; - AlignedBuffer _buf; +class DiskPacketReader : virtual public DataCaptureMethod { public: DiskPacketReader(int fd, size_t pkt_size_max=9000) - : DataCaptureMethod(fd, pkt_size_max), _fd(fd), _buf(pkt_size_max) {} - inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + : DataCaptureMethod(fd, pkt_size_max) {} + int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); } }; -class DiskReaderThread : public DataCaptureThread { - DiskPacketReader _disk; - PacketStats _stats; - std::vector _src_stats; - bool _have_pkt; - PacketDesc _pkt; +class DiskReaderThread : virtual public DataCaptureThread { + DiskPacketReader _method; + + DataCaptureMethod* get_method() { + return &_method; + } public: - enum { - CAPTURE_SUCCESS = 1 << 0, - CAPTURE_TIMEOUT = 1 << 1, - CAPTURE_INTERRUPTED = 1 << 2, - CAPTURE_ERROR = 1 << 3 - }; DiskReaderThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : DataCaptureThread(fd, nsrc, core, pkt_size_max), _disk(fd, pkt_size_max), _src_stats(nsrc), - _have_pkt(false) { - this->reset_stats(); - } - // Reads, decodes and unpacks frames into the provided buffers - // Note: Read continues until the first frame that belongs - // beyond the end of the provided buffers. This frame is - // saved, accessible via get_last_frame(), and will be - // processed on the next call to run() if possible. - template - int run(uint64_t seq_beg, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t* ngood_bytes[], - size_t* src_ngood_bytes[], - PacketDecoder* decode, - PacketProcessor* process) { - uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; - size_t local_ngood_bytes[2] = {0, 0}; - int ret; - while( true ) { - if( !_have_pkt ) { - uint8_t* pkt_ptr; - int pkt_size = _disk.recv_packet(&pkt_ptr); - if( pkt_size <= 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK ) { - ret = CAPTURE_TIMEOUT; // Timed out - } else if( errno == EINTR ) { - ret = CAPTURE_INTERRUPTED; // Interrupted by signal - } else { - ret = CAPTURE_ERROR; // Socket error - } - break; - } - if( !(*decode)(pkt_ptr, pkt_size, &_pkt) ) { - ++_stats.ninvalid; - _stats.ninvalid_bytes += pkt_size; - continue; - } - _have_pkt = true; - } - if( greater_equal(_pkt.seq, seq_end) ) { - // Reached the end of this processing gulp, so leave this - // frame unprocessed and return. - ret = CAPTURE_SUCCESS; - break; - } - _have_pkt = false; - if( less_than(_pkt.seq, seq_beg) ) { - ++_stats.nlate; - _stats.nlate_bytes += _pkt.payload_size; - ++_src_stats[_pkt.src].nlate; - _src_stats[_pkt.src].nlate_bytes += _pkt.payload_size; - continue; - } - ++_stats.nvalid; - _stats.nvalid_bytes += _pkt.payload_size; - ++_src_stats[_pkt.src].nvalid; - _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; - // HACK TODO: src_ngood_bytes should be accumulated locally and - // then atomically updated, like ngood_bytes. The - // current way is not thread-safe. - (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, - local_ngood_bytes, /*local_*/src_ngood_bytes); - } - if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } - if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } - return ret; + : DataCaptureThread(fd, nsrc, core, pkt_size_max), _method(fd, pkt_size_max) { + this->reset_stats(); } }; -class BFdiskreader_tbn_impl : public BFdatacapture_impl { +class BFdiskreader_tbn_impl : virtual public BFdatacapture_impl { DiskReaderThread _capture; TBNDecoder _decoder; TBNProcessor _processor; @@ -163,13 +88,22 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { BFoffset _time_tag; + inline DataCaptureThread* get_capture() { + return &_capture; + } + inline PacketDecoder* get_decoder() { + return &_decoder; + } + inline PacketProcessor* get_processor() { + return &_processor; + } void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + //cout << "Latest time_tag, tuning = " << pkt->time_tag << ", " << pkt->tuning << endl; } else { //cout << "No latest packet" << endl; @@ -179,6 +113,7 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { return (pkt->tuning != _chan0); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + //cout << "Sequence changed" << endl; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; if( _sequence_callback ) { @@ -210,26 +145,20 @@ class BFdiskreader_tbn_impl : public BFdatacapture_impl { BFring ring, int nsrc, int src0, - int max_payload_size, int buffer_ntime, int slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) - : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, TBN_FRAME_SIZE, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor(), _type_log("disk_reader/type"), _chan_log("disk_reader/chans"), - _sequence_callback((*sequence_callback)->get_tbn()) { - size_t contig_span = this->bufsize(max_payload_size); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "tbn"); + _sequence_callback(sequence_callback->get_tbn()) { + _type_log.update("type : %s\n", "tbn"); } }; -class BFdiskreader_drx_impl : public BFdatacapture_impl { +class BFdiskreader_drx_impl : virtual public BFdatacapture_impl { DiskReaderThread _capture; DRXDecoder _decoder; DRXProcessor _processor; @@ -242,6 +171,15 @@ class BFdiskreader_drx_impl : public BFdatacapture_impl { int _chan1; uint8_t _tstate; + inline DataCaptureThread* get_capture() { + return &_capture; + } + inline PacketDecoder* get_decoder() { + return &_decoder; + } + inline PacketProcessor* get_processor() { + return &_processor; + } void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); @@ -303,23 +241,17 @@ class BFdiskreader_drx_impl : public BFdatacapture_impl { BFring ring, int nsrc, int src0, - int max_payload_size, int buffer_ntime, int slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) - : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, DRX_FRAME_SIZE, buffer_ntime, slot_ntime, core), + _capture(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor(), _type_log("disk_reader/type"), _chan_log("disk_reader/chans"), - _sequence_callback((*sequence_callback)->get_drx()), + _sequence_callback(sequence_callback->get_drx()), _chan1(), _tstate(0) { - size_t contig_span = this->bufsize(max_payload_size); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "drx"); + _type_log.update("type : %s\n", "drx"); } }; @@ -329,19 +261,18 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFring ring, BFsize nsrc, BFsize src0, - BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_tbn_impl(fd, ring, nsrc, src0, max_payload_size, + BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_tbn_impl(fd, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback, core), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_drx_impl(fd, ring, nsrc, src0, max_payload_size, + BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_drx_impl(fd, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback, core), *obj = 0); diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 16f700066..286be3240 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -55,8 +55,10 @@ struct PacketDesc { uint32_t sync; uint64_t time_tag; int tuning; - int decimation; - int valid_mode; + uint8_t beam; + uint16_t gain; + uint16_t decimation; + uint8_t valid_mode; int payload_size; const uint8_t* payload_ptr; }; @@ -66,6 +68,7 @@ class PacketDecoder { protected: int _nsrc; int _src0; +private: virtual inline bool valid_packet(const PacketDesc* pkt) const { return false; } diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index d76fcf2c4..364be144a 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -45,7 +45,7 @@ struct chips_hdr_type { uint64_t seq; // Note: 1-based }; -class CHIPSDecoder : public PacketDecoder { +class CHIPSDecoder : virtual public PacketDecoder { inline bool valid_packet(const PacketDesc* pkt) const { return (pkt->seq >= 0 && pkt->src >= 0 && pkt->src < _nsrc && @@ -74,7 +74,7 @@ class CHIPSDecoder : public PacketDecoder { } }; -class CHIPSProcessor : public PacketProcessor { +class CHIPSProcessor : virtual public PacketProcessor { public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 1236c2ac1..b1ab71a89 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -44,48 +44,47 @@ struct drx_hdr_type { uint32_t flags; }; -class DRXDecoder : public PacketDecoder { +class DRXDecoder : virtual public PacketDecoder { inline bool valid_packet(const PacketDesc* pkt) const { - return (pkt->sync == 0x5CDEC0DE && - pkt->src >= 0 && - pkt->src < _nsrc && - pkt->time_tag >= 0 && - pkt->tuning >= 0); + return (pkt->sync == 0x5CDEC0DE && + pkt->src >= 0 && + pkt->src < _nsrc && + pkt->time_tag >= 0 && + pkt->tuning >= 0 && + pkt->valid_mode == 0); } public: DRXDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} inline bool operator()(const uint8_t* pkt_ptr, int pkt_size, PacketDesc* pkt) const { - if( pkt_size < (int)sizeof(drx_hdr_type) ) { + if( pkt_size != DRX_FRAME_SIZE ) { return false; } const drx_hdr_type* pkt_hdr = (drx_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(drx_hdr_type); int pld_size = pkt_size - sizeof(drx_hdr_type); - int pkt_id = pkt_hdr->frame_count_word & 0xFF; - //uint8_t pkt_beam = (pkt_id & 0x7) - 1; - int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; - int pkt_pol = ((pkt_id >> 7) & 0x1); - pkt_id = (pkt_tune << 1) | pkt_pol; + int pkt_id = pkt_hdr->frame_count_word & 0xFF; + pkt->beam = (pkt_id & 0x7) - 1; + int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; + int pkt_pol = ((pkt_id >> 7) & 0x1); + pkt_id = (pkt_tune << 1) | pkt_pol; pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag) - be16toh(pkt_hdr->time_offset); pkt->seq = pkt->time_tag / be16toh(pkt_hdr->decimation) / 4096; - //pkt->nsrc = pkt_hdr->nroach; pkt->nsrc = _nsrc; pkt->src = pkt_id - _src0; pkt->tuning = be32toh(pkt_hdr->tuning_word); pkt->decimation = be16toh(pkt_hdr->decimation); - pkt->valid_mode = 1; + pkt->valid_mode = ((pkt_id >> 6) & 0x1); pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; - // cout << pkt_id << pkt->src << "valid? " << this->valid_packet(pkt) << endl; return this->valid_packet(pkt); } }; -class DRXProcessor : public PacketProcessor { +class DRXProcessor : virtual public PacketProcessor { public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index b8bfe7d9f..cc3f78edf 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -42,21 +42,21 @@ struct tbn_hdr_type { uint64_t time_tag; }; -class TBNDecoder : public PacketDecoder { +class TBNDecoder : virtual public PacketDecoder { inline bool valid_packet(const PacketDesc* pkt) const { return (pkt->sync == 0x5CDEC0DE && pkt->src >= 0 && pkt->src < _nsrc && pkt->time_tag >= 0 && pkt->tuning >= 0 && - pkt->valid_mode == 1); + pkt->valid_mode == 0); } public: TBNDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} inline bool operator()(const uint8_t* pkt_ptr, int pkt_size, PacketDesc* pkt) const { - if( pkt_size < (int)sizeof(tbn_hdr_type) ) { + if( pkt_size != TBN_FRAME_SIZE ) { return false; } const tbn_hdr_type* pkt_hdr = (tbn_hdr_type*)pkt_ptr; @@ -65,19 +65,19 @@ class TBNDecoder : public PacketDecoder { pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag); pkt->seq = pkt->time_tag / 1960 / 512; - //pkt->nsrc = pkt_hdr->nroach; pkt->nsrc = _nsrc; pkt->src = (be16toh(pkt_hdr->tbn_id) & 1023) - 1 - _src0; pkt->tuning = be32toh(pkt_hdr->tuning_word); pkt->decimation = 1960; - pkt->valid_mode = (be16toh(pkt_hdr->tbn_id) >> 7) & 1; + pkt->valid_mode = (be16toh(pkt_hdr->tbn_id) >> 15) & 1; + pkt->gain = (be16toh(pkt_hdr->gain)); pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; return this->valid_packet(pkt); } }; -class TBNProcessor : public PacketProcessor { +class TBNProcessor : virtual public PacketProcessor { public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index 6b61d8ba6..27541f5fd 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -132,12 +132,12 @@ class UDPPacketReceiver : public DataCaptureMethod { } }; -class UDPCaptureThread : public DataCaptureThread { - UDPPacketReceiver _udp; - PacketStats _stats; - std::vector _src_stats; - bool _have_pkt; - PacketDesc _pkt; +class UDPCaptureThread : virtual public DataCaptureThread { + UDPPacketReceiver _method; + + DataCaptureMethod* get_method() { + return &_method; + } public: enum { CAPTURE_SUCCESS = 1 << 0, @@ -146,79 +146,12 @@ class UDPCaptureThread : public DataCaptureThread { CAPTURE_ERROR = 1 << 3 }; UDPCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : DataCaptureThread(fd, nsrc, core, pkt_size_max), _udp(fd, pkt_size_max), _src_stats(nsrc), - _have_pkt(false) { + : DataCaptureThread(fd, nsrc, core, pkt_size_max), _method(fd, pkt_size_max) { this->reset_stats(); } - // Captures, decodes and unpacks packets into the provided buffers - // Note: Capture continues until the first packet that belongs - // beyond the end of the provided buffers. This packet is - // saved, accessible via get_last_packet(), and will be - // processed on the next call to run() if possible. - template - int run(uint64_t seq_beg, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t* ngood_bytes[], - size_t* src_ngood_bytes[], - PacketDecoder* decode, - PacketProcessor* process) { - uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; - size_t local_ngood_bytes[2] = {0, 0}; - int ret; - while( true ) { - if( !_have_pkt ) { - uint8_t* pkt_ptr; - int pkt_size = _udp.recv_packet(&pkt_ptr); - if( pkt_size <= 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK ) { - ret = CAPTURE_TIMEOUT; // Timed out - } else if( errno == EINTR ) { - ret = CAPTURE_INTERRUPTED; // Interrupted by signal - } else { - ret = CAPTURE_ERROR; // Socket error - } - break; - } - if( !(*decode)(pkt_ptr, pkt_size, &_pkt) ) { - ++_stats.ninvalid; - _stats.ninvalid_bytes += pkt_size; - continue; - } - _have_pkt = true; - } - if( greater_equal(_pkt.seq, seq_end) ) { - // Reached the end of this processing gulp, so leave this - // packet unprocessed and return. - ret = CAPTURE_SUCCESS; - break; - } - _have_pkt = false; - if( less_than(_pkt.seq, seq_beg) ) { - ++_stats.nlate; - _stats.nlate_bytes += _pkt.payload_size; - ++_src_stats[_pkt.src].nlate; - _src_stats[_pkt.src].nlate_bytes += _pkt.payload_size; - continue; - } - ++_stats.nvalid; - _stats.nvalid_bytes += _pkt.payload_size; - ++_src_stats[_pkt.src].nvalid; - _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; - // HACK TODO: src_ngood_bytes should be accumulated locally and - // then atomically updated, like ngood_bytes. The - // current way is not thread-safe. - (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, - local_ngood_bytes, /*local_*/src_ngood_bytes); - } - if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } - if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } - return ret; - } }; -class BFudpcapture_chips_impl : public BFdatacapture_impl { +class BFudpcapture_chips_impl : virtual public BFdatacapture_impl { UDPCaptureThread _capture; CHIPSDecoder _decoder; CHIPSProcessor _processor; @@ -227,6 +160,15 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { BFdatacapture_chips_sequence_callback _sequence_callback; + inline DataCaptureThread* get_capture() { + return &_capture; + } + inline PacketDecoder* get_decoder() { + return &_decoder; + } + inline PacketProcessor* get_processor() { + return &_processor; + } void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { // TODO: Might be safer to round to nearest here, but the current firmware // always starts things ~3 seq's before the 1sec boundary anyway. @@ -283,23 +225,18 @@ class BFudpcapture_chips_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback((*sequence_callback)->get_chips()) { - size_t contig_span = this->bufsize(max_payload_size); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "chips"); + _sequence_callback(sequence_callback->get_chips()) { + _type_log.update("type : %s\n", "chips"); } }; -class BFudpcapture_tbn_impl : public BFdatacapture_impl { +class BFudpcapture_tbn_impl : virtual public BFdatacapture_impl { UDPCaptureThread _capture; TBNDecoder _decoder; TBNProcessor _processor; @@ -310,6 +247,15 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { BFoffset _time_tag; + inline DataCaptureThread* get_capture() { + return &_capture; + } + inline PacketDecoder* get_decoder() { + return &_decoder; + } + inline PacketProcessor* get_processor() { + return &_processor; + } void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); @@ -360,23 +306,18 @@ class BFudpcapture_tbn_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback((*sequence_callback)->get_tbn()) { - size_t contig_span = this->bufsize(max_payload_size); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "tbn"); + _sequence_callback(sequence_callback->get_tbn()) { + _type_log.update("type : %s\n", "tbn"); } }; -class BFudpcapture_drx_impl : public BFdatacapture_impl { +class BFudpcapture_drx_impl : virtual public BFdatacapture_impl { UDPCaptureThread _capture; DRXDecoder _decoder; DRXProcessor _processor; @@ -389,6 +330,15 @@ class BFudpcapture_drx_impl : public BFdatacapture_impl { int _chan1; uint8_t _tstate; + inline DataCaptureThread* get_capture() { + return &_capture; + } + inline PacketDecoder* get_decoder() { + return &_decoder; + } + inline PacketProcessor* get_processor() { + return &_processor; + } void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); @@ -453,20 +403,15 @@ class BFudpcapture_drx_impl : public BFdatacapture_impl { int max_payload_size, int buffer_ntime, int slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), _type_log("udp_capture/type"), _chan_log("udp_capture/chans"), - _sequence_callback((*sequence_callback)->get_drx()), + _sequence_callback(sequence_callback->get_drx()), _chan1(), _tstate(0) { - size_t contig_span = this->bufsize(max_payload_size); - // Note: 2 write bufs may be open for writing at one time - size_t total_span = contig_span * 4; - size_t nringlet_max = 1; - _ring.resize(contig_span, total_span, nringlet_max); - _type_log.update("type : %s", "drx"); + _type_log.update("type : %s\n", "drx"); } }; @@ -479,7 +424,7 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, - BFdatacapture_callback* sequence_callback, + BFdatacapture_callback sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); if( format == std::string("chips") ) { From e26063f81d46d4b79ccccfb197d14a389e9f7cd0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 22 May 2019 14:59:30 -0600 Subject: [PATCH 011/424] Fixed a problem passing the tuening work to the TBN callback function. --- src/disk_reader.cpp | 2 +- src/udp_capture.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 049b40c19..2cffee30d 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -119,7 +119,7 @@ class BFdiskreader_tbn_impl : virtual public BFdatacapture_impl { if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, - _chan0, + pkt->tuning, _nsrc, hdr, hdr_size); diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index 27541f5fd..12e96abb0 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -277,7 +277,7 @@ class BFudpcapture_tbn_impl : virtual public BFdatacapture_impl { if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, - _chan0, + pkt->tuning, _nsrc, hdr, hdr_size); From 07801b3a35950c3dce1261b9ebb7b0fcfcb05893 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 23 May 2019 15:00:41 -0600 Subject: [PATCH 012/424] Added a catch (and a new return code) to data_capture so that EOF conditions can be deal with more appropriately. --- src/data_capture.cpp | 14 ++++++++++++++ src/data_capture.hpp | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/data_capture.cpp b/src/data_capture.cpp index f4244e78e..775aa9904 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -28,8 +28,14 @@ #include "data_capture.hpp" +#define BF_JAYCE_DEBUG 0 + +#if BF_JAYCE_DEBUG #define BF_PRINTD(stmt) \ std::cout << stmt << std::endl +#else // not BF_JAYCE_DEBUG +#define BF_PRINTD(stmt) +#endif #if BF_HWLOC_ENABLED int HardwareLocality::bind_memory_to_core(int core) { @@ -75,6 +81,8 @@ int DataCaptureThread::run(uint64_t seq_beg, ret = CAPTURE_TIMEOUT; // Timed out } else if( errno == EINTR ) { ret = CAPTURE_INTERRUPTED; // Interrupted by signal + } else if( pkt_size == 0 ) { + ret = CAPTURE_NO_DATA; } else { ret = CAPTURE_ERROR; // Socket error } @@ -153,6 +161,12 @@ BFdatacapture_status BFdatacapture_impl::recv() { return BF_CAPTURE_ERROR; } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { return BF_CAPTURE_INTERRUPTED; + } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { + if( _active ) { + return BF_CAPTURE_ENDED; + } else { + return BF_CAPTURE_NO_DATA; + } } const PacketStats* stats = (this->get_capture())->get_stats(); _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" diff --git a/src/data_capture.hpp b/src/data_capture.hpp index 8c4bf3c9d..ad529b21a 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -199,7 +199,8 @@ class DataCaptureThread : public BoundThread { CAPTURE_SUCCESS = 1 << 0, CAPTURE_TIMEOUT = 1 << 1, CAPTURE_INTERRUPTED = 1 << 2, - CAPTURE_ERROR = 1 << 3 + CAPTURE_NO_DATA = 1 << 3, + CAPTURE_ERROR = 1 << 4 }; DataCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) : BoundThread(core), _method(fd, pkt_size_max), _src_stats(nsrc), From e8b11df91fd20b6f67f662c36430242d199984eb Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 23 May 2019 15:18:03 -0600 Subject: [PATCH 013/424] Changed the UdpCapture and DiskReader's recv() method to return a normal Python int instead of a ctypes.c_int. --- python/bifrost/data_capture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index 667976a97..f636c6e2e 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -60,7 +60,7 @@ def __exit__(self, type, value, tb): def recv(self): status = _bf.BFdatacapture_status() _check(_bf.bfDataCaptureRecv(self.obj, status)) - return status + return status.value def flush(self): _check(_bf.bfDataCaptureFlush(self.obj)) def end(self): @@ -83,7 +83,7 @@ def __exit__(self, type, value, tb): def recv(self): status = _bf.BFdatacapture_status() _check(_bf.bfDataCaptureRecv(self.obj, status)) - return status + return status.value def flush(self): _check(_bf.bfDataCaptureFlush(self.obj)) def end(self): From 309a49bdd7eed241c770c82aa444f200ffc64a20 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 31 May 2019 14:12:59 -0600 Subject: [PATCH 014/424] Fixed a bug in the Python interface for UDPCapture. --- python/bifrost/data_capture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index f636c6e2e..f05ae122d 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -52,7 +52,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, self, _bf.bfUdpCaptureCreate, _bf.bfDataCaptureDestroy, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, - sequence_callback, core) + sequence_callback.obj, core) def __enter__(self): return self def __exit__(self, type, value, tb): From 79a8a129857c49e71cd802f990eb87e1bd23c801 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 10:15:50 -0600 Subject: [PATCH 015/424] A second approach to unifying the disk and network readers that feels a lot cleaner. --- src/data_capture.cpp | 48 +++---- src/data_capture.hpp | 283 ++++++++++++++++++++++++++++++++++----- src/disk_reader.cpp | 223 ++++--------------------------- src/udp_capture.cpp | 306 ++----------------------------------------- 4 files changed, 314 insertions(+), 546 deletions(-) diff --git a/src/data_capture.cpp b/src/data_capture.cpp index 775aa9904..013821040 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -39,19 +39,19 @@ #if BF_HWLOC_ENABLED int HardwareLocality::bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; } #endif // BF_HWLOC_ENABLED @@ -75,7 +75,7 @@ int DataCaptureThread::run(uint64_t seq_beg, while( true ) { if( !_have_pkt ) { uint8_t* pkt_ptr; - int pkt_size = (this->get_method())->recv_packet(&pkt_ptr); + int pkt_size = _method->recv_packet(&pkt_ptr); if( pkt_size <= 0 ) { if( errno == EAGAIN || errno == EWOULDBLOCK ) { ret = CAPTURE_TIMEOUT; // Timed out @@ -148,14 +148,14 @@ BFdatacapture_status BFdatacapture_impl::recv() { src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - int state = (this->get_capture())->run(_seq, - _nseq_per_buf, - _bufs.size(), - buf_ptrs, - ngood_bytes_ptrs, - src_ngood_bytes_ptrs, - this->get_decoder(), - this->get_processor()); + int state = _capture->run(_seq, + _nseq_per_buf, + _bufs.size(), + buf_ptrs, + ngood_bytes_ptrs, + src_ngood_bytes_ptrs, + _decoder, + _processor); BF_PRINTD("OUTSIDE"); if( state & DataCaptureThread::CAPTURE_ERROR ) { return BF_CAPTURE_ERROR; @@ -168,7 +168,7 @@ BFdatacapture_status BFdatacapture_impl::recv() { return BF_CAPTURE_NO_DATA; } } - const PacketStats* stats = (this->get_capture())->get_stats(); + const PacketStats* stats = _capture->get_stats(); _stat_log.update() << "ngood_bytes : " << _ngood_bytes << "\n" << "nmissing_bytes : " << _nmissing_bytes << "\n" << "ninvalid : " << stats->ninvalid << "\n" @@ -190,7 +190,7 @@ BFdatacapture_status BFdatacapture_impl::recv() { BF_PRINTD("ACTIVE: " << _active << " WAS ACTIVE: " << was_active); if( _active ) { BF_PRINTD("START"); - const PacketDesc* pkt = (this->get_capture())->get_last_packet(); + const PacketDesc* pkt = _capture->get_last_packet(); BF_PRINTD("PRE-CALL"); this->on_sequence_active(pkt); BF_PRINTD("POST-CALL"); diff --git a/src/data_capture.hpp b/src/data_capture.hpp index ad529b21a..8c48efa88 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -165,13 +165,16 @@ class BoundThread { class DataCaptureMethod { protected: int _fd; + size_t _pkt_size_max; AlignedBuffer _buf; public: DataCaptureMethod(int fd, size_t pkt_size_max=9000) - : _fd(fd), _buf(pkt_size_max) {} + : _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max) {} virtual int recv_packet(uint8_t** pkt_ptr, int flags=0) { return 0; } + virtual const char* get_name() { return "generic_capture"; } + inline const size_t get_max_size() {return _pkt_size_max; } }; struct PacketStats { @@ -185,15 +188,13 @@ struct PacketStats { class DataCaptureThread : public BoundThread { private: - DataCaptureMethod _method; + DataCaptureMethod* _method; PacketStats _stats; std::vector _src_stats; bool _have_pkt; PacketDesc _pkt; + int _core; - virtual DataCaptureMethod* get_method() { - return &_method; - } public: enum { CAPTURE_SUCCESS = 1 << 0, @@ -202,9 +203,9 @@ class DataCaptureThread : public BoundThread { CAPTURE_NO_DATA = 1 << 3, CAPTURE_ERROR = 1 << 4 }; - DataCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : BoundThread(core), _method(fd, pkt_size_max), _src_stats(nsrc), - _have_pkt(false) { + DataCaptureThread(DataCaptureMethod* method, int nsrc, int core=0) + : BoundThread(core), _method(method), _src_stats(nsrc), + _have_pkt(false), _core(core) { this->reset_stats(); } template @@ -216,6 +217,9 @@ class DataCaptureThread : public BoundThread { size_t* src_ngood_bytes[], PDC* decode, PPC* process); + inline const char* get_name() { return _method->get_name(); } + inline const size_t get_max_size() { return _method->get_max_size(); } + inline const int get_core() { return _core; } inline const PacketDesc* get_last_packet() const { return _have_pkt ? &_pkt : NULL; } @@ -270,9 +274,9 @@ class BFdatacapture_callback_impl { class BFdatacapture_impl { protected: std::string _name; - DataCaptureThread _capture; - PacketDecoder _decoder; - PacketProcessor _processor; + DataCaptureThread* _capture; + PacketDecoder* _decoder; + PacketProcessor* _processor; ProcLog _bind_log; ProcLog _out_log; ProcLog _size_log; @@ -305,15 +309,6 @@ class BFdatacapture_impl { size_t _ngood_bytes; size_t _nmissing_bytes; - virtual DataCaptureThread* get_capture() { - return &_capture; - } - virtual PacketDecoder* get_decoder() { - return &_decoder; - } - virtual PacketProcessor* get_processor() { - return &_processor; - } inline size_t bufsize(int payload_size=-1) { if( payload_size == -1 ) { payload_size = _payload_size; @@ -340,8 +335,8 @@ class BFdatacapture_impl { if( src_nmissing_bytes > src_ngood_bytes ) { // Zero-out this source's contribution to the buffer uint8_t* data = (uint8_t*)_bufs.front()->data(); - _processor.blank_out_source(data, src, _nsrc, - _nchan, _nseq_per_buf); + _processor->blank_out_source(data, src, _nsrc, + _nchan, _nseq_per_buf); } } _buf_src_ngood_bytes.pop(); @@ -371,16 +366,14 @@ class BFdatacapture_impl { virtual inline bool has_sequence_changed(const PacketDesc* pkt) { return false; } virtual void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} public: - inline BFdatacapture_impl(std::string name, - int fd, - BFring ring, + inline BFdatacapture_impl(DataCaptureThread* capture, + PacketDecoder* decoder, + PacketProcessor* processor, + BFring ring, int nsrc, - int src0, - int max_payload_size, int buffer_ntime, - int slot_ntime, - int core) - : _name(name), _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), + int slot_ntime) + : _name(capture->get_name()), _capture(capture), _decoder(decoder), _processor(processor), _bind_log(_name+"/bind"), _out_log(_name+"/out"), _size_log(_name+"/sizes"), @@ -391,14 +384,14 @@ class BFdatacapture_impl { _ring(ring), _oring(_ring), // TODO: Add reset method for stats _ngood_bytes(0), _nmissing_bytes(0) { - size_t contig_span = this->bufsize(max_payload_size); + size_t contig_span = this->bufsize(_capture->get_max_size()); // Note: 2 write bufs may be open for writing at one time size_t total_span = contig_span * 4; size_t nringlet_max = 1; _ring.resize(contig_span, total_span, nringlet_max); _bind_log.update("ncore : %i\n" "core0 : %i\n", - 1, core); + 1, _capture->get_core()); _out_log.update("nring : %i\n" "ring0 : %s\n", 1, _ring.name()); @@ -422,3 +415,229 @@ class BFdatacapture_impl { } BFdatacapture_status recv(); }; + +class BFdatacapture_chips_impl : public BFdatacapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFdatacapture_chips_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFdatacapture_chips_impl(DataCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFdatacapture_callback sequence_callback) + : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"type").c_str()), + _chan_log((std::string(capture->get_name())+"chans").c_str()), + _sequence_callback(sequence_callback->get_chips()) { + _decoder = new CHIPSDecoder(nsrc, src0); + _processor = new CHIPSProcessor(); + _type_log.update("type : %s\n", "chips"); + } +}; + +class BFdatacapture_tbn_impl : public BFdatacapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFdatacapture_tbn_sequence_callback _sequence_callback; + + BFoffset _time_tag; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest time_tag, tuning = " << pkt->time_tag << ", " << pkt->tuning << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->tuning != _chan0); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + //cout << "Sequence changed" << endl; + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + *time_tag, + pkt->tuning, + _nsrc, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _time_tag = pkt->time_tag; + _chan0 = pkt->tuning; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFdatacapture_tbn_impl(DataCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFdatacapture_callback sequence_callback) + : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"type").c_str()), + _chan_log((std::string(capture->get_name())+"chans").c_str()), + _sequence_callback(sequence_callback->get_tbn()) { + _decoder = new TBNDecoder(nsrc, src0); + _processor = new TBNProcessor(); + _type_log.update("type : %s\n", "tbn"); + } +}; + +class BFdatacapture_drx_impl : public BFdatacapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFdatacapture_drx_sequence_callback _sequence_callback; + + BFoffset _time_tag; + int _chan1; + uint8_t _tstate; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + + if( pkt->src / 2 == 0 ) { + if( pkt->tuning != _chan0 ) { + _tstate |= 1; + _chan0 = pkt->tuning; + } + } else { + if( pkt->tuning != _chan1 ) { + _tstate |= 2; + _chan1 = pkt->tuning; + } + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return ( (_tstate == 3 && _nsrc == 4) + || (_tstate != 0 && _nsrc == 2) ); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + *time_tag, + _chan0, + _chan1, + _nsrc, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _time_tag = pkt->time_tag; + _payload_size = pkt->payload_size; + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFdatacapture_drx_impl(DataCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFdatacapture_callback sequence_callback) + : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"type").c_str()), + _chan_log((std::string(capture->get_name())+"chans").c_str()), + _sequence_callback(sequence_callback->get_drx()), + _chan1(), _tstate(0) { + _decoder = new DRXDecoder(nsrc, src0); + _processor = new DRXProcessor(); + _type_log.update("type : %s\n", "drx"); + } +}; diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 2cffee30d..c2b610be9 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -54,7 +54,7 @@ using bifrost::ring::WriteSequence; #include #include -class DiskPacketReader : virtual public DataCaptureMethod { +class DiskPacketReader : public DataCaptureMethod { public: DiskPacketReader(int fd, size_t pkt_size_max=9000) : DataCaptureMethod(fd, pkt_size_max) {} @@ -62,197 +62,7 @@ class DiskPacketReader : virtual public DataCaptureMethod { *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); } -}; - -class DiskReaderThread : virtual public DataCaptureThread { - DiskPacketReader _method; - - DataCaptureMethod* get_method() { - return &_method; - } -public: - DiskReaderThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : DataCaptureThread(fd, nsrc, core, pkt_size_max), _method(fd, pkt_size_max) { - this->reset_stats(); - } -}; - -class BFdiskreader_tbn_impl : virtual public BFdatacapture_impl { - DiskReaderThread _capture; - TBNDecoder _decoder; - TBNProcessor _processor; - ProcLog _type_log; - ProcLog _chan_log; - - BFdatacapture_tbn_sequence_callback _sequence_callback; - - BFoffset _time_tag; - - inline DataCaptureThread* get_capture() { - return &_capture; - } - inline PacketDecoder* get_decoder() { - return &_decoder; - } - inline PacketProcessor* get_processor() { - return &_processor; - } - void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - _seq = round_nearest(pkt->seq, _nseq_per_buf); - this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); - } - void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest time_tag, tuning = " << pkt->time_tag << ", " << pkt->tuning << endl; - } - else { - //cout << "No latest packet" << endl; - } - } - inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->tuning != _chan0); - } - void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { - //cout << "Sequence changed" << endl; - *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - *time_tag = pkt->time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(*seq0, - *time_tag, - pkt->tuning, - _nsrc, - hdr, - hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - *time_tag = *seq0; - *hdr = NULL; - *hdr_size = 0; - } - - _time_tag = pkt->time_tag; - _chan0 = pkt->tuning; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - } -public: - inline BFdiskreader_tbn_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback, - int core) - : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, TBN_FRAME_SIZE, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core, TBN_FRAME_SIZE), _decoder(nsrc, src0), _processor(), - _type_log("disk_reader/type"), - _chan_log("disk_reader/chans"), - _sequence_callback(sequence_callback->get_tbn()) { - _type_log.update("type : %s\n", "tbn"); - } -}; - -class BFdiskreader_drx_impl : virtual public BFdatacapture_impl { - DiskReaderThread _capture; - DRXDecoder _decoder; - DRXProcessor _processor; - ProcLog _type_log; - ProcLog _chan_log; - - BFdatacapture_drx_sequence_callback _sequence_callback; - - BFoffset _time_tag; - int _chan1; - uint8_t _tstate; - - inline DataCaptureThread* get_capture() { - return &_capture; - } - inline PacketDecoder* get_decoder() { - return &_decoder; - } - inline PacketProcessor* get_processor() { - return &_processor; - } - void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - _seq = round_nearest(pkt->seq, _nseq_per_buf); - this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); - } - void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - } - else { - //cout << "No latest packet" << endl; - } - - if( pkt->src / 2 == 0 ) { - if( pkt->tuning != _chan0 ) { - _tstate |= 1; - _chan0 = pkt->tuning; - } - } else { - if( pkt->tuning != _chan1 ) { - _tstate |= 2; - _chan1 = pkt->tuning; - } - } - } - inline bool has_sequence_changed(const PacketDesc* pkt) { - return ( (_tstate == 3 && _nsrc == 4) - || (_tstate != 0 && _nsrc == 2) ); - } - void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { - *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - *time_tag = pkt->time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(*seq0, - *time_tag, - _chan0, - _chan1, - _nsrc, - hdr, - hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - *time_tag = *seq0; - *hdr = NULL; - *hdr_size = 0; - } - - _time_tag = pkt->time_tag; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "chan1 : " << _chan1 << "\n" - << "payload_size : " << _payload_size << "\n"; - } -public: - inline BFdiskreader_drx_impl(int fd, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback, - int core) - : BFdatacapture_impl("disk_reader", fd, ring, nsrc, src0, DRX_FRAME_SIZE, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core, DRX_FRAME_SIZE), _decoder(nsrc, src0), _processor(), - _type_log("disk_reader/type"), - _chan_log("disk_reader/chans"), - _sequence_callback(sequence_callback->get_drx()), - _chan1(), _tstate(0) { - _type_log.update("type : %s\n", "drx"); - } + inline const char* get_name() { return "disk_reader"; } }; BFstatus bfDiskReaderCreate(BFdatacapture* obj, @@ -266,15 +76,34 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, BFdatacapture_callback sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_tbn_impl(fd, ring, nsrc, src0, + + size_t max_payload_size = JUMBO_FRAME_SIZE; + if( std::string(format).substr(0, 6) == std::string("chips_") ) { + int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); + max_payload_size = sizeof(chips_hdr_type) + 32*nchan; + } else if( format == std::string("tbn") ) { + max_payload_size = TBN_FRAME_SIZE; + } else if( format == std::string("drx") ) { + max_payload_size = DRX_FRAME_SIZE; + } + + DiskPacketReader* method = new DiskPacketReader(fd, max_payload_size); + DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + + if( std::string(format).substr(0, 6) == std::string("chips_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, - sequence_callback, core), + sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdiskreader_drx_impl(fd, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, - sequence_callback, core), + sequence_callback), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index 12e96abb0..72907e10d 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -105,14 +105,12 @@ class VMAReceiver { #endif // BF_VMA_ENABLED class UDPPacketReceiver : public DataCaptureMethod { - int _fd; - AlignedBuffer _buf; #if BF_VMA_ENABLED VMAReceiver _vma; #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : DataCaptureMethod(fd, pkt_size_max), _fd(fd), _buf(pkt_size_max) + : DataCaptureMethod(fd, pkt_size_max) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -130,289 +128,7 @@ class UDPPacketReceiver : public DataCaptureMethod { } #endif } -}; - -class UDPCaptureThread : virtual public DataCaptureThread { - UDPPacketReceiver _method; - - DataCaptureMethod* get_method() { - return &_method; - } -public: - enum { - CAPTURE_SUCCESS = 1 << 0, - CAPTURE_TIMEOUT = 1 << 1, - CAPTURE_INTERRUPTED = 1 << 2, - CAPTURE_ERROR = 1 << 3 - }; - UDPCaptureThread(int fd, int nsrc, int core=0, size_t pkt_size_max=9000) - : DataCaptureThread(fd, nsrc, core, pkt_size_max), _method(fd, pkt_size_max) { - this->reset_stats(); - } -}; - -class BFudpcapture_chips_impl : virtual public BFdatacapture_impl { - UDPCaptureThread _capture; - CHIPSDecoder _decoder; - CHIPSProcessor _processor; - ProcLog _type_log; - ProcLog _chan_log; - - BFdatacapture_chips_sequence_callback _sequence_callback; - - inline DataCaptureThread* get_capture() { - return &_capture; - } - inline PacketDecoder* get_decoder() { - return &_decoder; - } - inline PacketProcessor* get_processor() { - return &_processor; - } - void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - // TODO: Might be safer to round to nearest here, but the current firmware - // always starts things ~3 seq's before the 1sec boundary anyway. - //seq = round_up(pkt->seq, _slot_ntime); - //*_seq = round_nearest(pkt->seq, _slot_ntime); - _seq = round_up(pkt->seq, _slot_ntime); - this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); - } - void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - } - else { - //cout << "No latest packet" << endl; - } - } - inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->chan0 != _chan0) \ - || (pkt->nchan != _nchan); - } - void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { - *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - if( _sequence_callback ) { - int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - *time_tag = *seq0; - *hdr = NULL; - *hdr_size = 0; - } - - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "nchan : " << _nchan << "\n" - << "payload_size : " << _payload_size << "\n"; - } -public: - inline BFudpcapture_chips_impl(int fd, - BFring ring, - int nsrc, - int src0, - int max_payload_size, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback, - int core) - : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), - _type_log("udp_capture/type"), - _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback->get_chips()) { - _type_log.update("type : %s\n", "chips"); - } -}; - -class BFudpcapture_tbn_impl : virtual public BFdatacapture_impl { - UDPCaptureThread _capture; - TBNDecoder _decoder; - TBNProcessor _processor; - ProcLog _type_log; - ProcLog _chan_log; - - BFdatacapture_tbn_sequence_callback _sequence_callback; - - BFoffset _time_tag; - - inline DataCaptureThread* get_capture() { - return &_capture; - } - inline PacketDecoder* get_decoder() { - return &_decoder; - } - inline PacketProcessor* get_processor() { - return &_processor; - } - void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - _seq = round_nearest(pkt->seq, _nseq_per_buf); - this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); - } - void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - } - else { - //cout << "No latest packet" << endl; - } - } - inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->tuning != _chan0); - } - void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { - *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - *time_tag = pkt->time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(*seq0, - *time_tag, - pkt->tuning, - _nsrc, - hdr, - hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - *time_tag = *seq0; - *hdr = NULL; - *hdr_size = 0; - } - - _time_tag = pkt->time_tag; - _chan0 = pkt->tuning; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "payload_size : " << _payload_size << "\n"; - } -public: - inline BFudpcapture_tbn_impl(int fd, - BFring ring, - int nsrc, - int src0, - int max_payload_size, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback, - int core) - : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), - _type_log("udp_capture/type"), - _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback->get_tbn()) { - _type_log.update("type : %s\n", "tbn"); - } -}; - -class BFudpcapture_drx_impl : virtual public BFdatacapture_impl { - UDPCaptureThread _capture; - DRXDecoder _decoder; - DRXProcessor _processor; - ProcLog _type_log; - ProcLog _chan_log; - - BFdatacapture_drx_sequence_callback _sequence_callback; - - BFoffset _time_tag; - int _chan1; - uint8_t _tstate; - - inline DataCaptureThread* get_capture() { - return &_capture; - } - inline PacketDecoder* get_decoder() { - return &_decoder; - } - inline PacketProcessor* get_processor() { - return &_processor; - } - void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - _seq = round_nearest(pkt->seq, _nseq_per_buf); - this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); - } - void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - } - else { - //cout << "No latest packet" << endl; - } - - if( pkt->src / 2 == 0 ) { - if( pkt->tuning != _chan0 ) { - _tstate |= 1; - _chan0 = pkt->tuning; - } - } else { - if( pkt->tuning != _chan1 ) { - _tstate |= 2; - _chan1 = pkt->tuning; - } - } - } - inline bool has_sequence_changed(const PacketDesc* pkt) { - return ( (_tstate == 3 && _nsrc == 4) - || (_tstate != 0 && _nsrc == 2) ); - } - void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { - *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - *time_tag = pkt->time_tag; - if( _sequence_callback ) { - int status = (*_sequence_callback)(*seq0, - *time_tag, - _chan0, - _chan1, - _nsrc, - hdr, - hdr_size); - if( status != 0 ) { - // TODO: What to do here? Needed? - throw std::runtime_error("BAD HEADER CALLBACK STATUS"); - } - } else { - // Simple default for easy testing - *time_tag = *seq0; - *hdr = NULL; - *hdr_size = 0; - } - - _time_tag = pkt->time_tag; - _payload_size = pkt->payload_size; - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "chan1 : " << _chan1 << "\n" - << "payload_size : " << _payload_size << "\n"; - } -public: - inline BFudpcapture_drx_impl(int fd, - BFring ring, - int nsrc, - int src0, - int max_payload_size, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback, - int core) - : BFdatacapture_impl("udp_capture", fd, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, core), - _capture(fd, nsrc, core), _decoder(nsrc, src0), _processor(), - _type_log("udp_capture/type"), - _chan_log("udp_capture/chans"), - _sequence_callback(sequence_callback->get_drx()), - _chan1(), _tstate(0) { - _type_log.update("type : %s\n", "drx"); - } + inline const char* get_name() { return "udp_capture"; } }; BFstatus bfUdpCaptureCreate(BFdatacapture* obj, @@ -427,20 +143,24 @@ BFstatus bfUdpCaptureCreate(BFdatacapture* obj, BFdatacapture_callback sequence_callback, int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); + + UDPPacketReceiver* method = new UDPPacketReceiver(fd, max_payload_size); + DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_chips_impl(fd, ring, nsrc, src0, max_payload_size, + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, - sequence_callback, core), + sequence_callback), *obj = 0); } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_tbn_impl(fd, ring, nsrc, src0, max_payload_size, + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, - sequence_callback, core), + sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFudpcapture_drx_impl(fd, ring, nsrc, src0, max_payload_size, + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, - sequence_callback, core), + sequence_callback), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; From 8a0af48e23b31a6b8261104e4c37205635ad6410 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 11:13:52 -0600 Subject: [PATCH 016/424] Added support for sniffer sockets to help support fly-by data capture a la PASI and LASI. --- python/bifrost/udp_socket.py | 8 ++ src/Socket.hpp | 210 ++++++++++++++++++++++++++++++++--- src/bifrost/udp_socket.h | 3 + 3 files changed, 204 insertions(+), 17 deletions(-) diff --git a/python/bifrost/udp_socket.py b/python/bifrost/udp_socket.py index 965acbd16..abe4595c2 100644 --- a/python/bifrost/udp_socket.py +++ b/python/bifrost/udp_socket.py @@ -34,6 +34,8 @@ def __init__(self): BifrostObject.__init__(self, _bf.bfUdpSocketCreate, _bf.bfUdpSocketDestroy) def bind(self, local_addr): _check( _bf.bfUdpSocketBind(self.obj, local_addr.obj) ) + def sniff(self, local_addr): + _check( _bf.bfUdpSocketSniff(self.obj, local_addr.obj) ) def connect(self, remote_addr): _check( _bf.bfUdpSocketConnect(self.obj, remote_addr.obj) ) def shutdown(self): @@ -51,3 +53,9 @@ def timeout(self): @timeout.setter def timeout(self, secs): _check( _bf.bfUdpSocketSetTimeout(self.obj, secs) ) + @property + def promisc(self): + return _get(_bf.bfUdpSocketGetPromiscuous, self.obj) + @promisc.setter + def promisc(self, state): + _check( _bf.bfUdpSocketSetPromiscuous(self.obj, state) ) diff --git a/src/Socket.hpp b/src/Socket.hpp index da145e898..4f615e98c 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -125,6 +125,8 @@ client.send/recv_block/packet(...); #include #include //#include +#include +#include class Socket { // Not copy-assignable @@ -187,6 +189,8 @@ class Socket { // Server initialisation inline void bind(sockaddr_storage local_address, int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); + inline void sniff(sockaddr_storage local_address, + int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); // Client initialisation inline void connect(sockaddr_storage remote_address); // Accept incoming SOCK_STREAM connection requests @@ -279,8 +283,11 @@ class Socket { timeval timeout = self->get_option(SO_RCVTIMEO); return timeout.tv_sec + timeout.tv_usec*1e-6; } + inline void set_promiscuous(int state); + inline int get_promiscuous(); + private: - inline void open(sa_family_t family); + inline void open(sa_family_t family, int protocol=0); inline void set_default_options(); inline void check_error(int retval, std::string what) { if( retval < 0 ) { @@ -308,6 +315,10 @@ class Socket { inline static int addr_from_interface(const char* ifname, sockaddr* address, sa_family_t family=AF_UNSPEC); + inline static int interface_from_addr(sockaddr* address, + char* ifname, + sa_family_t family=AF_UNSPEC); + int _fd; sock_type _type; sa_family_t _family; @@ -359,7 +370,7 @@ sockaddr_storage Socket::address(//const char* addrstr, } return sas; } - if( family == AF_UNIX || port < 0 ) { + if( family == AF_UNIX || port < 0) { // UNIX path saU->sun_family = AF_UNIX; std::strncpy(saU->sun_path, addrstr.c_str(), @@ -451,16 +462,65 @@ void Socket::bind(sockaddr_storage local_address, #endif check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), - "bind socket"); - if( _type == SOCK_STREAM ) { - check_error(::listen(_fd, max_conn_queue), - "set socket to listen"); - _mode = Socket::MODE_LISTENING; - } - else { - _mode = Socket::MODE_BOUND; + "bind socket"); + if( _type == SOCK_STREAM ) { + check_error(::listen(_fd, max_conn_queue), + "set socket to listen"); + _mode = Socket::MODE_LISTENING; + } + else { + _mode = Socket::MODE_BOUND; + } +} +void Socket::sniff(sockaddr_storage local_address, + int max_conn_queue) { + if( _mode != Socket::MODE_CLOSED ) { + throw Socket::Error("Socket is already open"); } + this->open(AF_PACKET, htons(ETH_P_IP)); + + // Allow binding multiple sockets to one port + // See here for more info: https://lwn.net/Articles/542629/ + // TODO: This must be done before calling ::bind, which is slightly + // awkward with how this method is set up, as the user has + // no way to do it themselves. However, doing it by default + // is probably not a bad idea anyway. +#ifdef SO_REUSEPORT + this->set_option(SO_REUSEPORT, 1); +#else + #warning "Kernel version does not support SO_REUSEPORT; multithreaded send/recv will not be possible" +#endif + struct ifreq ethreq; + memset(ðreq, 0, sizeof(ethreq)); + + // Find out which interface this address corresponds to + this->interface_from_addr((struct sockaddr*)(&local_address), + ethreq.ifr_name, + local_address.ss_family); + check_error(::ioctl(_fd, SIOCGIFINDEX, ðreq), + "find sniff interface index"); + + // Bind to that interface + sockaddr_storage sas; + memset(&sas, 0, sizeof(sas)); + sockaddr_ll* sll = reinterpret_cast(&sas); + sll->sll_family = AF_PACKET; + sll->sll_ifindex = ethreq.ifr_ifindex; + sll->sll_protocol = htons(ETH_P_IP); + check_error(::bind(_fd, (struct sockaddr*)(&sas), sizeof(sas)), + "bind sniff socket"); + + // Final check to make sure we are golden + if( _type == SOCK_STREAM ) { + throw Socket::Error("SOCK_STREAM is not supported with packet sniffing"); + } else { + _mode = Socket::MODE_BOUND; + } + + // Make the socket promiscuous + this->set_promiscuous(true); } + // TODO: Add timeout support? Bit of a pain to implement. void Socket::connect(sockaddr_storage remote_address) { bool can_reuse = (_fd != -1 && @@ -698,10 +758,10 @@ size_t Socket::send_packet(void const* header_buf, payload_buf, 0, &payload_size, packet_dest, timeout_secs); } -void Socket::open(sa_family_t family) { +void Socket::open(sa_family_t family, int protocol) { this->close(); _family = family; - check_error(_fd = ::socket(_family, _type, 0), + check_error(_fd = ::socket(_family, _type, protocol), "create socket"); this->set_default_options(); } @@ -739,6 +799,7 @@ sockaddr_storage Socket::get_local_address() /*const*/ { } void Socket::close() { if( _fd >= 0 ) { + this->set_promiscuous(false); ::close(_fd); _fd = -1; _family = AF_UNSPEC; @@ -777,15 +838,15 @@ int Socket::addr_from_interface(const char* ifname, } bool found = false; for( ifaddrs* ifa=ifaddr; ifa!=NULL; ifa=ifa->ifa_next ) { - if( std::strcmp(ifa->ifa_name, ifname) != 0 || + if( std::strcmp(ifa->ifa_name, ifname) != 0 || ifa->ifa_addr == NULL ) { continue; } sa_family_t ifa_family = ifa->ifa_addr->sa_family; - if( (family == AF_UNSPEC && (ifa_family == AF_INET || - ifa_family == AF_INET6)) || - ifa_family == family ) { - size_t addr_size = ((ifa_family == AF_INET) ? + if( (family == AF_UNSPEC && (ifa_family == AF_INET \ + || ifa_family == AF_INET6) \ + ) || ifa_family == family ) { + size_t addr_size = ((ifa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); ::memcpy(address, ifa->ifa_addr, addr_size); @@ -796,6 +857,121 @@ int Socket::addr_from_interface(const char* ifname, ::freeifaddrs(ifaddr); return found; } +int Socket::interface_from_addr(sockaddr* address, + char* ifname, + sa_family_t family) { + ifaddrs* ifaddr; + if( ::getifaddrs(&ifaddr) == -1 ) { + return 0; + } + bool found = false; + for( ifaddrs* ifa=ifaddr; ifa!=NULL; ifa=ifa->ifa_next ) { + if( ifa->ifa_name == NULL || + ifa->ifa_addr == NULL ) { + continue; + } + sa_family_t ifa_family = ifa->ifa_addr->sa_family; + if( (family == AF_UNSPEC && (ifa_family == AF_INET \ + || ifa_family == AF_INET6) \ + ) || ifa_family == family ) { + switch(ifa_family) { + case AF_INET: { + struct sockaddr_in* inaddr = (struct sockaddr_in*) ifa->ifa_addr; + struct sockaddr_in* inmask = (struct sockaddr_in*) ifa->ifa_netmask; + sockaddr_in* sa4 = reinterpret_cast(address); + + if( (inaddr->sin_addr.s_addr & inmask->sin_addr.s_addr) \ + == (sa4->sin_addr.s_addr & inmask->sin_addr.s_addr) ) { + found = true; + } + break; + } + case AF_INET6: { + struct sockaddr_in6* inaddr6 = (struct sockaddr_in6*) ifa->ifa_addr; + struct sockaddr_in6* inmask6 = (struct sockaddr_in6*) ifa->ifa_netmask; + sockaddr_in6* sa6 = reinterpret_cast(address); + + uint64_t lowerIA=0, upperIA=0, lowerIM=0, upperIM=0; + uint64_t lowerAA=0, upperAA=0; + for(int i=0; i<8; i++) { + lowerIA |= inaddr6->sin6_addr.s6_addr[i] << (8*i); + upperIA |= inaddr6->sin6_addr.s6_addr[8+i] << (8*i); + lowerIM |= inmask6->sin6_addr.s6_addr[i] << (8*i); + upperIM |= inmask6->sin6_addr.s6_addr[8+i] << (8*i); + + lowerAA |= sa6->sin6_addr.s6_addr[i] << (8*i); + upperAA |= sa6->sin6_addr.s6_addr[8+i] << (8*i); + } + + if( ((lowerIA & lowerIM) == (lowerAA & lowerIM)) \ + && ((upperIA & upperIM) == (upperAA & upperIM)) ) { + found = true; + } + break; + } + default: break; + } + if( found ) { + std::strcpy(ifname, ifa->ifa_name); + break; // Return first match + } + } + } + ::freeifaddrs(ifaddr); + return found; +} +void Socket::set_promiscuous(int state) { + sockaddr_storage addr = this->get_local_address(); + + struct ifreq ethreq; + memset(ðreq, 0, sizeof(ethreq)); + if( ((sockaddr*)(&addr))->sa_family == AF_PACKET ) { + sockaddr_ll* sll = reinterpret_cast(&addr); + ethreq.ifr_ifindex = sll->sll_ifindex; + check_error(::ioctl(_fd, SIOCGIFNAME, ðreq), + "find interface name"); + } else { + this->interface_from_addr((sockaddr*)&addr, ethreq.ifr_name, _family); + } + + check_error(ioctl(_fd, SIOCGIFFLAGS, ðreq), + "read interface setup"); + if( state && (ethreq.ifr_flags & IFF_PROMISC) ) { + // Oh good, it's already done + } else if ( state && !(ethreq.ifr_flags & IFF_PROMISC) ) { + ethreq.ifr_flags |= IFF_PROMISC; + check_error(ioctl(_fd, SIOCSIFFLAGS, ðreq), + "change interface setup"); + } else if ( !state && (ethreq.ifr_flags & IFF_PROMISC) ){ + ethreq.ifr_flags ^= IFF_PROMISC; + check_error(ioctl(_fd, SIOCSIFFLAGS, ðreq), + "change interface setup"); + } + +} +int Socket::get_promiscuous() { + sockaddr_storage addr = this->get_local_address(); + + struct ifreq ethreq; + memset(ðreq, 0, sizeof(ethreq)); + if( ((sockaddr*)(&addr))->sa_family == AF_PACKET ) { + sockaddr_ll* sll = reinterpret_cast(&addr); + ethreq.ifr_ifindex = sll->sll_ifindex; + check_error(::ioctl(_fd, SIOCGIFNAME, ðreq), + "find interface name"); + } else { + this->interface_from_addr((sockaddr*)&addr, ethreq.ifr_name, _family); + } + + check_error(ioctl(_fd, SIOCGIFFLAGS, ðreq), + "read interface setup"); + if( ethreq.ifr_flags & IFF_PROMISC ) { + return true; + } else { + return false; + } +} + #if __cplusplus >= 201103L void Socket::replace(Socket& s) { _fd = s._fd; s._fd = -1; diff --git a/src/bifrost/udp_socket.h b/src/bifrost/udp_socket.h index 80ff3d1d2..e773256cc 100644 --- a/src/bifrost/udp_socket.h +++ b/src/bifrost/udp_socket.h @@ -41,10 +41,13 @@ BFstatus bfUdpSocketCreate(BFudpsocket* obj); BFstatus bfUdpSocketDestroy(BFudpsocket obj); BFstatus bfUdpSocketConnect(BFudpsocket obj, BFaddress remote_addr); BFstatus bfUdpSocketBind( BFudpsocket obj, BFaddress local_addr); +BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr); BFstatus bfUdpSocketShutdown(BFudpsocket obj); // Unblocks recv in another thread BFstatus bfUdpSocketClose(BFudpsocket obj); BFstatus bfUdpSocketSetTimeout(BFudpsocket obj, double secs); BFstatus bfUdpSocketGetTimeout(BFudpsocket obj, double* secs); +BFstatus bfUdpSocketSetPromiscuous(BFudpsocket obj, int promisc); +BFstatus bfUdpSocketGetPromiscuous(BFudpsocket obj, int* promisc); BFstatus bfUdpSocketGetMTU(BFudpsocket obj, int* mtu); BFstatus bfUdpSocketGetFD(BFudpsocket obj, int* fd); From 6dd9e47bd319ee9bd80242c1dc42c47dd83a7082 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 11:15:11 -0600 Subject: [PATCH 017/424] Added the missing changes to udp_socket.cpp to that last commit. --- src/udp_socket.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 4b6f34ff5..61391de98 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -55,6 +55,11 @@ BFstatus bfUdpSocketBind( BFudpsocket obj, BFaddress local_addr) { BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); BF_TRY_RETURN(obj->bind(*(sockaddr_storage*)local_addr)); } +BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); + BF_TRY_RETURN(obj->sniff(*(sockaddr_storage*)local_addr)); +} BFstatus bfUdpSocketShutdown(BFudpsocket obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->shutdown()); @@ -85,6 +90,27 @@ BFstatus bfUdpSocketGetTimeout(BFudpsocket obj, double* secs) { //BF_TRY(*secs = obj->get_timeout(), // *secs = 0); } +BFstatus bfUdpSocketSetPromiscuous(BFudpsocket obj, int state) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->set_promiscuous(state)); +} +BFstatus bfUdpSocketGetPromiscuous(BFudpsocket obj, int* promisc) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(promisc, BF_STATUS_INVALID_POINTER); + // WAR for old Socket implem returning Socket::Error not BFexception + try { + *promisc = obj->get_promiscuous(); + } + catch( Socket::Error ) { + *promisc = 0; + return BF_STATUS_INVALID_STATE; + } + catch(...) { + *promisc = 0; + return BF_STATUS_INTERNAL_ERROR; + } + return BF_STATUS_SUCCESS; +} BFstatus bfUdpSocketGetMTU(BFudpsocket obj, int* mtu) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_ASSERT(mtu, BF_STATUS_INVALID_POINTER); From 568906a1cec8641399a784e4739f44fb73b201d6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 11:19:30 -0600 Subject: [PATCH 018/424] Added a new sniffer class for data capture a la PASI and LASI. --- src/Makefile | 1 + src/bifrost/udp_sniffer.h | 55 ++++++++++++ src/udp_sniffer.cpp | 171 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 src/bifrost/udp_sniffer.h create mode 100644 src/udp_sniffer.cpp diff --git a/src/Makefile b/src/Makefile index 43d1cee35..ff6cfa7ff 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,6 +16,7 @@ LIBBIFROST_OBJS = \ data_capture.o \ udp_socket.o \ udp_capture.o \ + udp_sniffer.o \ udp_transmit.o \ disk_reader.o \ unpack.o \ diff --git a/src/bifrost/udp_sniffer.h b/src/bifrost/udp_sniffer.h new file mode 100644 index 000000000..b2f62ff2a --- /dev/null +++ b/src/bifrost/udp_sniffer.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_UDP_SNIFFER_H_INCLUDE_GUARD_ +#define BF_UDP_SNIFFER_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +BFstatus bfUdpSnifferCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdatacapture_callback sequence_callback, + int core); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_UDP_SNIFFER_H_INCLUDE_GUARD_ diff --git a/src/udp_sniffer.cpp b/src/udp_sniffer.cpp new file mode 100644 index 000000000..511344864 --- /dev/null +++ b/src/udp_sniffer.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include +#include +using bifrost::ring::RingWrapper; +using bifrost::ring::RingWriter; +using bifrost::ring::WriteSpan; +using bifrost::ring::WriteSequence; +#include "proclog.hpp" +#include "formats/formats.hpp" +#include "data_capture.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include +#include + +// TODO: The VMA API is returning unaligned buffers, which prevents use of SSE +#ifndef BF_VMA_ENABLED +#define BF_VMA_ENABLED 0 +//#define BF_VMA_ENABLED 1 +#endif + +#if BF_VMA_ENABLED +#include +class VMAReceiver { + int _fd; + vma_api_t* _api; + vma_packet_t* _pkt; + inline void clean_cache() { + if( _pkt ) { + _api->free_packets(_fd, _pkt, 1); + _pkt = 0; + } + } +public: + VMAReceiver(int fd) + : _fd(fd), _api(vma_get_api()), _pkt(0) {} + VMAReceiver(VMAReceiver const& other) + : _fd(other._fd), _api(other._api), _pkt(0) {} + VMAReceiver& operator=(VMAReceiver const& other) { + if( &other != this ) { + this->clean_cache(); + _fd = other._fd; + _api = other._api; + } + return *this; + } + ~VMAReceiver() { this->clean_cache(); } + inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { + this->clean_cache(); + int ret = _api->recvfrom_zcopy(_fd, buf, bufsize, &flags, 0, 0); + if( ret < 0 ) { + return ret; + } + if( flags & MSG_VMA_ZCOPY ) { + _pkt = &((vma_packets_t*)buf)->pkts[0]; + *pkt_ptr = (uint8_t*)_pkt->iov[0].iov_base; + } else { + *pkt_ptr = buf; + } + return ret; + } + inline operator bool() const { return _api != NULL; } +}; +#endif // BF_VMA_ENABLED + +class UDPPacketSniffer : public DataCaptureMethod { +#if BF_VMA_ENABLED + VMAReceiver _vma; +#endif +public: + UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : DataCaptureMethod(fd, pkt_size_max) +#if BF_VMA_ENABLED + , _vma(fd) +#endif + {} + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { +#if BF_VMA_ENABLED + if( _vma ) { + *pkt_ptr = 0; + int rc = _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags) - 28; + *pkt_ptr = *(pkt_ptr + 28); + return rc; + } else { +#endif + *pkt_ptr = &_buf[28]; // Offset for the IP+UDP headers + return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0) - 28; +#if BF_VMA_ENABLED + } +#endif + } + inline const char* get_name() { return "udp_sniffer"; } +}; + +BFstatus bfUdpSnifferCreate(BFdatacapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFdatacapture_callback sequence_callback, + int core) { + BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); + + UDPPacketSniffer* method = new UDPPacketSniffer(fd, max_payload_size); + DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + + if( format == std::string("chips") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( format == std::string("drx") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else { + return BF_STATUS_UNSUPPORTED; + } +} + From 6ea5804f188cd69c6dd33ffba7ba65d091eb96f2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 11:20:07 -0600 Subject: [PATCH 019/424] Updated the Python module for the new sniffer class. --- python/bifrost/data_capture.py | 23 +++++++++++++++++++++++ tools/like_bmon.py | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index f05ae122d..81f753978 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -66,6 +66,29 @@ def flush(self): def end(self): _check(_bf.bfDataCaptureEnd(self.obj)) +class UDPSniffer(BifrostObject): + def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpSnifferCreate, _bf.bfDataCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.end() + def recv(self): + status = _bf.BFdatacapture_status() + _check(_bf.bfDataCaptureRecv(self.obj, status)) + return status.value + def flush(self): + _check(_bf.bfDataCaptureFlush(self.obj)) + def end(self): + _check(_bf.bfDataCaptureEnd(self.obj)) + class DiskReader(BifrostObject): def __init__(self, fmt, fh, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core=None): diff --git a/tools/like_bmon.py b/tools/like_bmon.py index e5f22e588..dfc087ad1 100755 --- a/tools/like_bmon.py +++ b/tools/like_bmon.py @@ -158,7 +158,7 @@ def _getStatistics(blockList, prevList): # Loop over the blocks to find udp_capture and udp_transmit blocks output = {'updated': datetime.now()} for block in blockList: - if block.find('udp_capture') != -1: + if block.find('udp_capture') != -1 or block.find('udp_sniffer') != -1: ## udp_capture is RX good = True type = 'rx' From 7a77c4bb2be184a91fa7404de7b78bb937e929bc Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 5 Jun 2019 14:24:06 -0600 Subject: [PATCH 020/424] I'm not sure why changing this fixes my segault when HWLOC is enabled. I don't know why I was getting a segfault to start with. --- src/data_capture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_capture.cpp b/src/data_capture.cpp index 013821040..79345e850 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -44,7 +44,7 @@ int HardwareLocality::bind_memory_to_core(int core) { int ret = 0; if( 0 <= core && core < ncore ) { hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; From 9a2879ddb5b61657265bd74b5f6b835661ca0bf2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 25 Jun 2019 14:18:08 -0600 Subject: [PATCH 021/424] Initial work on adding support for COR data from LWA-SV. --- python/bifrost/data_capture.py | 3 + src/bifrost/data_capture.h | 3 + src/data_capture.cpp | 6 ++ src/data_capture.hpp | 132 +++++++++++++++++++++++----- src/disk_reader.cpp | 10 ++- src/formats/cor.hpp | 154 +++++++++++++++++++++++++++++++++ src/formats/formats.hpp | 1 + src/udp_capture.cpp | 5 ++ src/udp_sniffer.cpp | 5 ++ 9 files changed, 295 insertions(+), 24 deletions(-) create mode 100644 src/formats/cor.hpp diff --git a/python/bifrost/data_capture.py b/python/bifrost/data_capture.py index 81f753978..6c4545903 100644 --- a/python/bifrost/data_capture.py +++ b/python/bifrost/data_capture.py @@ -36,6 +36,9 @@ def __init__(self): def set_chips(self, fnc): _check(_bf.bfDataCaptureCallbackSetCHIPS( self.obj, _bf.BFdatacapture_chips_sequence_callback(fnc))) + def set_cor(self, fnc): + _check(_bf.bfDataCaptureCallbackSetCOR( + self.obj, _bf.BFdatacapture_cor_sequence_callback(fnc))) def set_tbn(self, fnc): _check(_bf.bfDataCaptureCallbackSetTBN( self.obj, _bf.BFdatacapture_tbn_sequence_callback(fnc))) diff --git a/src/bifrost/data_capture.h b/src/bifrost/data_capture.h index 564e6624a..cb9fca0ab 100644 --- a/src/bifrost/data_capture.h +++ b/src/bifrost/data_capture.h @@ -55,6 +55,8 @@ BFstatus bfDataCaptureEnd(BFdatacapture obj); typedef int (*BFdatacapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); +typedef int (*BFdatacapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, + int, int, void const**, size_t*); typedef int (*BFdatacapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, void const**, size_t*); typedef int (*BFdatacapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, @@ -65,6 +67,7 @@ typedef struct BFdatacapture_callback_impl* BFdatacapture_callback; BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj); BFstatus bfDataCaptureCallbackDestroy(BFdatacapture_callback obj); BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback); +BFstatus bfDataCaptureCallbackSetCOR(BFdatacapture_callback obj, BFdatacapture_cor_sequence_callback callback); BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback); BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback); diff --git a/src/data_capture.cpp b/src/data_capture.cpp index 79345e850..690701f35 100644 --- a/src/data_capture.cpp +++ b/src/data_capture.cpp @@ -273,6 +273,12 @@ BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture return BF_STATUS_SUCCESS; } +BFstatus bfDataCaptureCallbackSetCOR(BFdatacapture_callback obj, BFdatacapture_cor_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_cor(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_tbn(callback); diff --git a/src/data_capture.hpp b/src/data_capture.hpp index 8c48efa88..c4cedd346 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -245,16 +245,23 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { class BFdatacapture_callback_impl { BFdatacapture_chips_sequence_callback _chips_callback; + BFdatacapture_cor_sequence_callback _cor_callback; BFdatacapture_tbn_sequence_callback _tbn_callback; BFdatacapture_drx_sequence_callback _drx_callback; public: BFdatacapture_callback_impl() - : _chips_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} + : _chips_callback(NULL), _cor_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} inline void set_chips(BFdatacapture_chips_sequence_callback callback) { - _chips_callback = callback; + _chips_callback = callback; } inline BFdatacapture_chips_sequence_callback get_chips() { - return _chips_callback; + return _chips_callback; + } + inline void set_cor(BFdatacapture_cor_sequence_callback callback) { + _cor_callback = callback; + } + inline BFdatacapture_cor_sequence_callback get_cor() { + return _cor_callback; } inline void set_tbn(BFdatacapture_tbn_sequence_callback callback) { _tbn_callback = callback; @@ -268,7 +275,6 @@ class BFdatacapture_callback_impl { inline BFdatacapture_drx_sequence_callback get_drx() { return _drx_callback; } - }; class BFdatacapture_impl { @@ -444,14 +450,18 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, - _nchan, - _nsrc, - time_tag, - hdr, - hdr_size); + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -463,9 +473,6 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { *hdr_size = 0; } - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; _chan_log.update() << "chan0 : " << _chan0 << "\n" << "nchan : " << _nchan << "\n" << "payload_size : " << _payload_size << "\n"; @@ -488,6 +495,83 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { } }; +class BFdatacapture_cor_impl : public BFdatacapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFdatacapture_cor_sequence_callback _sequence_callback; + + BFoffset _time_tag; + int _navg; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest time_tag, tuning = " << pkt->time_tag << ", " << pkt->tuning << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->tuning == 0) \ + && ((pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan) \ + || (pkt->decimation != _navg)); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _navg = pkt->decimation; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + *time_tag, + _chan0, + _nchan, + _navg, + _nsrc, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFdatacapture_cor_impl(DataCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFdatacapture_callback sequence_callback) + : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"type").c_str()), + _chan_log((std::string(capture->get_name())+"chans").c_str()), + _sequence_callback(sequence_callback->get_cor()) { + _decoder = new CORDecoder(nsrc, src0); + _processor = new CORProcessor(); + _type_log.update("type : %s\n", "cor"); + } +}; + class BFdatacapture_tbn_impl : public BFdatacapture_impl { ProcLog _type_log; ProcLog _chan_log; @@ -515,13 +599,17 @@ class BFdatacapture_tbn_impl : public BFdatacapture_impl { //cout << "Sequence changed" << endl; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; + _time_tag = pkt->time_tag; + _chan0 = pkt->tuning; + _payload_size = pkt->payload_size; + if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - *time_tag, - pkt->tuning, - _nsrc, - hdr, - hdr_size); + *time_tag, + pkt->tuning, + _nsrc, + hdr, + hdr_size); if( status != 0 ) { // TODO: What to do here? Needed? throw std::runtime_error("BAD HEADER CALLBACK STATUS"); @@ -533,9 +621,6 @@ class BFdatacapture_tbn_impl : public BFdatacapture_impl { *hdr_size = 0; } - _time_tag = pkt->time_tag; - _chan0 = pkt->tuning; - _payload_size = pkt->payload_size; _chan_log.update() << "chan0 : " << _chan0 << "\n" << "payload_size : " << _payload_size << "\n"; } @@ -598,6 +683,9 @@ class BFdatacapture_drx_impl : public BFdatacapture_impl { void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; + _time_tag = pkt->time_tag; + _payload_size = pkt->payload_size; + if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, @@ -617,8 +705,6 @@ class BFdatacapture_drx_impl : public BFdatacapture_impl { *hdr_size = 0; } - _time_tag = pkt->time_tag; - _payload_size = pkt->payload_size; _chan_log.update() << "chan0 : " << _chan0 << "\n" << "chan1 : " << _chan1 << "\n" << "payload_size : " << _payload_size << "\n"; diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index c2b610be9..63e0cfe1f 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -81,6 +81,9 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); max_payload_size = sizeof(chips_hdr_type) + 32*nchan; + } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { + int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); + max_payload_size = sizeof(cor_hdr_type) + (8*4*nchan); } else if( format == std::string("tbn") ) { max_payload_size = TBN_FRAME_SIZE; } else if( format == std::string("drx") ) { @@ -95,6 +98,11 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_cor_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else if( format == std::string("tbn") ) { BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, @@ -105,7 +113,7 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); - } else { + } else { return BF_STATUS_UNSUPPORTED; } } diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp new file mode 100644 index 000000000..86a7e2e20 --- /dev/null +++ b/src/formats/cor.hpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" +#include + +#pragma pack(1) +struct cor_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t second_count; + uint16_t first_chan; + uint16_t gain; + uint64_t time_tag; + uint32_t navg; + uint16_t stand0; + uint16_t stand1; +}; + +class CORDecoder : virtual public PacketDecoder { + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->sync == 0x5CDEC0DE && + pkt->src >= 0 && + pkt->src < _nsrc && + pkt->time_tag >= 0 && + pkt->chan0 >= 0); + } +public: + CORDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(cor_hdr_type) ) { + return false; + } + const cor_hdr_type* pkt_hdr = (cor_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(cor_hdr_type); + int pld_size = pkt_size - sizeof(cor_hdr_type); + // HACK + uint8_t nserver = 1;//(be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; + // HACK + uint8_t server = 1;//be32toh(pkt_hdr->frame_count_word) & 0xFF; + uint16_t stand0 = be16toh(pkt_hdr->stand0) - 1; + uint16_t stand1 = be16toh(pkt_hdr->stand1) - 1; + uint16_t nstand = (sqrt(8*_nsrc+1)-1)/2; + pkt->sync = pkt_hdr->sync_word; + pkt->time_tag = be64toh(pkt_hdr->time_tag); + pkt->decimation = be32toh(pkt_hdr->navg); + pkt->seq = pkt->time_tag / 196000000 / (pkt->decimation / 100); + pkt->nsrc = _nsrc; + pkt->src = stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0; + pkt->chan0 = be16toh(pkt_hdr->first_chan); + pkt->nchan = nserver * (pld_size/(8*4)); // Stores the total number of channels + pkt->tuning = (nserver << 8) | (server - 1); // Stores the number of servers and + // the server that sent this packet + pkt->gain = be16toh(pkt_hdr->gain); + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + /* + if( stand0 == 0 || (stand0 == 1 && stand1 < 2) ) { + std::cout << "nsrc: " << pkt->nsrc << std::endl; + std::cout << "stand0: " << stand0 << std::endl; + std::cout << "stand1: " << stand1 << std::endl; + std::cout << "src: " << pkt->src << std::endl; + std::cout << "chan0: " << pkt->chan0 << std::endl; + std::cout << "nchan: " << pld_size/32 << std::endl; + std::cout << "navg: " << pkt->decimation << std::endl; + std::cout << "tuning: " << pkt->tuning << std::endl; + std::cout << "valid: " << this->valid_packet(pkt) << std::endl; + } + */ + return this->valid_packet(pkt); + } +}; + +class CORProcessor : virtual public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef aligned256_type itype; // 32+32 * 4 pol. products + typedef aligned256_type otype; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + // Convinience + int bl = pkt->src; + //int nbl = pkt->nsrc; + int server = pkt->tuning & 0xFF; + int nserver = (pkt->tuning >> 8) & 0xFF; + int nchan = pkt->nchan/nserver; + + int chan = 0; + for( ; chan Date: Mon, 1 Jul 2019 10:24:01 -0600 Subject: [PATCH 022/424] Added a try...catch block around the call to disable promiscuous mode during a socket close. --- src/Socket.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Socket.hpp b/src/Socket.hpp index 4f615e98c..fba9edd15 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -799,7 +799,10 @@ sockaddr_storage Socket::get_local_address() /*const*/ { } void Socket::close() { if( _fd >= 0 ) { - this->set_promiscuous(false); + try { + this->set_promiscuous(false); + } + catch( Socket::Error ) {} ::close(_fd); _fd = -1; _family = AF_UNSPEC; From 1bd78e363223e456669f5c85e26199b6a54aaf8e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 2 Jul 2019 10:40:52 -0600 Subject: [PATCH 023/424] Even more work on the COR format. I think it really works now. --- src/data_capture.hpp | 9 ++++----- src/formats/cor.hpp | 36 ++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/data_capture.hpp b/src/data_capture.hpp index c4cedd346..c6c664484 100644 --- a/src/data_capture.hpp +++ b/src/data_capture.hpp @@ -517,10 +517,9 @@ class BFdatacapture_cor_impl : public BFdatacapture_impl { } } inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->tuning == 0) \ - && ((pkt->chan0 != _chan0) \ - || (pkt->nchan != _nchan) \ - || (pkt->decimation != _navg)); + return ((pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan) \ + || (pkt->decimation != _navg)); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); @@ -536,7 +535,7 @@ class BFdatacapture_cor_impl : public BFdatacapture_impl { _chan0, _nchan, _navg, - _nsrc, + _nsrc/((pkt->tuning >> 8) & 0xFF), hdr, hdr_size); if( status != 0 ) { diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 86a7e2e20..04bfc241f 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -48,7 +48,7 @@ class CORDecoder : virtual public PacketDecoder { inline bool valid_packet(const PacketDesc* pkt) const { return (pkt->sync == 0x5CDEC0DE && pkt->src >= 0 && - pkt->src < _nsrc && + pkt->src < pkt->nsrc && pkt->time_tag >= 0 && pkt->chan0 >= 0); } @@ -63,21 +63,22 @@ class CORDecoder : virtual public PacketDecoder { const cor_hdr_type* pkt_hdr = (cor_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(cor_hdr_type); int pld_size = pkt_size - sizeof(cor_hdr_type); - // HACK - uint8_t nserver = 1;//(be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; - // HACK - uint8_t server = 1;//be32toh(pkt_hdr->frame_count_word) & 0xFF; + uint8_t nserver = (be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; + uint8_t server = be32toh(pkt_hdr->frame_count_word) & 0xFF; + uint16_t nchan_pkt = (pld_size/(8*4)); uint16_t stand0 = be16toh(pkt_hdr->stand0) - 1; uint16_t stand1 = be16toh(pkt_hdr->stand1) - 1; - uint16_t nstand = (sqrt(8*_nsrc+1)-1)/2; + uint16_t nstand = (sqrt(8*_nsrc/nserver+1)-1)/2; pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag); pkt->decimation = be32toh(pkt_hdr->navg); pkt->seq = pkt->time_tag / 196000000 / (pkt->decimation / 100); pkt->nsrc = _nsrc; - pkt->src = stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0; - pkt->chan0 = be16toh(pkt_hdr->first_chan); - pkt->nchan = nserver * (pld_size/(8*4)); // Stores the total number of channels + pkt->src = (stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0)*nserver \ + + (server - 1); + pkt->chan0 = be16toh(pkt_hdr->first_chan) \ + - nchan_pkt * (server - 1); + pkt->nchan = nchan_pkt * nserver; // Stores the total number of channels pkt->tuning = (nserver << 8) | (server - 1); // Stores the number of servers and // the server that sent this packet pkt->gain = be16toh(pkt_hdr->gain); @@ -88,6 +89,7 @@ class CORDecoder : virtual public PacketDecoder { std::cout << "nsrc: " << pkt->nsrc << std::endl; std::cout << "stand0: " << stand0 << std::endl; std::cout << "stand1: " << stand1 << std::endl; + std::cout << "server: " << server << std::endl; std::cout << "src: " << pkt->src << std::endl; std::cout << "chan0: " << pkt->chan0 << std::endl; std::cout << "nchan: " << pld_size/32 << std::endl; @@ -126,29 +128,27 @@ class CORProcessor : virtual public PacketProcessor { itype const* __restrict__ in = (itype const*)pkt->payload_ptr; otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; - // Convinience - int bl = pkt->src; - //int nbl = pkt->nsrc; - int server = pkt->tuning & 0xFF; + // Convenience + int bl_server = pkt->src; int nserver = (pkt->tuning >> 8) & 0xFF; int nchan = pkt->nchan/nserver; int chan = 0; - for( ; chan Date: Wed, 3 Jul 2019 10:45:44 -0600 Subject: [PATCH 024/424] Removed data_capture to packet_capture to make it a little more clear what it deals with. --- python/bifrost/{data_capture.py => packet_capture.py} | 0 src/Makefile | 8 +++++--- src/bifrost/disk_reader.h | 2 +- src/bifrost/{data_capture.h => packet_capture.h} | 6 +++--- src/bifrost/udp_capture.h | 2 +- src/bifrost/udp_sniffer.h | 2 +- src/disk_reader.cpp | 5 ++--- src/{data_capture.cpp => packet_capture.cpp} | 2 +- src/{data_capture.hpp => packet_capture.hpp} | 2 +- src/udp_capture.cpp | 4 ++-- src/udp_sniffer.cpp | 4 ++-- 11 files changed, 19 insertions(+), 18 deletions(-) rename python/bifrost/{data_capture.py => packet_capture.py} (100%) rename src/bifrost/{data_capture.h => packet_capture.h} (96%) rename src/{data_capture.cpp => packet_capture.cpp} (99%) rename src/{data_capture.hpp => packet_capture.hpp} (99%) diff --git a/python/bifrost/data_capture.py b/python/bifrost/packet_capture.py similarity index 100% rename from python/bifrost/data_capture.py rename to python/bifrost/packet_capture.py diff --git a/src/Makefile b/src/Makefile index ff6cfa7ff..ebedfcec1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,12 +13,12 @@ LIBBIFROST_OBJS = \ ring_impl.o \ array.o \ address.o \ - data_capture.o \ udp_socket.o \ + packet_capture.o \ + disk_reader.o \ udp_capture.o \ udp_sniffer.o \ udp_transmit.o \ - disk_reader.o \ unpack.o \ quantize.o \ proclog.o @@ -36,7 +36,9 @@ ifndef NOCUDA reduce.o \ fir.o \ guantize.o \ - gunpack.o + gunpack.o \ + romein.o \ + orville.o endif JIT_SOURCES ?= \ diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index 3c551799a..e790d21b0 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -33,7 +33,7 @@ extern "C" { #endif -#include +#include #include BFstatus bfDiskReaderCreate(BFdatacapture* obj, diff --git a/src/bifrost/data_capture.h b/src/bifrost/packet_capture.h similarity index 96% rename from src/bifrost/data_capture.h rename to src/bifrost/packet_capture.h index cb9fca0ab..e8a31c509 100644 --- a/src/bifrost/data_capture.h +++ b/src/bifrost/packet_capture.h @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BF_DATA_CAPTURE_H_INCLUDE_GUARD_ -#define BF_DATA_CAPTURE_H_INCLUDE_GUARD_ +#ifndef BF_PACKET_CAPTURE_H_INCLUDE_GUARD_ +#define BF_PACKET_CAPTURE_H_INCLUDE_GUARD_ #ifdef __cplusplus extern "C" { @@ -75,4 +75,4 @@ BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_d } // extern "C" #endif -#endif // BF_DATA_CAPTURE_H_INCLUDE_GUARD_ +#endif // BF_PACKET_CAPTURE_H_INCLUDE_GUARD_ diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index 83249101d..767a51541 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -33,7 +33,7 @@ extern "C" { #endif -#include +#include #include BFstatus bfUdpCaptureCreate(BFdatacapture* obj, diff --git a/src/bifrost/udp_sniffer.h b/src/bifrost/udp_sniffer.h index b2f62ff2a..5a88d8744 100644 --- a/src/bifrost/udp_sniffer.h +++ b/src/bifrost/udp_sniffer.h @@ -33,7 +33,7 @@ extern "C" { #endif -#include +#include #include BFstatus bfUdpSnifferCreate(BFdatacapture* obj, diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 63e0cfe1f..8fa92a54a 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -27,7 +27,7 @@ */ #include "assert.hpp" -#include +#include #include #include #include @@ -37,7 +37,7 @@ using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" #include "formats/formats.hpp" -#include "data_capture.hpp" +#include "packet_capture.hpp" #include // For ntohs #include // For recvfrom @@ -117,4 +117,3 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, return BF_STATUS_UNSUPPORTED; } } - diff --git a/src/data_capture.cpp b/src/packet_capture.cpp similarity index 99% rename from src/data_capture.cpp rename to src/packet_capture.cpp index 690701f35..9653459f5 100644 --- a/src/data_capture.cpp +++ b/src/packet_capture.cpp @@ -26,7 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "data_capture.hpp" +#include "packet_capture.hpp" #define BF_JAYCE_DEBUG 0 diff --git a/src/data_capture.hpp b/src/packet_capture.hpp similarity index 99% rename from src/data_capture.hpp rename to src/packet_capture.hpp index c6c664484..905192119 100644 --- a/src/data_capture.hpp +++ b/src/packet_capture.hpp @@ -29,7 +29,7 @@ #pragma once #include "assert.hpp" -#include +#include #include #include using bifrost::ring::RingWrapper; diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index e08f4b58e..652f627eb 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -27,7 +27,7 @@ */ #include "assert.hpp" -#include +#include #include #include #include @@ -37,7 +37,7 @@ using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" #include "formats/formats.hpp" -#include "data_capture.hpp" +#include "packet_capture.hpp" #include // For ntohs #include // For recvfrom diff --git a/src/udp_sniffer.cpp b/src/udp_sniffer.cpp index d1a396986..03485d551 100644 --- a/src/udp_sniffer.cpp +++ b/src/udp_sniffer.cpp @@ -27,7 +27,7 @@ */ #include "assert.hpp" -#include +#include #include #include #include @@ -37,7 +37,7 @@ using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" #include "formats/formats.hpp" -#include "data_capture.hpp" +#include "packet_capture.hpp" #include // For ntohs #include // For recvfrom From 40a6d3b989b02c2c9918ac5ccee40a6d1b2c3a99 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 10:47:00 -0600 Subject: [PATCH 025/424] Added in a couple of missing '/'s to the ProcLog entries in packet_capture.hpp. --- src/packet_capture.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 905192119..71b2a729f 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -486,8 +486,8 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { int slot_ntime, BFdatacapture_callback sequence_callback) : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), - _type_log((std::string(capture->get_name())+"type").c_str()), - _chan_log((std::string(capture->get_name())+"chans").c_str()), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_chips()) { _decoder = new CHIPSDecoder(nsrc, src0); _processor = new CHIPSProcessor(); @@ -562,8 +562,8 @@ class BFdatacapture_cor_impl : public BFdatacapture_impl { int slot_ntime, BFdatacapture_callback sequence_callback) : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), - _type_log((std::string(capture->get_name())+"type").c_str()), - _chan_log((std::string(capture->get_name())+"chans").c_str()), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_cor()) { _decoder = new CORDecoder(nsrc, src0); _processor = new CORProcessor(); @@ -632,8 +632,8 @@ class BFdatacapture_tbn_impl : public BFdatacapture_impl { int slot_ntime, BFdatacapture_callback sequence_callback) : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), - _type_log((std::string(capture->get_name())+"type").c_str()), - _chan_log((std::string(capture->get_name())+"chans").c_str()), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_tbn()) { _decoder = new TBNDecoder(nsrc, src0); _processor = new TBNProcessor(); @@ -717,8 +717,8 @@ class BFdatacapture_drx_impl : public BFdatacapture_impl { int slot_ntime, BFdatacapture_callback sequence_callback) : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), - _type_log((std::string(capture->get_name())+"type").c_str()), - _chan_log((std::string(capture->get_name())+"chans").c_str()), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_drx()), _chan1(), _tstate(0) { _decoder = new DRXDecoder(nsrc, src0); From c6ffa69bc37eb92675a5c7b6ca9519843dc370a4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 11:07:21 -0600 Subject: [PATCH 026/424] More cleanup of the data_capture -> packet_capture conversion. --- python/bifrost/packet_capture.py | 50 +++++----- src/bifrost/disk_reader.h | 22 ++--- src/bifrost/packet_capture.h | 51 +++++----- src/bifrost/udp_capture.h | 22 ++--- src/bifrost/udp_sniffer.h | 22 ++--- src/disk_reader.cpp | 34 +++---- src/packet_capture.cpp | 58 +++++------ src/packet_capture.hpp | 162 +++++++++++++++---------------- src/udp_capture.cpp | 36 +++---- src/udp_sniffer.cpp | 36 +++---- 10 files changed, 251 insertions(+), 242 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 6c4545903..58dbfa619 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -29,22 +29,22 @@ from libbifrost import _bf, _check, _get, BifrostObject -class DataCaptureCallback(BifrostObject): +class PacketCaptureCallback(BifrostObject): def __init__(self): BifrostObject.__init__( - self, _bf.bfDataCaptureCallbackCreate, _bf.bfDataCaptureCallbackDestroy) + self, _bf.bfPacketCaptureCallbackCreate, _bf.bfPacketCaptureCallbackDestroy) def set_chips(self, fnc): - _check(_bf.bfDataCaptureCallbackSetCHIPS( - self.obj, _bf.BFdatacapture_chips_sequence_callback(fnc))) + _check(_bf.bfPacketCaptureCallbackSetCHIPS( + self.obj, _bf.BFpacketcapture_chips_sequence_callback(fnc))) def set_cor(self, fnc): - _check(_bf.bfDataCaptureCallbackSetCOR( - self.obj, _bf.BFdatacapture_cor_sequence_callback(fnc))) + _check(_bf.bfPacketCaptureCallbackSetCOR( + self.obj, _bf.BFpacketcapture_cor_sequence_callback(fnc))) def set_tbn(self, fnc): - _check(_bf.bfDataCaptureCallbackSetTBN( - self.obj, _bf.BFdatacapture_tbn_sequence_callback(fnc))) + _check(_bf.bfPacketCaptureCallbackSetTBN( + self.obj, _bf.BFpacketcapture_tbn_sequence_callback(fnc))) def set_drx(self, fnc): - _check(_bf.bfDataCaptureCallbackSetDRX( - self.obj, _bf.BFdatacapture_drx_sequence_callback(fnc))) + _check(_bf.bfPacketCaptureCallbackSetDRX( + self.obj, _bf.BFpacketcapture_drx_sequence_callback(fnc))) class UDPCapture(BifrostObject): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, @@ -52,7 +52,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfDataCaptureDestroy, + self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) @@ -61,13 +61,13 @@ def __enter__(self): def __exit__(self, type, value, tb): self.end() def recv(self): - status = _bf.BFdatacapture_status() - _check(_bf.bfDataCaptureRecv(self.obj, status)) + status = _bf.BFpacketcapture_status() + _check(_bf.bfPacketCaptureRecv(self.obj, status)) return status.value def flush(self): - _check(_bf.bfDataCaptureFlush(self.obj)) + _check(_bf.bfPacketCaptureFlush(self.obj)) def end(self): - _check(_bf.bfDataCaptureEnd(self.obj)) + _check(_bf.bfPacketCaptureEnd(self.obj)) class UDPSniffer(BifrostObject): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, @@ -75,7 +75,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfUdpSnifferCreate, _bf.bfDataCaptureDestroy, + self, _bf.bfUdpSnifferCreate, _bf.bfPacketCaptureDestroy, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) @@ -84,13 +84,13 @@ def __enter__(self): def __exit__(self, type, value, tb): self.end() def recv(self): - status = _bf.BFdatacapture_status() - _check(_bf.bfDataCaptureRecv(self.obj, status)) + status = _bf.BFpacketcapture_status() + _check(_bf.bfPacketCaptureRecv(self.obj, status)) return status.value def flush(self): - _check(_bf.bfDataCaptureFlush(self.obj)) + _check(_bf.bfPacketCaptureFlush(self.obj)) def end(self): - _check(_bf.bfDataCaptureEnd(self.obj)) + _check(_bf.bfPacketCaptureEnd(self.obj)) class DiskReader(BifrostObject): def __init__(self, fmt, fh, ring, nsrc, src0, @@ -98,7 +98,7 @@ def __init__(self, fmt, fh, ring, nsrc, src0, if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfDiskReaderCreate, _bf.bfDataCaptureDestroy, + self, _bf.bfDiskReaderCreate, _bf.bfPacketCaptureDestroy, fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback.obj, core) @@ -107,10 +107,10 @@ def __enter__(self): def __exit__(self, type, value, tb): self.end() def recv(self): - status = _bf.BFdatacapture_status() - _check(_bf.bfDataCaptureRecv(self.obj, status)) + status = _bf.BFpacketcapture_status() + _check(_bf.bfPacketCaptureRecv(self.obj, status)) return status.value def flush(self): - _check(_bf.bfDataCaptureFlush(self.obj)) + _check(_bf.bfPacketCaptureFlush(self.obj)) def end(self): - _check(_bf.bfDataCaptureEnd(self.obj)) + _check(_bf.bfPacketCaptureEnd(self.obj)) diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h index e790d21b0..0b9339e01 100644 --- a/src/bifrost/disk_reader.h +++ b/src/bifrost/disk_reader.h @@ -32,20 +32,20 @@ #ifdef __cplusplus extern "C" { #endif - + #include #include -BFstatus bfDiskReaderCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core); +BFstatus bfDiskReaderCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); #ifdef __cplusplus } // extern "C" diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index e8a31c509..1d8bbde56 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -35,9 +35,9 @@ extern "C" { #include -typedef struct BFdatacapture_impl* BFdatacapture; +typedef struct BFpacketcapture_impl* BFpacketcapture; -typedef enum BFdatacapture_status_ { +typedef enum BFpacketcapture_status_ { BF_CAPTURE_STARTED, BF_CAPTURE_ENDED, BF_CAPTURE_CONTINUED, @@ -45,31 +45,36 @@ typedef enum BFdatacapture_status_ { BF_CAPTURE_NO_DATA, BF_CAPTURE_INTERRUPTED, BF_CAPTURE_ERROR -} BFdatacapture_status; +} BFpacketcapture_status; -BFstatus bfDataCaptureDestroy(BFdatacapture obj); -BFstatus bfDataCaptureRecv(BFdatacapture obj, BFdatacapture_status* result); -BFstatus bfDataCaptureFlush(BFdatacapture obj); -BFstatus bfDataCaptureEnd(BFdatacapture obj); -// TODO: bfDataCaptureGetXX +BFstatus bfPacketCaptureDestroy(BFpacketcapture obj); +BFstatus bfPacketCaptureRecv(BFpacketcapture obj, + BFpacketcapture_status* result); +BFstatus bfPacketCaptureFlush(BFpacketcapture obj); +BFstatus bfPacketCaptureEnd(BFpacketcapture obj); +// TODO: bfPacketCaptureGetXX -typedef int (*BFdatacapture_chips_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); -typedef int (*BFdatacapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, - int, int, void const**, size_t*); -typedef int (*BFdatacapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, - void const**, size_t*); -typedef int (*BFdatacapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, - void const**, size_t*); +typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); +typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, + int, int, void const**, size_t*); +typedef int (*BFpacketcapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, + void const**, size_t*); +typedef int (*BFpacketcapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, + void const**, size_t*); -typedef struct BFdatacapture_callback_impl* BFdatacapture_callback; +typedef struct BFpacketcapture_callback_impl* BFpacketcapture_callback; -BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj); -BFstatus bfDataCaptureCallbackDestroy(BFdatacapture_callback obj); -BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback); -BFstatus bfDataCaptureCallbackSetCOR(BFdatacapture_callback obj, BFdatacapture_cor_sequence_callback callback); -BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback); -BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback); +BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj); +BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj); +BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, + BFpacketcapture_chips_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, + BFpacketcapture_cor_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, + BFpacketcapture_tbn_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, + BFpacketcapture_drx_sequence_callback callback); #ifdef __cplusplus } // extern "C" diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h index 767a51541..b3f55d14f 100644 --- a/src/bifrost/udp_capture.h +++ b/src/bifrost/udp_capture.h @@ -36,17 +36,17 @@ extern "C" { #include #include -BFstatus bfUdpCaptureCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core); +BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); #ifdef __cplusplus } // extern "C" diff --git a/src/bifrost/udp_sniffer.h b/src/bifrost/udp_sniffer.h index 5a88d8744..457a5a514 100644 --- a/src/bifrost/udp_sniffer.h +++ b/src/bifrost/udp_sniffer.h @@ -36,17 +36,17 @@ extern "C" { #include #include -BFstatus bfUdpSnifferCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core); +BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); #ifdef __cplusplus } // extern "C" diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp index 8fa92a54a..87d6c62e4 100644 --- a/src/disk_reader.cpp +++ b/src/disk_reader.cpp @@ -54,10 +54,10 @@ using bifrost::ring::WriteSequence; #include #include -class DiskPacketReader : public DataCaptureMethod { +class DiskPacketReader : public PacketCaptureMethod { public: DiskPacketReader(int fd, size_t pkt_size_max=9000) - : DataCaptureMethod(fd, pkt_size_max) {} + : PacketCaptureMethod(fd, pkt_size_max) {} int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); @@ -65,16 +65,16 @@ class DiskPacketReader : public DataCaptureMethod { inline const char* get_name() { return "disk_reader"; } }; -BFstatus bfDiskReaderCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core) { +BFstatus bfDiskReaderCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); size_t max_payload_size = JUMBO_FRAME_SIZE; @@ -91,25 +91,25 @@ BFstatus bfDiskReaderCreate(BFdatacapture* obj, } DiskPacketReader* method = new DiskPacketReader(fd, max_payload_size); - DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); if( std::string(format).substr(0, 6) == std::string("chips_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_cor_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 9653459f5..93ef97fb7 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -61,14 +61,14 @@ int HardwareLocality::bind_memory_to_core(int core) { // saved, accessible via get_last_frame(), and will be // processed on the next call to run() if possible. template -int DataCaptureThread::run(uint64_t seq_beg, - uint64_t nseq_per_obuf, - int nbuf, - uint8_t* obufs[], - size_t* ngood_bytes[], - size_t* src_ngood_bytes[], - PDC* decode, - PPC* process) { +int PacketCaptureThread::run(uint64_t seq_beg, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t* ngood_bytes[], + size_t* src_ngood_bytes[], + PDC* decode, + PPC* process) { uint64_t seq_end = seq_beg + nbuf*nseq_per_obuf; size_t local_ngood_bytes[2] = {0, 0}; int ret; @@ -132,7 +132,7 @@ int DataCaptureThread::run(uint64_t seq_beg, return ret; } -BFdatacapture_status BFdatacapture_impl::recv() { +BFpacketcapture_status BFpacketcapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); uint8_t* buf_ptrs[2]; @@ -157,11 +157,11 @@ BFdatacapture_status BFdatacapture_impl::recv() { _decoder, _processor); BF_PRINTD("OUTSIDE"); - if( state & DataCaptureThread::CAPTURE_ERROR ) { + if( state & PacketCaptureThread::CAPTURE_ERROR ) { return BF_CAPTURE_ERROR; - } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { + } else if( state & PacketCaptureThread::CAPTURE_INTERRUPTED ) { return BF_CAPTURE_INTERRUPTED; - } else if( state & DataCaptureThread::CAPTURE_INTERRUPTED ) { + } else if( state & PacketCaptureThread::CAPTURE_INTERRUPTED ) { if( _active ) { return BF_CAPTURE_ENDED; } else { @@ -184,9 +184,9 @@ BFdatacapture_status BFdatacapture_impl::recv() { const void* hdr=NULL; size_t hdr_size=0; - BFdatacapture_status ret; + BFpacketcapture_status ret; bool was_active = _active; - _active = state & DataCaptureThread::CAPTURE_SUCCESS; + _active = state & PacketCaptureThread::CAPTURE_SUCCESS; BF_PRINTD("ACTIVE: " << _active << " WAS ACTIVE: " << was_active); if( _active ) { BF_PRINTD("START"); @@ -234,60 +234,64 @@ BFdatacapture_status BFdatacapture_impl::recv() { return ret; } -BFstatus bfDataCaptureDestroy(BFdatacapture obj) { +BFstatus bfPacketCaptureDestroy(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; return BF_STATUS_SUCCESS; } -BFstatus bfDataCaptureRecv(BFdatacapture obj, BFdatacapture_status* result) { +BFstatus bfPacketCaptureRecv(BFpacketcapture obj, + BFpacketcapture_status* result) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN_ELSE(*result = obj->recv(), *result = BF_CAPTURE_ERROR); } -BFstatus bfDataCaptureFlush(BFdatacapture obj) { +BFstatus bfPacketCaptureFlush(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->flush()); } -BFstatus bfDataCaptureEnd(BFdatacapture obj) { +BFstatus bfPacketCaptureEnd(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->end_writing()); } -BFstatus bfDataCaptureCallbackCreate(BFdatacapture_callback* obj) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_callback_impl(), - *obj = 0); +BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_callback_impl(), + *obj = 0); } -BFstatus bfDataCaptureCallbackDestroy(BFdatacapture_callback obj) { +BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; return BF_STATUS_SUCCESS; } -BFstatus bfDataCaptureCallbackSetCHIPS(BFdatacapture_callback obj, BFdatacapture_chips_sequence_callback callback) { +BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, + BFpacketcapture_chips_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_chips(callback); return BF_STATUS_SUCCESS; } -BFstatus bfDataCaptureCallbackSetCOR(BFdatacapture_callback obj, BFdatacapture_cor_sequence_callback callback) { +BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, + BFpacketcapture_cor_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_cor(callback); return BF_STATUS_SUCCESS; } -BFstatus bfDataCaptureCallbackSetTBN(BFdatacapture_callback obj, BFdatacapture_tbn_sequence_callback callback) { +BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, + BFpacketcapture_tbn_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_tbn(callback); return BF_STATUS_SUCCESS; } -BFstatus bfDataCaptureCallbackSetDRX(BFdatacapture_callback obj, BFdatacapture_drx_sequence_callback callback) { +BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, + BFpacketcapture_drx_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_drx(callback); return BF_STATUS_SUCCESS; } - diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 71b2a729f..9a917a1be 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -162,13 +162,13 @@ class BoundThread { } }; -class DataCaptureMethod { +class PacketCaptureMethod { protected: int _fd; size_t _pkt_size_max; AlignedBuffer _buf; public: - DataCaptureMethod(int fd, size_t pkt_size_max=9000) + PacketCaptureMethod(int fd, size_t pkt_size_max=9000) : _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max) {} virtual int recv_packet(uint8_t** pkt_ptr, int flags=0) { return 0; @@ -186,9 +186,9 @@ struct PacketStats { size_t nvalid_bytes; }; -class DataCaptureThread : public BoundThread { +class PacketCaptureThread : public BoundThread { private: - DataCaptureMethod* _method; + PacketCaptureMethod* _method; PacketStats _stats; std::vector _src_stats; bool _have_pkt; @@ -203,7 +203,7 @@ class DataCaptureThread : public BoundThread { CAPTURE_NO_DATA = 1 << 3, CAPTURE_ERROR = 1 << 4 }; - DataCaptureThread(DataCaptureMethod* method, int nsrc, int core=0) + PacketCaptureThread(PacketCaptureMethod* method, int nsrc, int core=0) : BoundThread(core), _method(method), _src_stats(nsrc), _have_pkt(false), _core(core) { this->reset_stats(); @@ -243,61 +243,61 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { return (2*val/mult+1)/2*mult; } -class BFdatacapture_callback_impl { - BFdatacapture_chips_sequence_callback _chips_callback; - BFdatacapture_cor_sequence_callback _cor_callback; - BFdatacapture_tbn_sequence_callback _tbn_callback; - BFdatacapture_drx_sequence_callback _drx_callback; +class BFpacketcapture_callback_impl { + BFpacketcapture_chips_sequence_callback _chips_callback; + BFpacketcapture_cor_sequence_callback _cor_callback; + BFpacketcapture_tbn_sequence_callback _tbn_callback; + BFpacketcapture_drx_sequence_callback _drx_callback; public: - BFdatacapture_callback_impl() + BFpacketcapture_callback_impl() : _chips_callback(NULL), _cor_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} - inline void set_chips(BFdatacapture_chips_sequence_callback callback) { + inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } - inline BFdatacapture_chips_sequence_callback get_chips() { + inline BFpacketcapture_chips_sequence_callback get_chips() { return _chips_callback; } - inline void set_cor(BFdatacapture_cor_sequence_callback callback) { + inline void set_cor(BFpacketcapture_cor_sequence_callback callback) { _cor_callback = callback; } - inline BFdatacapture_cor_sequence_callback get_cor() { + inline BFpacketcapture_cor_sequence_callback get_cor() { return _cor_callback; } - inline void set_tbn(BFdatacapture_tbn_sequence_callback callback) { + inline void set_tbn(BFpacketcapture_tbn_sequence_callback callback) { _tbn_callback = callback; } - inline BFdatacapture_tbn_sequence_callback get_tbn() { + inline BFpacketcapture_tbn_sequence_callback get_tbn() { return _tbn_callback; } - inline void set_drx(BFdatacapture_drx_sequence_callback callback) { + inline void set_drx(BFpacketcapture_drx_sequence_callback callback) { _drx_callback = callback; } - inline BFdatacapture_drx_sequence_callback get_drx() { + inline BFpacketcapture_drx_sequence_callback get_drx() { return _drx_callback; } }; -class BFdatacapture_impl { +class BFpacketcapture_impl { protected: - std::string _name; - DataCaptureThread* _capture; - PacketDecoder* _decoder; - PacketProcessor* _processor; - ProcLog _bind_log; - ProcLog _out_log; - ProcLog _size_log; - ProcLog _stat_log; - ProcLog _perf_log; - pid_t _pid; + std::string _name; + PacketCaptureThread* _capture; + PacketDecoder* _decoder; + PacketProcessor* _processor; + ProcLog _bind_log; + ProcLog _out_log; + ProcLog _size_log; + ProcLog _stat_log; + ProcLog _perf_log; + pid_t _pid; - int _nsrc; - int _nseq_per_buf; - int _slot_ntime; - BFoffset _seq; - int _chan0; - int _nchan; - int _payload_size; - bool _active; + int _nsrc; + int _nseq_per_buf; + int _slot_ntime; + BFoffset _seq; + int _chan0; + int _nchan; + int _payload_size; + bool _active; private: std::chrono::high_resolution_clock::time_point _t0; @@ -372,7 +372,7 @@ class BFdatacapture_impl { virtual inline bool has_sequence_changed(const PacketDesc* pkt) { return false; } virtual void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) {} public: - inline BFdatacapture_impl(DataCaptureThread* capture, + inline BFpacketcapture_impl(PacketCaptureThread* capture, PacketDecoder* decoder, PacketProcessor* processor, BFring ring, @@ -406,7 +406,7 @@ class BFdatacapture_impl { "slot_ntime : %i\n", _nsrc, _nseq_per_buf, _slot_ntime); } - virtual ~BFdatacapture_impl() {} + virtual ~BFpacketcapture_impl() {} inline void flush() { while( _bufs.size() ) { this->commit_buf(); @@ -419,14 +419,14 @@ class BFdatacapture_impl { this->flush(); _oring.close(); } - BFdatacapture_status recv(); + BFpacketcapture_status recv(); }; -class BFdatacapture_chips_impl : public BFdatacapture_impl { +class BFpacketcapture_chips_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdatacapture_chips_sequence_callback _sequence_callback; + BFpacketcapture_chips_sequence_callback _sequence_callback; void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { // TODO: Might be safer to round to nearest here, but the current firmware @@ -478,14 +478,14 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { << "payload_size : " << _payload_size << "\n"; } public: - inline BFdatacapture_chips_impl(DataCaptureThread* capture, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback) - : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + inline BFpacketcapture_chips_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_chips()) { @@ -495,11 +495,11 @@ class BFdatacapture_chips_impl : public BFdatacapture_impl { } }; -class BFdatacapture_cor_impl : public BFdatacapture_impl { +class BFpacketcapture_cor_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdatacapture_cor_sequence_callback _sequence_callback; + BFpacketcapture_cor_sequence_callback _sequence_callback; BFoffset _time_tag; int _navg; @@ -554,14 +554,14 @@ class BFdatacapture_cor_impl : public BFdatacapture_impl { << "payload_size : " << _payload_size << "\n"; } public: - inline BFdatacapture_cor_impl(DataCaptureThread* capture, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback) - : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + inline BFpacketcapture_cor_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_cor()) { @@ -571,11 +571,11 @@ class BFdatacapture_cor_impl : public BFdatacapture_impl { } }; -class BFdatacapture_tbn_impl : public BFdatacapture_impl { +class BFpacketcapture_tbn_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdatacapture_tbn_sequence_callback _sequence_callback; + BFpacketcapture_tbn_sequence_callback _sequence_callback; BFoffset _time_tag; @@ -624,14 +624,14 @@ class BFdatacapture_tbn_impl : public BFdatacapture_impl { << "payload_size : " << _payload_size << "\n"; } public: - inline BFdatacapture_tbn_impl(DataCaptureThread* capture, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback) - : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + inline BFpacketcapture_tbn_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_tbn()) { @@ -641,11 +641,11 @@ class BFdatacapture_tbn_impl : public BFdatacapture_impl { } }; -class BFdatacapture_drx_impl : public BFdatacapture_impl { +class BFpacketcapture_drx_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFdatacapture_drx_sequence_callback _sequence_callback; + BFpacketcapture_drx_sequence_callback _sequence_callback; BFoffset _time_tag; int _chan1; @@ -709,14 +709,14 @@ class BFdatacapture_drx_impl : public BFdatacapture_impl { << "payload_size : " << _payload_size << "\n"; } public: - inline BFdatacapture_drx_impl(DataCaptureThread* capture, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFdatacapture_callback sequence_callback) - : BFdatacapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + inline BFpacketcapture_drx_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_drx()), diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp index 652f627eb..21c8ffeb6 100644 --- a/src/udp_capture.cpp +++ b/src/udp_capture.cpp @@ -104,13 +104,13 @@ class VMAReceiver { }; #endif // BF_VMA_ENABLED -class UDPPacketReceiver : public DataCaptureMethod { +class UDPPacketReceiver : public PacketCaptureMethod { #if BF_VMA_ENABLED VMAReceiver _vma; #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : DataCaptureMethod(fd, pkt_size_max) + : PacketCaptureMethod(fd, pkt_size_max) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -131,39 +131,39 @@ class UDPPacketReceiver : public DataCaptureMethod { inline const char* get_name() { return "udp_capture"; } }; -BFstatus bfUdpCaptureCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core) { +BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); UDPPacketReceiver* method = new UDPPacketReceiver(fd, max_payload_size); - DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("cor") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_cor_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); diff --git a/src/udp_sniffer.cpp b/src/udp_sniffer.cpp index 03485d551..cf7fb38dc 100644 --- a/src/udp_sniffer.cpp +++ b/src/udp_sniffer.cpp @@ -104,13 +104,13 @@ class VMAReceiver { }; #endif // BF_VMA_ENABLED -class UDPPacketSniffer : public DataCaptureMethod { +class UDPPacketSniffer : public PacketCaptureMethod { #if BF_VMA_ENABLED VMAReceiver _vma; #endif public: UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : DataCaptureMethod(fd, pkt_size_max) + : PacketCaptureMethod(fd, pkt_size_max) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -133,39 +133,39 @@ class UDPPacketSniffer : public DataCaptureMethod { inline const char* get_name() { return "udp_sniffer"; } }; -BFstatus bfUdpSnifferCreate(BFdatacapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFdatacapture_callback sequence_callback, - int core) { +BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); UDPPacketSniffer* method = new UDPPacketSniffer(fd, max_payload_size); - DataCaptureThread* capture = new DataCaptureThread(method, nsrc, core); + PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_chips_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("cor") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_cor_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_tbn_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFdatacapture_drx_impl(capture, ring, nsrc, src0, + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); From 5608f798d5a4c4ccbee512dfa213a8e60ca2b459 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 11:17:24 -0600 Subject: [PATCH 027/424] Initial work on getting packet writers into bifrost. --- python/bifrost/packet_writer.py | 95 +++++++++++ python/bifrost/udp_transmit.py | 61 ------- src/bifrost/packet_writer.h | 70 +++++++++ src/bifrost/udp_transmit.h | 56 ------- src/formats/base.hpp | 8 + src/formats/chips.hpp | 19 +++ src/formats/drx.hpp | 16 ++ src/formats/tbn.hpp | 16 ++ src/packet_writer.cpp | 159 +++++++++++++++++++ src/packet_writer.hpp | 271 ++++++++++++++++++++++++++++++++ src/udp_transmit.cpp | 234 --------------------------- 11 files changed, 654 insertions(+), 351 deletions(-) create mode 100644 python/bifrost/packet_writer.py delete mode 100644 python/bifrost/udp_transmit.py create mode 100644 src/bifrost/packet_writer.h delete mode 100644 src/bifrost/udp_transmit.h create mode 100644 src/packet_writer.cpp create mode 100644 src/packet_writer.hpp delete mode 100644 src/udp_transmit.cpp diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py new file mode 100644 index 000000000..0352d36ce --- /dev/null +++ b/python/bifrost/packet_writer.py @@ -0,0 +1,95 @@ + +# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# **TODO: Write tests for this class + +from libbifrost import _bf, _check, _get, BifrostObject +from ndarray import asarray + +class PacketDescription(BifrostObject): + def __init__(self): + BifrostObject.__init__( + self, _bf.bfPacketDescriptionCreate, _bf.bfPacketDescriptionDestroy) + def set_nsrc(self, nsrc): + _check(_bf.bfPacketDescriptionSetNSrc(self.obj, + nsrc)) + def set_nchan(self, nchan): + _check(_bf.bfPacketDescriptionSetNChan(self.obj, + nchan)) + def set_chan0(self, chan0): + _check(_bf.bfPacketDescriptionSetChan0(self.obj, + chan0)) + def set_tuning(self, tuning): + _check(_bf.bfPacketDescriptionSetTuning(self.obj, + tuning)) + def set_gain(self, gain): + _check(_bf.bfPacketDescriptionSetGain(self.obj, + gain)) + def set_decimation(self, decimation): + _check(_bf.bfPacketDescriptionSetDecimation(self.obj, + tuning)) + +class UDPTransmit(BifrostObject): + def __init__(self, fmt, sock, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpTransmitCreate, _bf.bfPacketWriterDestroy, + fmt, sock.fileno(), core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + pass + def send(self, description, seq, seq_increment, src, src_increment, idata): + _check(_bf.bfPacketWriterSend(self.obj, + description.obj, + seq, + seq_increment, + src, + src_increment, + asarray(idata).as_BFarray())) + +class DiskWriter(BifrostObject): + def __init__(self, fmt, fh, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfDiskWriterCreate, _bf.bfPacketWriterDestroy, + fmt, fh.fileno(), core) + def __enter__(self): + return self + def __exit__(self, type, value, tb): + pass + def send(self, description, seq, seq_increment, src, src_increment, idata): + _check(_bf.bfPacketWriterSend(self.obj, + description.obj, + seq, + seq_increment, + src, + src_increment, + asarray(idata).as_BFarray())) + diff --git a/python/bifrost/udp_transmit.py b/python/bifrost/udp_transmit.py deleted file mode 100644 index 18060f49a..000000000 --- a/python/bifrost/udp_transmit.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2017, The Bifrost Authors. All rights reserved. -# Copyright (c) 2017, The University of New Mexico. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# * Neither the name of The Bifrost Authors nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY -# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# **TODO: Write tests for this class - -from libbifrost import _bf, _check, _get, BifrostObject - -import ctypes - -def _packet2pointer(packet): - buf = ctypes.c_char_p(packet) - siz = ctypes.c_uint( len(packet) ) - return buf, siz - -def _packets2pointer(packets): - count = ctypes.c_uint( len(packets) ) - buf = ctypes.c_char_p("".join(packets)) - siz = ctypes.c_uint( len(packets[0]) ) - return buf, siz, count - -class UDPTransmit(BifrostObject): - def __init__(self, sock, core=-1): - BifrostObject.__init__( - self, _bf.bfUdpTransmitCreate, _bf.bfUdpTransmitDestroy, - sock.fileno(), core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - pass - def send(self, packet): - ptr, siz = _packet2pointer(packet) - _check(_bf.bfUdpTransmitSend(self.obj, ptr, siz)) - def sendmany(self, packets): - assert(type(packets) is list) - ptr, siz, count = _packets2pointer(packets) - _check(_bf.bfUdpTransmitSendMany(self.obj, ptr, siz, count)) diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h new file mode 100644 index 000000000..f2936a213 --- /dev/null +++ b/src/bifrost/packet_writer.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_PACKET_WRITER_H_INCLUDE_GUARD_ +#define BF_PACKET_WRITER_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct BFpacketdescription_impl* BFpacketdescription; + +BFstatus bfPacketDescriptionCreate(BFpacketdescription* obj); +BFstatus bfPacketDescriptionDestroy(BFpacketdescription obj); +BFstatus bfPacketDescriptionSetNSrc(BFpacketdescription obj, + int nsrc); +BFstatus bfPacketDescriptionSetNChan(BFpacketdescription obj, + int nchan); +BFstatus bfPacketDescriptionSetChan0(BFpacketdescription obj, + int chan0); +BFstatus bfPacketDescriptionSetTuning(BFpacketdescription obj, + int tuning); +BFstatus bfPacketDescriptionSetGain(BFpacketdescription obj, + uint16_t gain); +BFstatus bfPacketDescriptionSetDecimation(BFpacketdescription obj, + uint16_t decimation); + +typedef struct BFpacketwriter_impl* BFpacketwriter; + +BFstatus bfPacketWriterDestroy(BFpacketwriter obj); +BFstatus bfPacketWriterSend(BFpacketwriter obj, + BFpacketdescription desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_PACKET_WRITER_H_INCLUDE_GUARD_ diff --git a/src/bifrost/udp_transmit.h b/src/bifrost/udp_transmit.h deleted file mode 100644 index e3336ccad..000000000 --- a/src/bifrost/udp_transmit.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. - * Copyright (c) 2017, The University of New Mexico. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ -#define BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct BFudptransmit_impl* BFudptransmit; - -typedef enum BFudptransmit_status_ { - BF_TRANSMIT_CONTINUED, - BF_TRANSMIT_INTERRUPTED, - BF_TRANSMIT_ERROR -} BFudptransmit_status; - -BFstatus bfUdpTransmitCreate(BFudptransmit* obj, - int fd, - int core); -BFstatus bfUdpTransmitDestroy(BFudptransmit obj); -BFstatus bfUdpTransmitSend(BFudptransmit obj, char* packet, unsigned int len); -BFstatus bfUdpTransmitSendMany(BFudptransmit obj, char* packets, unsigned int len, unsigned int npackets); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 286be3240..c4e5ea6aa 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -97,3 +97,11 @@ class PacketProcessor { int nchan, int nseq) {} }; + + +class PacketHeaderFiller { +public: + virtual inline int get_size() { return 0; } + virtual inline void operator()(const PacketDesc* hdr_base, + char* hdr) {} +}; diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 364be144a..fdb0be6cc 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -164,3 +164,22 @@ class CHIPSProcessor : virtual public PacketProcessor { } } }; + +class CHIPSHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(chips_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + char* hdr) { + chips_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(chips_hdr_type)); + + header->roach = hdr_base->src + 1; + header->gbe = hdr_base->tuning; + header->nchan = hdr_base->nchan; + header->nsubband = 1; + header->subband = 0; + header->nroach = hdr_base->nsrc; + header->chan0 = htons(hdr_base->chan0); + header->seq = htobe64(hdr_base->seq + 1); + } +}; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index b1ab71a89..82a766380 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -128,3 +128,19 @@ class DRXProcessor : virtual public PacketProcessor { } } }; + +class DRXHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(drx_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + char* hdr) { + drx_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(drx_hdr_type)); + + header->sync_word = 0x5CDEC0DE; + header->decimation = htobe16(hdr_base->decimation); + header->time_offset = 0; + header->time_tag = htobe64(hdr_base->seq); + header->tuning_word = htobe32(hdr_base->tuning); + } +}; diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index cc3f78edf..8a5ab4464 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -122,3 +122,19 @@ class TBNProcessor : virtual public PacketProcessor { } } }; + +class TBNHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(tbn_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + char* hdr) { + tbn_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(tbn_hdr_type)); + + header->sync_word = 0x5CDEC0DE; + header->tuning_word = htobe32(hdr_base->tuning); + header->tbn_id = htobe16(hdr_base->src + 1) | 1; + header->gain = htobe16(hdr_base->gain); + header->time_tag = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp new file mode 100644 index 000000000..a592cc08d --- /dev/null +++ b/src/packet_writer.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "packet_writer.hpp" + +#define BF_JAYCE_DEBUG 0 + +#if BF_JAYCE_DEBUG +#define BF_PRINTD(stmt) \ + std::cout << stmt << std::endl +#else // not BF_JAYCE_DEBUG +#define BF_PRINTD(stmt) +#endif + +#if BF_HWLOC_ENABLED +int HardwareLocality::bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; +} +#endif // BF_HWLOC_ENABLED + +BFstatus BFpacketwriter_impl::send(BFpacketdescription desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in) { + BF_ASSERT(desc, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(in, BF_STATUS_INVALID_POINTER); + BF_ASSERT(in->ndim == 1, BF_STATUS_INVALID_SHAPE); + + PacketDesc* hdr_base = desc->get_description(); + + int hdr_size = _filler->get_size(); + int data_size = (BF_DTYPE_NBIT(in->dtype)/8) * _nsamples; + int npackets = in->shape[0] / _nsamples; + + char* hdrs; + hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); + hdr_base->seq = seq; + hdr_base->src = src; + for(int i=0; iseq += seq_increment; + hdr_base->src += src_increment; + } + + _writer->send(hdrs, hdr_size, (char*) in->data, data_size, npackets); + + free(hdrs); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionCreate(BFpacketdescription* obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN_ELSE(*obj = new BFpacketdescription_impl(), + *obj = 0); +} + +BFstatus bfPacketDescriptionDestroy(BFpacketdescription obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetNSrc(BFpacketdescription obj, + int nsrc) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_nsrc(nsrc); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetNChan(BFpacketdescription obj, + int nchan) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_nchan(nchan); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetChan0(BFpacketdescription obj, + int chan0) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_chan0(chan0); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetTuning(BFpacketdescription obj, + int tuning) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_tuning(tuning); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetGain(BFpacketdescription obj, + uint16_t gain) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_gain(gain); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketDescriptionSetDecimation(BFpacketdescription obj, + uint16_t decimation) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_decimation(decimation); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketWriterDestroy(BFpacketwriter obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketWriterSend(BFpacketwriter obj, + BFpacketdescription desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + return obj->send(desc, seq, seq_increment, src, src_increment, in); +} diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp new file mode 100644 index 000000000..192d0f386 --- /dev/null +++ b/src/packet_writer.hpp @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include "proclog.hpp" +#include "formats/formats.hpp" +#include "utils.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include + +#if BF_HWLOC_ENABLED +#include +class HardwareLocality { + hwloc_topology_t _topo; + HardwareLocality(HardwareLocality const&); + HardwareLocality& operator=(HardwareLocality const&); +public: + HardwareLocality() { + hwloc_topology_init(&_topo); + hwloc_topology_load(_topo); + } + ~HardwareLocality() { + hwloc_topology_destroy(_topo); + } + int bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; + } +}; +#endif // BF_HWLOC_ENABLED + +class BoundThread { +#if BF_HWLOC_ENABLED + HardwareLocality _hwloc; +#endif +public: + BoundThread(int core) { + bfAffinitySetCore(core); +#if BF_HWLOC_ENABLED + assert(_hwloc.bind_memory_to_core(core) == 0); +#endif + } +}; + +class PacketWriterMethod { +protected: + int _fd; +public: + PacketWriterMethod(int fd) + : _fd(fd) {} + virtual ssize_t send_packets(char* hdrs, + int hdr_size, + char* data, + int data_size, + int npackets, + int flags=0) { + return 0; + } + virtual const char* get_name() { return "generic_writer"; } +}; + +struct PacketStats { + size_t ninvalid; + size_t ninvalid_bytes; + size_t nlate; + size_t nlate_bytes; + size_t nvalid; + size_t nvalid_bytes; +}; + +class PacketWriterThread : public BoundThread { +private: + PacketWriterMethod* _method; + PacketStats _stats; + int _core; + +public: + PacketWriterThread(PacketWriterMethod* method, int core=0) + : BoundThread(core), _method(method), _core(core) { + this->reset_stats(); + } + inline ssize_t send(char* hdrs, + int hdr_size, + char* datas, + int data_size, + int npackets) { + ssize_t nsent = _method->send_packets(hdrs, hdr_size, datas, data_size, npackets); + if( nsent == -1 ) { + _stats.ninvalid += npackets; + _stats.ninvalid_bytes += npackets * (hdr_size + data_size); + } else { + _stats.nvalid += npackets; + _stats.nvalid_bytes += npackets * (hdr_size + data_size); + } + return nsent; + } + inline const char* get_name() { return _method->get_name(); } + inline const int get_core() { return _core; } + inline const PacketStats* get_stats() const { return &_stats; } + inline void reset_stats() { + ::memset(&_stats, 0, sizeof(_stats)); + } +}; + +class BFpacketdescription_impl { + PacketDesc _desc; +public: + inline BFpacketdescription_impl() { + memset(&_desc, 0, sizeof(PacketDesc)); + } + inline PacketDesc* get_description() { return &_desc; } + inline void set_nsrc(int nsrc) { _desc.nsrc = nsrc; } + inline void set_nchan(int nchan) { _desc.nchan = nchan; } + inline void set_chan0(int chan0) { _desc.chan0 = chan0; } + inline void set_tuning(int tuning) { _desc.tuning = tuning; } + inline void set_gain(uint16_t gain) { _desc.gain = gain; } + inline void set_decimation(uint16_t decimation) { _desc.decimation = decimation; } +}; + +class BFpacketwriter_impl { +protected: + std::string _name; + PacketWriterThread* _writer; + PacketHeaderFiller* _filler; + + ProcLog _bind_log; + ProcLog _stat_log; + pid_t _pid; + + int _nsamples; +private: + void update_stats_log() { + const PacketStats* stats = _writer->get_stats(); + _stat_log.update() << "ngood_bytes : " << stats->nvalid_bytes << "\n" + << "nmissing_bytes : " << stats->ninvalid_bytes << "\n" + << "ninvalid : " << stats->ninvalid << "\n" + << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" + << "nlate : " << stats->nlate << "\n" + << "nlate_bytes : " << stats->nlate_bytes << "\n" + << "nvalid : " << stats->nvalid << "\n" + << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; + } +public: + inline BFpacketwriter_impl(PacketWriterThread* writer, + PacketHeaderFiller* filler, + int nsamples) + : _name(writer->get_name()), _writer(writer), _filler(filler), + _bind_log(_name+"/bind"), + _stat_log(_name+"/stats"), + _nsamples(nsamples) { + _bind_log.update() << "ncore : " << 1 << "\n" + << "core0 : " << _writer->get_core() << "\n"; + } + virtual ~BFpacketwriter_impl() {} + BFstatus send(BFpacketdescription desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in); +}; + +class BFpacketwriter_generic_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_generic_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new PacketHeaderFiller(); + _type_log.update("type : %s\n", "generic"); + } +}; + +class BFpacketwriter_chips_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_chips_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new CHIPSHeaderFiller(); + _type_log.update("type : %s\n", "chips"); + } +}; + +class BFpacketwriter_cor_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_cor_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new CORHeaderFiller(); + _type_log.update("type : %s\n", "cor"); + } +}; + +class BFpacketwriter_tbn_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_tbn_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new TBNHeaderFiller(); + _type_log.update("type : %s\n", "tbn"); + } +}; + +class BFpacketwriter_drx_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_drx_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new DRXHeaderFiller(); + _type_log.update("type : %s\n", "drx"); + } +}; diff --git a/src/udp_transmit.cpp b/src/udp_transmit.cpp deleted file mode 100644 index a470c8e76..000000000 --- a/src/udp_transmit.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. - * Copyright (c) 2017, The University of New Mexico. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include "proclog.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include - -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; - } -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { -#if BF_HWLOC_ENABLED - HardwareLocality _hwloc; -#endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); -#if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); -#endif - } -}; - -struct PacketStats { - size_t ninvalid; - size_t ninvalid_bytes; - size_t nlate; - size_t nlate_bytes; - size_t nvalid; - size_t nvalid_bytes; -}; - -class UDPTransmitThread : public BoundThread { - PacketStats _stats; - - int _fd; - -public: - UDPTransmitThread(int fd, int core=0) - : BoundThread(core), _fd(fd) { - this->reset_stats(); - } - inline ssize_t send(msghdr* packet) { - ssize_t nsent = sendmsg(_fd, packet, 0); - if( nsent == -1 ) { - ++_stats.ninvalid; - _stats.ninvalid_bytes += packet->msg_iovlen; - } else { - ++_stats.nvalid; - _stats.nvalid_bytes += nsent; - } - return nsent; - } - inline ssize_t sendmany(mmsghdr *packets, unsigned int npackets) { - ssize_t nsent = sendmmsg(_fd, packets, npackets, 0); - if( nsent == -1 ) { - _stats.ninvalid += npackets; - _stats.ninvalid_bytes += npackets * packets->msg_len; - } else { - _stats.nvalid += npackets; - _stats.nvalid_bytes += npackets * packets->msg_len; - } - return nsent; - } - inline const PacketStats* get_stats() const { return &_stats; } - inline void reset_stats() { - ::memset(&_stats, 0, sizeof(_stats)); - } -}; - -class BFudptransmit_impl { - UDPTransmitThread _transmit; - ProcLog _type_log; - ProcLog _bind_log; - ProcLog _stat_log; - pid_t _pid; - - void update_stats_log() { - const PacketStats* stats = _transmit.get_stats(); - _stat_log.update() << "ngood_bytes : " << stats->nvalid_bytes << "\n" - << "nmissing_bytes : " << stats->ninvalid_bytes << "\n" - << "ninvalid : " << stats->ninvalid << "\n" - << "ninvalid_bytes : " << stats->ninvalid_bytes << "\n" - << "nlate : " << stats->nlate << "\n" - << "nlate_bytes : " << stats->nlate_bytes << "\n" - << "nvalid : " << stats->nvalid << "\n" - << "nvalid_bytes : " << stats->nvalid_bytes << "\n"; - } -public: - inline BFudptransmit_impl(int fd, - int core) - : _transmit(fd, core), - _type_log("udp_transmit/type"), - _bind_log("udp_transmit/bind"), - _stat_log("udp_transmit/stats") { - _type_log.update() << "type : " << "generic"; - _bind_log.update() << "ncore : " << 1 << "\n" - << "core0 : " << core << "\n"; - } - BFudptransmit_status send(char *packet, unsigned int len) { - ssize_t state; - struct msghdr msg; - struct iovec iov[1]; - - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = iov; - msg.msg_iovlen = 1; - iov[0].iov_base = packet; - iov[0].iov_len = len; - - state = _transmit.send( &msg ); - if( state == -1 ) { - return BF_TRANSMIT_ERROR; - } - this->update_stats_log(); - return BF_TRANSMIT_CONTINUED; - } - BFudptransmit_status sendmany(char *packets, unsigned int len, unsigned int npackets) { - ssize_t state; - unsigned int i; - struct mmsghdr *mmsg = NULL; - struct iovec *iovs = NULL; - - mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - iovs = (struct iovec *) malloc(sizeof(struct iovec)*npackets); - memset(mmsg, 0, sizeof(struct mmsghdr)*npackets); - for(i=0; iupdate_stats_log(); - return BF_TRANSMIT_CONTINUED; - } -}; - -BFstatus bfUdpTransmitCreate(BFudptransmit* obj, - int fd, - int core) { - BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - BF_TRY_RETURN_ELSE(*obj = new BFudptransmit_impl(fd, core), - *obj = 0); - -} -BFstatus bfUdpTransmitDestroy(BFudptransmit obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - delete obj; - return BF_STATUS_SUCCESS; -} -BFstatus bfUdpTransmitSend(BFudptransmit obj, char* packet, unsigned int len) { - BF_TRY_RETURN(obj->send(packet, len)); -} -BFstatus bfUdpTransmitSendMany(BFudptransmit obj, char* packets, unsigned int len, unsigned int npackets) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->sendmany(packets, len, npackets)); -} From 3f31344b9927c588c55df5da974e77fa019eb3a8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 11:25:06 -0600 Subject: [PATCH 028/424] Added in the disk and UDP parts of the new packet_writer feature. --- src/Makefile | 2 + src/bifrost/disk_writer.h | 48 ++++++++++++++ src/bifrost/udp_transmit.h | 48 ++++++++++++++ src/disk_writer.cpp | 117 ++++++++++++++++++++++++++++++++++ src/formats/cor.hpp | 13 ++++ src/udp_transmit.cpp | 127 +++++++++++++++++++++++++++++++++++++ 6 files changed, 355 insertions(+) create mode 100644 src/bifrost/disk_writer.h create mode 100644 src/bifrost/udp_transmit.h create mode 100644 src/disk_writer.cpp create mode 100644 src/udp_transmit.cpp diff --git a/src/Makefile b/src/Makefile index ebedfcec1..0497f72f3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,6 +18,8 @@ LIBBIFROST_OBJS = \ disk_reader.o \ udp_capture.o \ udp_sniffer.o \ + packet_writer.o \ + disk_writer.o \ udp_transmit.o \ unpack.o \ quantize.o \ diff --git a/src/bifrost/disk_writer.h b/src/bifrost/disk_writer.h new file mode 100644 index 000000000..b9a103302 --- /dev/null +++ b/src/bifrost/disk_writer.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_DISK_WRITER_H_INCLUDE_GUARD_ +#define BF_DISK_WRITER_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +BFstatus bfDiskWriterCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_DISK_WRITER_H_INCLUDE_GUARD_ diff --git a/src/bifrost/udp_transmit.h b/src/bifrost/udp_transmit.h new file mode 100644 index 000000000..14fac3eda --- /dev/null +++ b/src/bifrost/udp_transmit.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ +#define BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ diff --git a/src/disk_writer.cpp b/src/disk_writer.cpp new file mode 100644 index 000000000..74b5b0192 --- /dev/null +++ b/src/disk_writer.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include +#include "proclog.hpp" +#include "formats/formats.hpp" +#include "packet_writer.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include +#include + +class DiskPacketWriter : public PacketWriterMethod { +public: + DiskPacketWriter(int fd) + : PacketWriterMethod(fd) {} + ssize_t send_packets(char* hdrs, + int hdr_size, + char* data, + int data_size, + int npackets, + int flags=0) { + ssize_t status, nsent = 0; + for(int i=0; i(hdr); + memset(header, 0, sizeof(cor_hdr_type)); + + // TODO: Finish this! + header->sync_word = 0x5CDEC0DE; + } +}; diff --git a/src/udp_transmit.cpp b/src/udp_transmit.cpp new file mode 100644 index 000000000..25c081602 --- /dev/null +++ b/src/udp_transmit.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include +#include +#include +#include "proclog.hpp" +#include "packet_writer.hpp" + +#include // For ntohs +#include // For recvfrom + +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset +#include + +#include +#include +#include + +class UDPPacketSender : public PacketWriterMethod { +public: + UDPPacketSender(int fd) + : PacketWriterMethod(fd) {} + ssize_t send_packets(char* hdrs, + int hdr_size, + char* data, + int data_size, + int npackets, + int flags=0) { + struct mmsghdr *mmsg = NULL; + struct iovec *iovs = NULL; + mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); + iovs = (struct iovec *) malloc(sizeof(struct iovec)*2*npackets); + memset(mmsg, 0, sizeof(struct mmsghdr)*npackets); + + for(int i=0; i Date: Wed, 3 Jul 2019 11:39:17 -0600 Subject: [PATCH 029/424] Cleaned up some naming in the new packet_writer modules. --- python/bifrost/packet_writer.py | 24 +++++++-------- src/bifrost/packet_writer.h | 44 +++++++++++++-------------- src/packet_writer.cpp | 54 ++++++++++++++++----------------- src/packet_writer.hpp | 16 +++++----- 4 files changed, 69 insertions(+), 69 deletions(-) diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 0352d36ce..5ed6db42a 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -30,27 +30,27 @@ from libbifrost import _bf, _check, _get, BifrostObject from ndarray import asarray -class PacketDescription(BifrostObject): +class HeaderInfo(BifrostObject): def __init__(self): BifrostObject.__init__( - self, _bf.bfPacketDescriptionCreate, _bf.bfPacketDescriptionDestroy) + self, _bf.bfHeaderInfoCreate, _bf.bfHeaderInfoDestroy) def set_nsrc(self, nsrc): - _check(_bf.bfPacketDescriptionSetNSrc(self.obj, + _check(_bf.bfHeaderInfoSetNSrc(self.obj, nsrc)) def set_nchan(self, nchan): - _check(_bf.bfPacketDescriptionSetNChan(self.obj, + _check(_bf.bfHeaderInfoSetNChan(self.obj, nchan)) def set_chan0(self, chan0): - _check(_bf.bfPacketDescriptionSetChan0(self.obj, + _check(_bf.bfHeaderInfoSetChan0(self.obj, chan0)) def set_tuning(self, tuning): - _check(_bf.bfPacketDescriptionSetTuning(self.obj, + _check(_bf.bfHeaderInfoSetTuning(self.obj, tuning)) def set_gain(self, gain): - _check(_bf.bfPacketDescriptionSetGain(self.obj, + _check(_bf.bfHeaderInfoSetGain(self.obj, gain)) def set_decimation(self, decimation): - _check(_bf.bfPacketDescriptionSetDecimation(self.obj, + _check(_bf.bfHeaderInfoSetDecimation(self.obj, tuning)) class UDPTransmit(BifrostObject): @@ -64,9 +64,9 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, description, seq, seq_increment, src, src_increment, idata): + def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): _check(_bf.bfPacketWriterSend(self.obj, - description.obj, + headerinfo.obj, seq, seq_increment, src, @@ -84,9 +84,9 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, description, seq, seq_increment, src, src_increment, idata): + def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): _check(_bf.bfPacketWriterSend(self.obj, - description.obj, + headerinfo.obj, seq, seq_increment, src, diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index f2936a213..e0a6abc6c 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -35,33 +35,33 @@ extern "C" { #include -typedef struct BFpacketdescription_impl* BFpacketdescription; +typedef struct BFheaderinfo_impl* BFheaderinfo; -BFstatus bfPacketDescriptionCreate(BFpacketdescription* obj); -BFstatus bfPacketDescriptionDestroy(BFpacketdescription obj); -BFstatus bfPacketDescriptionSetNSrc(BFpacketdescription obj, - int nsrc); -BFstatus bfPacketDescriptionSetNChan(BFpacketdescription obj, - int nchan); -BFstatus bfPacketDescriptionSetChan0(BFpacketdescription obj, - int chan0); -BFstatus bfPacketDescriptionSetTuning(BFpacketdescription obj, - int tuning); -BFstatus bfPacketDescriptionSetGain(BFpacketdescription obj, - uint16_t gain); -BFstatus bfPacketDescriptionSetDecimation(BFpacketdescription obj, - uint16_t decimation); +BFstatus bfHeaderInfoCreate(BFheaderinfo* obj); +BFstatus bfHeaderInfoDestroy(BFheaderinfo obj); +BFstatus bfHeaderInfoSetNSrc(BFheaderinfo obj, + int nsrc); +BFstatus bfHeaderInfoSetNChan(BFheaderinfo obj, + int nchan); +BFstatus bfHeaderInfoSetChan0(BFheaderinfo obj, + int chan0); +BFstatus bfHeaderInfoSetTuning(BFheaderinfo obj, + int tuning); +BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, + uint16_t gain); +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + uint16_t decimation); typedef struct BFpacketwriter_impl* BFpacketwriter; BFstatus bfPacketWriterDestroy(BFpacketwriter obj); -BFstatus bfPacketWriterSend(BFpacketwriter obj, - BFpacketdescription desc, - BFoffset seq, - BFoffset seq_increment, - BFoffset src, - BFoffset src_increment, - BFarray const* in); +BFstatus bfPacketWriterSend(BFpacketwriter obj, + BFheaderinfo desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in); #ifdef __cplusplus } // extern "C" diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index a592cc08d..26b3f0ada 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -55,12 +55,12 @@ int HardwareLocality::bind_memory_to_core(int core) { } #endif // BF_HWLOC_ENABLED -BFstatus BFpacketwriter_impl::send(BFpacketdescription desc, - BFoffset seq, - BFoffset seq_increment, - BFoffset src, - BFoffset src_increment, - BFarray const* in) { +BFstatus BFpacketwriter_impl::send(BFheaderinfo desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in) { BF_ASSERT(desc, BF_STATUS_INVALID_HANDLE); BF_ASSERT(in, BF_STATUS_INVALID_POINTER); BF_ASSERT(in->ndim == 1, BF_STATUS_INVALID_SHAPE); @@ -87,55 +87,55 @@ BFstatus BFpacketwriter_impl::send(BFpacketdescription desc, return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionCreate(BFpacketdescription* obj) { +BFstatus bfHeaderInfoCreate(BFheaderinfo* obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN_ELSE(*obj = new BFpacketdescription_impl(), + BF_TRY_RETURN_ELSE(*obj = new BFheaderinfo_impl(), *obj = 0); } -BFstatus bfPacketDescriptionDestroy(BFpacketdescription obj) { +BFstatus bfHeaderInfoDestroy(BFheaderinfo obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetNSrc(BFpacketdescription obj, - int nsrc) { +BFstatus bfHeaderInfoSetNSrc(BFheaderinfo obj, + int nsrc) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_nsrc(nsrc); return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetNChan(BFpacketdescription obj, - int nchan) { +BFstatus bfHeaderInfoSetNChan(BFheaderinfo obj, + int nchan) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_nchan(nchan); return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetChan0(BFpacketdescription obj, - int chan0) { +BFstatus bfHeaderInfoSetChan0(BFheaderinfo obj, + int chan0) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_chan0(chan0); return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetTuning(BFpacketdescription obj, - int tuning) { +BFstatus bfHeaderInfoSetTuning(BFheaderinfo obj, + int tuning) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_tuning(tuning); return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetGain(BFpacketdescription obj, - uint16_t gain) { +BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, + uint16_t gain) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_gain(gain); return BF_STATUS_SUCCESS; } -BFstatus bfPacketDescriptionSetDecimation(BFpacketdescription obj, - uint16_t decimation) { +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + uint16_t decimation) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_decimation(decimation); return BF_STATUS_SUCCESS; @@ -147,12 +147,12 @@ BFstatus bfPacketWriterDestroy(BFpacketwriter obj) { return BF_STATUS_SUCCESS; } -BFstatus bfPacketWriterSend(BFpacketwriter obj, - BFpacketdescription desc, - BFoffset seq, - BFoffset seq_increment, - BFoffset src, - BFoffset src_increment, +BFstatus bfPacketWriterSend(BFpacketwriter obj, + BFheaderinfo desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, BFarray const* in) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); return obj->send(desc, seq, seq_increment, src, src_increment, in); diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 192d0f386..29e959f93 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -152,10 +152,10 @@ class PacketWriterThread : public BoundThread { } }; -class BFpacketdescription_impl { +class BFheaderinfo_impl { PacketDesc _desc; public: - inline BFpacketdescription_impl() { + inline BFheaderinfo_impl() { memset(&_desc, 0, sizeof(PacketDesc)); } inline PacketDesc* get_description() { return &_desc; } @@ -202,12 +202,12 @@ class BFpacketwriter_impl { << "core0 : " << _writer->get_core() << "\n"; } virtual ~BFpacketwriter_impl() {} - BFstatus send(BFpacketdescription desc, - BFoffset seq, - BFoffset seq_increment, - BFoffset src, - BFoffset src_increment, - BFarray const* in); + BFstatus send(BFheaderinfo desc, + BFoffset seq, + BFoffset seq_increment, + BFoffset src, + BFoffset src_increment, + BFarray const* in); }; class BFpacketwriter_generic_impl : public BFpacketwriter_impl { From dbc1f9314eb59187a0b9f58b85b4dc1ec17a283d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 14:11:21 -0600 Subject: [PATCH 030/424] Small tweak to the send method in packet_writer to allow strides in seq and src so that the two can be mixed. --- python/bifrost/packet_writer.py | 8 ++++++-- src/bifrost/packet_writer.h | 2 ++ src/packet_writer.cpp | 12 +++++++----- src/packet_writer.hpp | 2 ++ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 5ed6db42a..684b484b8 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -64,13 +64,15 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): + def send(self, headerinfo, seq, seq_increment, seq_stride, src, src_increment, src_stride, idata): _check(_bf.bfPacketWriterSend(self.obj, headerinfo.obj, seq, seq_increment, + seq_stride, src, src_increment, + src_stride, asarray(idata).as_BFarray())) class DiskWriter(BifrostObject): @@ -84,12 +86,14 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): + def send(self, headerinfo, seq, seq_increment, seq_stride, src, src_increment, src_stride, idata): _check(_bf.bfPacketWriterSend(self.obj, headerinfo.obj, seq, seq_increment, + seq_stride, src, src_increment, + src_stride, asarray(idata).as_BFarray())) diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index e0a6abc6c..d21edfe95 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -59,8 +59,10 @@ BFstatus bfPacketWriterSend(BFpacketwriter obj, BFheaderinfo desc, BFoffset seq, BFoffset seq_increment, + BFoffset seq_stride, BFoffset src, BFoffset src_increment, + BFoffset src_stride, BFarray const* in); #ifdef __cplusplus diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index 26b3f0ada..a0039143b 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -58,8 +58,10 @@ int HardwareLocality::bind_memory_to_core(int core) { BFstatus BFpacketwriter_impl::send(BFheaderinfo desc, BFoffset seq, BFoffset seq_increment, + BFoffset seq_stride, BFoffset src, BFoffset src_increment, + BFoffset src_stride, BFarray const* in) { BF_ASSERT(desc, BF_STATUS_INVALID_HANDLE); BF_ASSERT(in, BF_STATUS_INVALID_POINTER); @@ -73,12 +75,10 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo desc, char* hdrs; hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); - hdr_base->seq = seq; - hdr_base->src = src; for(int i=0; iseq = seq + i*seq_increment/seq_stride; + hdr_base->src = src + i*src_increment/src_stride; (*_filler)(hdr_base, hdrs+hdr_size*i); - hdr_base->seq += seq_increment; - hdr_base->src += src_increment; } _writer->send(hdrs, hdr_size, (char*) in->data, data_size, npackets); @@ -151,9 +151,11 @@ BFstatus bfPacketWriterSend(BFpacketwriter obj, BFheaderinfo desc, BFoffset seq, BFoffset seq_increment, + BFoffset seq_stride, BFoffset src, BFoffset src_increment, + BFoffset src_stride, BFarray const* in) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - return obj->send(desc, seq, seq_increment, src, src_increment, in); + return obj->send(desc, seq, seq_increment, seq_stride, src, src_increment, src_stride, in); } diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 29e959f93..845a02dfc 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -205,8 +205,10 @@ class BFpacketwriter_impl { BFstatus send(BFheaderinfo desc, BFoffset seq, BFoffset seq_increment, + BFoffset seq_stride, BFoffset src, BFoffset src_increment, + BFoffset src_stride, BFarray const* in); }; From 8ad75685c1ebf143775a82704fe6009ebd05657f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 14:14:01 -0600 Subject: [PATCH 031/424] Cleaned up the PacketHeaderFiller sub-classes for the CHIPS, DRX, TBN, and COR formats. --- src/formats/chips.hpp | 4 ++-- src/formats/cor.hpp | 20 ++++++++++++++++++-- src/formats/drx.hpp | 12 +++++++----- src/formats/tbn.hpp | 4 +++- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index fdb0be6cc..9e050ef7a 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -176,8 +176,8 @@ class CHIPSHeaderFiller : virtual public PacketHeaderFiller { header->roach = hdr_base->src + 1; header->gbe = hdr_base->tuning; header->nchan = hdr_base->nchan; - header->nsubband = 1; - header->subband = 0; + header->nsubband = 1; // Should be changable? + header->subband = 0; // Should be changable? header->nroach = hdr_base->nsrc; header->chan0 = htons(hdr_base->chan0); header->seq = htobe64(hdr_base->seq + 1); diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 225c466ec..4da5ea429 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -161,7 +161,23 @@ class CORHeaderFiller : virtual public PacketHeaderFiller { cor_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(cor_hdr_type)); - // TODO: Finish this! - header->sync_word = 0x5CDEC0DE; + // Find the number of antennas needed to reach this number of baselines + int N = (sqrt(8*hdr_base->nsrc+1)-1)/2; + + // Find the indices of the two stands that form this baseline + int a = -1; + int b = 2 + 2*(N-1)+1; + int c = -2*hdr_base->src; + int stand0 = (int) (-b + sqrt(b*b-4*a*c))/(2*a); + int stand1 = hdr_base->src - stand0*(2*(N-1)+1-stand0)/2 + stand0; + + header->sync_word = 0x5CDEC0DE; + header->frame_count_word = 0x02; // COR packet identifier + header->first_chan = htons(hdr_base->chan0); + header->gain = htons(hdr_base->gain); + header->time_tag = htobe64(hdr_base->seq); + header->navg = htobe32(hdr_base->decimation); + header->stand0 = htons(stand0 + 1); + header->stand1 = htons(stand1 + 1); } }; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 82a766380..15b4ebd8f 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -137,10 +137,12 @@ class DRXHeaderFiller : virtual public PacketHeaderFiller { drx_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(drx_hdr_type)); - header->sync_word = 0x5CDEC0DE; - header->decimation = htobe16(hdr_base->decimation); - header->time_offset = 0; - header->time_tag = htobe64(hdr_base->seq); - header->tuning_word = htobe32(hdr_base->tuning); + header->sync_word = 0x5CDEC0DE; + header->frame_count_word = (hdr_base->src & 0xFD); // ID is the lower 8 bits; + // bit 2 is reserved + header->decimation = htobe16(hdr_base->decimation); + header->time_offset = 0; + header->time_tag = htobe64(hdr_base->seq); + header->tuning_word = htobe32(hdr_base->tuning); } }; diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index 8a5ab4464..23e0a0185 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -133,7 +133,9 @@ class TBNHeaderFiller : virtual public PacketHeaderFiller { header->sync_word = 0x5CDEC0DE; header->tuning_word = htobe32(hdr_base->tuning); - header->tbn_id = htobe16(hdr_base->src + 1) | 1; + header->tbn_id = (htobe16(hdr_base->src + 1) & 0xFFC); // ID is the upper 14 bits; + // bit 2 is reserved; + // bit 1 indicates TBW header->gain = htobe16(hdr_base->gain); header->time_tag = htobe64(hdr_base->seq); } From ac4ed4ada0de7c88cb2ce65a5687a630d32cd619 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 15:18:57 -0600 Subject: [PATCH 032/424] Fixed the CORHeaderFiller class to include the server information via the frame_count_word as is done on ADP. --- src/formats/cor.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 4da5ea429..1ca350322 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -172,7 +172,9 @@ class CORHeaderFiller : virtual public PacketHeaderFiller { int stand1 = hdr_base->src - stand0*(2*(N-1)+1-stand0)/2 + stand0; header->sync_word = 0x5CDEC0DE; - header->frame_count_word = 0x02; // COR packet identifier + header->frame_count_word = htobe32(((hdr_base->tuning & 0xFFFFFF) << 8)\ + | 0x02); // bits 9-32 are the server identifier + // bits 1-8 are the COR packet flag header->first_chan = htons(hdr_base->chan0); header->gain = htons(hdr_base->gain); header->time_tag = htobe64(hdr_base->seq); From b241c3423c0a80531c9a5969fffb65440d89cb01 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 15:32:07 -0600 Subject: [PATCH 033/424] Removed a duplicate declaration of HardwareLocality::bind_memory_to_core. I should probably move this into another file since it is shared by both packet_capture and packet_writer. --- src/packet_writer.hpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 845a02dfc..711dd13e6 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -61,21 +61,7 @@ class HardwareLocality { ~HardwareLocality() { hwloc_topology_destroy(_topo); } - int bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; - } + int bind_memory_to_core(int core); }; #endif // BF_HWLOC_ENABLED From b13004f546bd0bdb62597327137faa13b202f160 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 15:36:31 -0600 Subject: [PATCH 034/424] Fixed a byte ordering problem in DRXHeaderFiller. --- src/formats/drx.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 15b4ebd8f..620c3315e 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -138,8 +138,8 @@ class DRXHeaderFiller : virtual public PacketHeaderFiller { memset(header, 0, sizeof(drx_hdr_type)); header->sync_word = 0x5CDEC0DE; - header->frame_count_word = (hdr_base->src & 0xFD); // ID is the lower 8 bits; - // bit 2 is reserved + header->frame_count_word = htobe32(hdr_base->src & 0xFD); // ID is the lower 8 bits; + // bit 2 is reserved header->decimation = htobe16(hdr_base->decimation); header->time_offset = 0; header->time_tag = htobe64(hdr_base->seq); From f5f781e8038500c936f4c4464e5c1e8caeb6c183 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 15:56:24 -0600 Subject: [PATCH 035/424] Added support for writing TBF packets. --- src/disk_writer.cpp | 5 ++++ src/formats/formats.hpp | 1 + src/formats/tbf.hpp | 58 +++++++++++++++++++++++++++++++++++++++++ src/packet_writer.hpp | 12 +++++++++ src/udp_transmit.cpp | 5 ++++ 5 files changed, 81 insertions(+) create mode 100644 src/formats/tbf.hpp diff --git a/src/disk_writer.cpp b/src/disk_writer.cpp index 74b5b0192..07e380fac 100644 --- a/src/disk_writer.cpp +++ b/src/disk_writer.cpp @@ -91,6 +91,8 @@ BFstatus bfDiskWriterCreate(BFpacketwriter* obj, nsamples = 512; } else if( format == std::string("drx") ) { nsamples = 4096; + } else if( format == std::string("tbf") ) { + nsamples = 6144; } DiskPacketWriter* method = new DiskPacketWriter(fd); @@ -111,6 +113,9 @@ BFstatus bfDiskWriterCreate(BFpacketwriter* obj, } else if( format == std::string("drx") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_drx_impl(writer, nsamples), *obj = 0); + } else if( format == std::string("tbf") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), + *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 017e15c0e..4ab419dea 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -32,3 +32,4 @@ #include "cor.hpp" #include "drx.hpp" #include "tbn.hpp" +#include "tbf.hpp" diff --git a/src/formats/tbf.hpp b/src/formats/tbf.hpp new file mode 100644 index 000000000..01bd08637 --- /dev/null +++ b/src/formats/tbf.hpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +#define TBF_FRAME_SIZE 6168 + +#pragma pack(1) +struct tbf_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t seconds_count; + uint16_t first_chan; + uint16_t unassinged; + uint64_t time_tag; +}; + +class TBFHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(tbf_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + char* hdr) { + tbf_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(tbf_hdr_type)); + + header->sync_word = 0x5CDEC0DE; + header->frame_count_word = htobe32(0x01); // bits 1-8 are the COR packet flag + header->first_chan = htons(hdr_base->src); + header->time_tag = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 711dd13e6..9d7e2dde2 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -257,3 +257,15 @@ class BFpacketwriter_drx_impl : public BFpacketwriter_impl { _type_log.update("type : %s\n", "drx"); } }; + +class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_tbf_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new TBFHeaderFiller(); + _type_log.update("type : %s\n", "tbf"); + } +}; diff --git a/src/udp_transmit.cpp b/src/udp_transmit.cpp index 25c081602..8c7e91d59 100644 --- a/src/udp_transmit.cpp +++ b/src/udp_transmit.cpp @@ -101,6 +101,8 @@ BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, nsamples = 512; } else if( format == std::string("drx") ) { nsamples = 4096; + } else if( format == std::string("tbf") ) { + nsamples = 6144; } UDPPacketSender* method = new UDPPacketSender(fd); @@ -121,6 +123,9 @@ BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, } else if( format == std::string("drx") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_drx_impl(writer, nsamples), *obj = 0); + } else if( format == std::string("tbf") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), + *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } From 28970c470c8254e70da52ac10b9b425858573320 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 3 Jul 2019 17:24:00 -0600 Subject: [PATCH 036/424] Moved the HardwareLocality into its own set of files. --- src/Makefile | 5 ++-- src/hw_locality.cpp | 47 +++++++++++++++++++++++++++++++++ src/hw_locality.hpp | 60 ++++++++++++++++++++++++++++++++++++++++++ src/packet_capture.cpp | 18 ------------- src/packet_capture.hpp | 33 +---------------------- src/packet_writer.cpp | 18 ------------- src/packet_writer.hpp | 33 +---------------------- 7 files changed, 111 insertions(+), 103 deletions(-) create mode 100644 src/hw_locality.cpp create mode 100644 src/hw_locality.hpp diff --git a/src/Makefile b/src/Makefile index 0497f72f3..045ada2d2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -14,6 +14,7 @@ LIBBIFROST_OBJS = \ array.o \ address.o \ udp_socket.o \ + hw_locality.o \ packet_capture.o \ disk_reader.o \ udp_capture.o \ @@ -38,9 +39,7 @@ ifndef NOCUDA reduce.o \ fir.o \ guantize.o \ - gunpack.o \ - romein.o \ - orville.o + gunpack.o endif JIT_SOURCES ?= \ diff --git a/src/hw_locality.cpp b/src/hw_locality.cpp new file mode 100644 index 000000000..85739c002 --- /dev/null +++ b/src/hw_locality.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "hw_locality.hpp" + +#if BF_HWLOC_ENABLED +int HardwareLocality::bind_memory_to_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = 0; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; +} +#endif // BF_HWLOC_ENABLED diff --git a/src/hw_locality.hpp b/src/hw_locality.hpp new file mode 100644 index 000000000..1494bb1cf --- /dev/null +++ b/src/hw_locality.hpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#if BF_HWLOC_ENABLED +#include +class HardwareLocality { + hwloc_topology_t _topo; + HardwareLocality(HardwareLocality const&); + HardwareLocality& operator=(HardwareLocality const&); +public: + HardwareLocality() { + hwloc_topology_init(&_topo); + hwloc_topology_load(_topo); + } + ~HardwareLocality() { + hwloc_topology_destroy(_topo); + } + int bind_memory_to_core(int core); +}; +#endif // BF_HWLOC_ENABLED + +class BoundThread { +#if BF_HWLOC_ENABLED + HardwareLocality _hwloc; +#endif +public: + BoundThread(int core) { + bfAffinitySetCore(core); +#if BF_HWLOC_ENABLED + assert(_hwloc.bind_memory_to_core(core) == 0); +#endif + } +}; diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 93ef97fb7..7fe18a01e 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -37,24 +37,6 @@ #define BF_PRINTD(stmt) #endif -#if BF_HWLOC_ENABLED -int HardwareLocality::bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; -} -#endif // BF_HWLOC_ENABLED - // Reads, decodes and unpacks frames into the provided buffers // Note: Read continues until the first frame that belongs // beyond the end of the provided buffers. This frame is diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 9a917a1be..852df6932 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -30,7 +30,6 @@ #include "assert.hpp" #include -#include #include using bifrost::ring::RingWrapper; using bifrost::ring::RingWriter; @@ -38,6 +37,7 @@ using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" #include "formats/formats.hpp" +#include "hw_locality.hpp" #include // For posix_memalign #include // For memcpy, memset @@ -131,37 +131,6 @@ class AlignedBuffer { inline T const& operator[](size_t i) const { return _buf[i]; } }; -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core); -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { -#if BF_HWLOC_ENABLED - HardwareLocality _hwloc; -#endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); -#if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); -#endif - } -}; - class PacketCaptureMethod { protected: int _fd; diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index a0039143b..e4cb4cc31 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -37,24 +37,6 @@ #define BF_PRINTD(stmt) #endif -#if BF_HWLOC_ENABLED -int HardwareLocality::bind_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); - int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); - int ret = 0; - if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); - } - return ret; -} -#endif // BF_HWLOC_ENABLED - BFstatus BFpacketwriter_impl::send(BFheaderinfo desc, BFoffset seq, BFoffset seq_increment, diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 9d7e2dde2..1b8f288b9 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -28,10 +28,10 @@ #include "assert.hpp" #include -#include #include "proclog.hpp" #include "formats/formats.hpp" #include "utils.hpp" +#include "hw_locality.hpp" #include // For ntohs #include // For recvfrom @@ -47,37 +47,6 @@ #include #include -#if BF_HWLOC_ENABLED -#include -class HardwareLocality { - hwloc_topology_t _topo; - HardwareLocality(HardwareLocality const&); - HardwareLocality& operator=(HardwareLocality const&); -public: - HardwareLocality() { - hwloc_topology_init(&_topo); - hwloc_topology_load(_topo); - } - ~HardwareLocality() { - hwloc_topology_destroy(_topo); - } - int bind_memory_to_core(int core); -}; -#endif // BF_HWLOC_ENABLED - -class BoundThread { -#if BF_HWLOC_ENABLED - HardwareLocality _hwloc; -#endif -public: - BoundThread(int core) { - bfAffinitySetCore(core); -#if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); -#endif - } -}; - class PacketWriterMethod { protected: int _fd; From 1a2d3ade65812cb50a88f7e9c839bcdaef7bba74 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 5 Jul 2019 15:28:54 -0600 Subject: [PATCH 037/424] Added a frame counter to BFpacketwriter_impl and updated send to use it. Changed the interface to send to make it more intuitive. Added a new 'subbeam2' pseudo-format to get around the explicit size and datatype checking in the updated version of BFpacketwriter_impl. --- python/bifrost/packet_writer.py | 30 ++++++++------------ src/bifrost/packet_writer.h | 13 ++++----- src/disk_writer.cpp | 8 +++++- src/formats/base.hpp | 1 + src/formats/chips.hpp | 3 +- src/formats/cor.hpp | 7 +++-- src/formats/drx.hpp | 5 ++-- src/formats/tbf.hpp | 5 +++- src/formats/tbn.hpp | 16 ++++++----- src/packet_writer.cpp | 49 ++++++++++++++++++++------------- src/packet_writer.hpp | 39 ++++++++++++++++++-------- src/udp_transmit.cpp | 17 ++++++++++-- 12 files changed, 119 insertions(+), 74 deletions(-) diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 684b484b8..88853e69a 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -35,23 +35,17 @@ def __init__(self): BifrostObject.__init__( self, _bf.bfHeaderInfoCreate, _bf.bfHeaderInfoDestroy) def set_nsrc(self, nsrc): - _check(_bf.bfHeaderInfoSetNSrc(self.obj, - nsrc)) + _check(_bf.bfHeaderInfoSetNSrc(self.obj, nsrc)) def set_nchan(self, nchan): - _check(_bf.bfHeaderInfoSetNChan(self.obj, - nchan)) + _check(_bf.bfHeaderInfoSetNChan(self.obj, nchan)) def set_chan0(self, chan0): - _check(_bf.bfHeaderInfoSetChan0(self.obj, - chan0)) + _check(_bf.bfHeaderInfoSetChan0(self.obj, chan0)) def set_tuning(self, tuning): - _check(_bf.bfHeaderInfoSetTuning(self.obj, - tuning)) + _check(_bf.bfHeaderInfoSetTuning(self.obj, tuning)) def set_gain(self, gain): - _check(_bf.bfHeaderInfoSetGain(self.obj, - gain)) + _check(_bf.bfHeaderInfoSetGain(self.obj, gain)) def set_decimation(self, decimation): - _check(_bf.bfHeaderInfoSetDecimation(self.obj, - tuning)) + _check(_bf.bfHeaderInfoSetDecimation(self.obj, decimation)) class UDPTransmit(BifrostObject): def __init__(self, fmt, sock, core=None): @@ -64,15 +58,15 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, headerinfo, seq, seq_increment, seq_stride, src, src_increment, src_stride, idata): + def reset_counter(self): + _check(_bf.bfPacketWriterResetCounter(self.obj)) + def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): _check(_bf.bfPacketWriterSend(self.obj, headerinfo.obj, seq, seq_increment, - seq_stride, src, src_increment, - src_stride, asarray(idata).as_BFarray())) class DiskWriter(BifrostObject): @@ -86,14 +80,14 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def send(self, headerinfo, seq, seq_increment, seq_stride, src, src_increment, src_stride, idata): + def reset_counter(self): + _check(_bf.bfPacketWriterResetCounter(self.obj)) + def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): _check(_bf.bfPacketWriterSend(self.obj, headerinfo.obj, seq, seq_increment, - seq_stride, src, src_increment, - src_stride, asarray(idata).as_BFarray())) diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index d21edfe95..498a11b7c 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -47,22 +47,21 @@ BFstatus bfHeaderInfoSetChan0(BFheaderinfo obj, int chan0); BFstatus bfHeaderInfoSetTuning(BFheaderinfo obj, int tuning); -BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, - uint16_t gain); -BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, - uint16_t decimation); +BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, + unsigned short int gain); +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + unsigned short int decimation); typedef struct BFpacketwriter_impl* BFpacketwriter; BFstatus bfPacketWriterDestroy(BFpacketwriter obj); +BFstatus bfPacketWriterResetCounter(BFpacketwriter obj); BFstatus bfPacketWriterSend(BFpacketwriter obj, - BFheaderinfo desc, + BFheaderinfo info, BFoffset seq, BFoffset seq_increment, - BFoffset seq_stride, BFoffset src, BFoffset src_increment, - BFoffset src_stride, BFarray const* in); #ifdef __cplusplus diff --git a/src/disk_writer.cpp b/src/disk_writer.cpp index 07e380fac..9c2eca182 100644 --- a/src/disk_writer.cpp +++ b/src/disk_writer.cpp @@ -84,9 +84,12 @@ BFstatus bfDiskWriterCreate(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; + } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { + int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); + nsamples = 4*nchan; } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); - nsamples = (8*4*nchan); + nsamples = 4*nchan; } else if( format == std::string("tbn") ) { nsamples = 512; } else if( format == std::string("drx") ) { @@ -104,6 +107,9 @@ BFstatus bfDiskWriterCreate(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_chips_impl(writer, nsamples), *obj = 0); + } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam2_impl(writer, nsamples), + *obj = 0); } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_cor_impl(writer, nsamples), *obj = 0); diff --git a/src/formats/base.hpp b/src/formats/base.hpp index c4e5ea6aa..2f5ec1679 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -103,5 +103,6 @@ class PacketHeaderFiller { public: virtual inline int get_size() { return 0; } virtual inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) {} }; diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 9e050ef7a..013dcf08c 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -169,6 +169,7 @@ class CHIPSHeaderFiller : virtual public PacketHeaderFiller { public: inline int get_size() { return sizeof(chips_hdr_type); } inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) { chips_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(chips_hdr_type)); @@ -180,6 +181,6 @@ class CHIPSHeaderFiller : virtual public PacketHeaderFiller { header->subband = 0; // Should be changable? header->nroach = hdr_base->nsrc; header->chan0 = htons(hdr_base->chan0); - header->seq = htobe64(hdr_base->seq + 1); + header->seq = htobe64(hdr_base->seq); } }; diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 1ca350322..fb980168d 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -157,6 +157,7 @@ class CORHeaderFiller : virtual public PacketHeaderFiller { public: inline int get_size() { return sizeof(cor_hdr_type); } inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) { cor_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(cor_hdr_type)); @@ -172,9 +173,9 @@ class CORHeaderFiller : virtual public PacketHeaderFiller { int stand1 = hdr_base->src - stand0*(2*(N-1)+1-stand0)/2 + stand0; header->sync_word = 0x5CDEC0DE; - header->frame_count_word = htobe32(((hdr_base->tuning & 0xFFFFFF) << 8)\ - | 0x02); // bits 9-32 are the server identifier - // bits 1-8 are the COR packet flag + // Bits 9-32 are the server identifier; bits 1-8 are the COR packet flag + header->frame_count_word = htobe32((hdr_base->tuning & 0xFFFFFF) \ + | ((uint32_t) 0x02 << 24)); header->first_chan = htons(hdr_base->chan0); header->gain = htons(hdr_base->gain); header->time_tag = htobe64(hdr_base->seq); diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 620c3315e..cea75e1fc 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -133,13 +133,14 @@ class DRXHeaderFiller : virtual public PacketHeaderFiller { public: inline int get_size() { return sizeof(drx_hdr_type); } inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) { drx_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(drx_hdr_type)); header->sync_word = 0x5CDEC0DE; - header->frame_count_word = htobe32(hdr_base->src & 0xFD); // ID is the lower 8 bits; - // bit 2 is reserved + // ID is stored in the lower 8 bits; bit 2 is reserved + header->frame_count_word = htobe32(hdr_base->src & 0xFD); header->decimation = htobe16(hdr_base->decimation); header->time_offset = 0; header->time_tag = htobe64(hdr_base->seq); diff --git a/src/formats/tbf.hpp b/src/formats/tbf.hpp index 01bd08637..772d68def 100644 --- a/src/formats/tbf.hpp +++ b/src/formats/tbf.hpp @@ -46,12 +46,15 @@ class TBFHeaderFiller : virtual public PacketHeaderFiller { public: inline int get_size() { return sizeof(tbf_hdr_type); } inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) { tbf_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(tbf_hdr_type)); header->sync_word = 0x5CDEC0DE; - header->frame_count_word = htobe32(0x01); // bits 1-8 are the COR packet flag + // Bits 9-32 are the frame count; bits 1-8 are the TBF packet flag + header->frame_count_word = htobe32((framecount & 0xFFFFFF) \ + | ((uint32_t) 0x01 << 24)); header->first_chan = htons(hdr_base->src); header->time_tag = htobe64(hdr_base->seq); } diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index 23e0a0185..43cc1c4e5 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -127,16 +127,18 @@ class TBNHeaderFiller : virtual public PacketHeaderFiller { public: inline int get_size() { return sizeof(tbn_hdr_type); } inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, char* hdr) { tbn_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(tbn_hdr_type)); - header->sync_word = 0x5CDEC0DE; - header->tuning_word = htobe32(hdr_base->tuning); - header->tbn_id = (htobe16(hdr_base->src + 1) & 0xFFC); // ID is the upper 14 bits; - // bit 2 is reserved; - // bit 1 indicates TBW - header->gain = htobe16(hdr_base->gain); - header->time_tag = htobe64(hdr_base->seq); + header->sync_word = 0x5CDEC0DE; + // Bits 9-32 are the frame count; bits 1-8 are zero + header->frame_count_word = htobe32((framecount & 0xFFFFFF)); + header->tuning_word = htobe32(hdr_base->tuning); + // ID is the upper 14 bits; bit 2 is reserved; bit 1 is the TBW flag + header->tbn_id = htons((hdr_base->src + 1) & 0x3FFF); + header->gain = htons(hdr_base->gain); + header->time_tag = htobe64(hdr_base->seq); } }; diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index e4cb4cc31..5c69c0d8c 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -37,33 +37,41 @@ #define BF_PRINTD(stmt) #endif -BFstatus BFpacketwriter_impl::send(BFheaderinfo desc, +BFstatus BFpacketwriter_impl::send(BFheaderinfo info, BFoffset seq, BFoffset seq_increment, - BFoffset seq_stride, BFoffset src, BFoffset src_increment, - BFoffset src_stride, BFarray const* in) { - BF_ASSERT(desc, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(info, BF_STATUS_INVALID_HANDLE); BF_ASSERT(in, BF_STATUS_INVALID_POINTER); - BF_ASSERT(in->ndim == 1, BF_STATUS_INVALID_SHAPE); + BF_ASSERT(in->dtype == _dtype, BF_STATUS_INVALID_DTYPE); + BF_ASSERT(in->ndim == 3, BF_STATUS_INVALID_SHAPE); + BF_ASSERT(in->shape[2] == _nsamples, BF_STATUS_INVALID_SHAPE); + BF_ASSERT(is_contiguous(in), BF_STATUS_UNSUPPORTED_STRIDE); + BF_ASSERT(space_accessible_from(in->space, BF_SPACE_SYSTEM), + BF_STATUS_UNSUPPORTED_SPACE); - PacketDesc* hdr_base = desc->get_description(); + PacketDesc* hdr_base = info->get_description(); + int i, j; int hdr_size = _filler->get_size(); int data_size = (BF_DTYPE_NBIT(in->dtype)/8) * _nsamples; - int npackets = in->shape[0] / _nsamples; + int npackets = in->shape[0]*in->shape[1]; char* hdrs; hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); - for(int i=0; iseq = seq + i*seq_increment/seq_stride; - hdr_base->src = src + i*src_increment/src_stride; - (*_filler)(hdr_base, hdrs+hdr_size*i); + for(i=0; ishape[0]; i++) { + hdr_base->seq = seq + i*seq_increment; + for(j=0; jshape[1]; j++) { + hdr_base->src = src + j*src_increment; + (*_filler)(hdr_base, _framecount, hdrs+hdr_size*(i*in->shape[1]+j)); + } + _framecount++; } _writer->send(hdrs, hdr_size, (char*) in->data, data_size, npackets); + this->update_stats_log(); free(hdrs); return BF_STATUS_SUCCESS; @@ -109,15 +117,15 @@ BFstatus bfHeaderInfoSetTuning(BFheaderinfo obj, return BF_STATUS_SUCCESS; } -BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, - uint16_t gain) { +BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, + unsigned short int gain) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_gain(gain); return BF_STATUS_SUCCESS; } -BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, - uint16_t decimation) { +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + unsigned short int decimation) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_decimation(decimation); return BF_STATUS_SUCCESS; @@ -129,15 +137,18 @@ BFstatus bfPacketWriterDestroy(BFpacketwriter obj) { return BF_STATUS_SUCCESS; } +BFstatus bfPacketWriterResetCounter(BFpacketwriter obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->reset_counter()); +} + BFstatus bfPacketWriterSend(BFpacketwriter obj, - BFheaderinfo desc, + BFheaderinfo info, BFoffset seq, BFoffset seq_increment, - BFoffset seq_stride, BFoffset src, BFoffset src_increment, - BFoffset src_stride, BFarray const* in) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - return obj->send(desc, seq, seq_increment, seq_stride, src, src_increment, src_stride, in); + return obj->send(info, seq, seq_increment, src, src_increment, in); } diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 1b8f288b9..205ca1314 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -127,12 +127,14 @@ class BFpacketwriter_impl { std::string _name; PacketWriterThread* _writer; PacketHeaderFiller* _filler; + int _nsamples; + BFdtype _dtype; ProcLog _bind_log; ProcLog _stat_log; pid_t _pid; - int _nsamples; + BFoffset _framecount; private: void update_stats_log() { const PacketStats* stats = _writer->get_stats(); @@ -148,22 +150,23 @@ class BFpacketwriter_impl { public: inline BFpacketwriter_impl(PacketWriterThread* writer, PacketHeaderFiller* filler, - int nsamples) + int nsamples, + BFdtype dtype) : _name(writer->get_name()), _writer(writer), _filler(filler), + _nsamples(nsamples), _dtype(dtype), _bind_log(_name+"/bind"), _stat_log(_name+"/stats"), - _nsamples(nsamples) { + _framecount(0) { _bind_log.update() << "ncore : " << 1 << "\n" << "core0 : " << _writer->get_core() << "\n"; } virtual ~BFpacketwriter_impl() {} - BFstatus send(BFheaderinfo desc, + inline void reset_counter() { _framecount = 0; } + BFstatus send(BFheaderinfo info, BFoffset seq, BFoffset seq_increment, - BFoffset seq_stride, BFoffset src, BFoffset src_increment, - BFoffset src_stride, BFarray const* in); }; @@ -172,7 +175,7 @@ class BFpacketwriter_generic_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_generic_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_U8), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new PacketHeaderFiller(); _type_log.update("type : %s\n", "generic"); @@ -184,19 +187,31 @@ class BFpacketwriter_chips_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_chips_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI4), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new CHIPSHeaderFiller(); _type_log.update("type : %s\n", "chips"); } }; +class BFpacketwriter_subbeam2_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_subbeam2_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new CHIPSHeaderFiller(); + _type_log.update("type : %s\n", "subbeam2"); + } +}; + class BFpacketwriter_cor_impl : public BFpacketwriter_impl { ProcLog _type_log; public: inline BFpacketwriter_cor_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new CORHeaderFiller(); _type_log.update("type : %s\n", "cor"); @@ -208,7 +223,7 @@ class BFpacketwriter_tbn_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_tbn_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI8), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new TBNHeaderFiller(); _type_log.update("type : %s\n", "tbn"); @@ -220,7 +235,7 @@ class BFpacketwriter_drx_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_drx_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI4), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new DRXHeaderFiller(); _type_log.update("type : %s\n", "drx"); @@ -232,7 +247,7 @@ class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_tbf_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI4), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new TBFHeaderFiller(); _type_log.update("type : %s\n", "tbf"); diff --git a/src/udp_transmit.cpp b/src/udp_transmit.cpp index 8c7e91d59..4e92c0bc8 100644 --- a/src/udp_transmit.cpp +++ b/src/udp_transmit.cpp @@ -64,7 +64,7 @@ class UDPPacketSender : public PacketWriterMethod { memset(mmsg, 0, sizeof(struct mmsghdr)*npackets); for(int i=0; i Date: Fri, 5 Jul 2019 17:01:30 -0600 Subject: [PATCH 038/424] Fixed a bug in how the DRX ID was packed into the header. --- src/formats/drx.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index cea75e1fc..5837bbd33 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -139,8 +139,8 @@ class DRXHeaderFiller : virtual public PacketHeaderFiller { memset(header, 0, sizeof(drx_hdr_type)); header->sync_word = 0x5CDEC0DE; - // ID is stored in the lower 8 bits; bit 2 is reserved - header->frame_count_word = htobe32(hdr_base->src & 0xFD); + // ID is stored in the lowest 8 bits; bit 2 is reserved + header->frame_count_word = htobe32((uint32_t) (hdr_base->src & 0xBF) << 24); header->decimation = htobe16(hdr_base->decimation); header->time_offset = 0; header->time_tag = htobe64(hdr_base->seq); From 2dbc123b7daba3026e483a2363d88e650fb26271 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 5 Jul 2019 19:30:48 -0600 Subject: [PATCH 039/424] Fixed a bug in the baseline number to stand pair mapping in the COR header filler. --- src/formats/cor.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index fb980168d..094ae4bef 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -163,14 +163,12 @@ class CORHeaderFiller : virtual public PacketHeaderFiller { memset(header, 0, sizeof(cor_hdr_type)); // Find the number of antennas needed to reach this number of baselines - int N = (sqrt(8*hdr_base->nsrc+1)-1)/2; + int N = (sqrt(8*hdr_base->nsrc+1) - 1) / 2; // Find the indices of the two stands that form this baseline - int a = -1; int b = 2 + 2*(N-1)+1; - int c = -2*hdr_base->src; - int stand0 = (int) (-b + sqrt(b*b-4*a*c))/(2*a); - int stand1 = hdr_base->src - stand0*(2*(N-1)+1-stand0)/2 + stand0; + int stand0 = (b - sqrt(b*b-8*hdr_base->src)) / 2; + int stand1 = hdr_base->src - stand0*(2*(N-1)+1-stand0)/2; header->sync_word = 0x5CDEC0DE; // Bits 9-32 are the server identifier; bits 1-8 are the COR packet flag From ae7bd8474b80afcfe62eb4584b67595e76e97fb4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 8 Jul 2019 13:07:22 -0600 Subject: [PATCH 040/424] Consolated disk_writer and udp_transmit into a single set of source files to reduce code duplication. Cleaned up the bifrost.packet_writer module to add a new _WriterBase class. --- python/bifrost/packet_writer.py | 34 +++----- src/Makefile | 2 - src/bifrost/disk_writer.h | 48 ----------- src/bifrost/packet_writer.h | 8 ++ src/bifrost/udp_transmit.h | 48 ----------- src/disk_writer.cpp | 128 ---------------------------- src/packet_writer.cpp | 14 ++++ src/packet_writer.hpp | 124 +++++++++++++++++++++++++++ src/udp_transmit.cpp | 143 -------------------------------- 9 files changed, 157 insertions(+), 392 deletions(-) delete mode 100644 src/bifrost/disk_writer.h delete mode 100644 src/bifrost/udp_transmit.h delete mode 100644 src/disk_writer.cpp delete mode 100644 src/udp_transmit.cpp diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 88853e69a..8410d028c 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -47,13 +47,7 @@ def set_gain(self, gain): def set_decimation(self, decimation): _check(_bf.bfHeaderInfoSetDecimation(self.obj, decimation)) -class UDPTransmit(BifrostObject): - def __init__(self, fmt, sock, core=None): - if core is None: - core = -1 - BifrostObject.__init__( - self, _bf.bfUdpTransmitCreate, _bf.bfPacketWriterDestroy, - fmt, sock.fileno(), core) +class _WriterBase(BifrostObject): def __enter__(self): return self def __exit__(self, type, value, tb): @@ -69,25 +63,19 @@ def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): src_increment, asarray(idata).as_BFarray())) -class DiskWriter(BifrostObject): +class UDPTransmit(_WriterBase): + def __init__(self, fmt, sock, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpTransmitCreate, _bf.bfPacketWriterDestroy, + fmt, sock.fileno(), core) + + +class DiskWriter(_WriterBase): def __init__(self, fmt, fh, core=None): if core is None: core = -1 BifrostObject.__init__( self, _bf.bfDiskWriterCreate, _bf.bfPacketWriterDestroy, fmt, fh.fileno(), core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - pass - def reset_counter(self): - _check(_bf.bfPacketWriterResetCounter(self.obj)) - def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): - _check(_bf.bfPacketWriterSend(self.obj, - headerinfo.obj, - seq, - seq_increment, - src, - src_increment, - asarray(idata).as_BFarray())) - diff --git a/src/Makefile b/src/Makefile index 045ada2d2..31e98ab03 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,8 +20,6 @@ LIBBIFROST_OBJS = \ udp_capture.o \ udp_sniffer.o \ packet_writer.o \ - disk_writer.o \ - udp_transmit.o \ unpack.o \ quantize.o \ proclog.o diff --git a/src/bifrost/disk_writer.h b/src/bifrost/disk_writer.h deleted file mode 100644 index b9a103302..000000000 --- a/src/bifrost/disk_writer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_DISK_WRITER_H_INCLUDE_GUARD_ -#define BF_DISK_WRITER_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -BFstatus bfDiskWriterCreate(BFpacketwriter* obj, - const char* format, - int fd, - int core); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_DISK_WRITER_H_INCLUDE_GUARD_ diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index 498a11b7c..c558ff39d 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -54,6 +54,14 @@ BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, typedef struct BFpacketwriter_impl* BFpacketwriter; +BFstatus bfDiskWriterCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core); +BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core); BFstatus bfPacketWriterDestroy(BFpacketwriter obj); BFstatus bfPacketWriterResetCounter(BFpacketwriter obj); BFstatus bfPacketWriterSend(BFpacketwriter obj, diff --git a/src/bifrost/udp_transmit.h b/src/bifrost/udp_transmit.h deleted file mode 100644 index 14fac3eda..000000000 --- a/src/bifrost/udp_transmit.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ -#define BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, - const char* format, - int fd, - int core); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_UDP_TRANSMIT_H_INCLUDE_GUARD_ diff --git a/src/disk_writer.cpp b/src/disk_writer.cpp deleted file mode 100644 index 9c2eca182..000000000 --- a/src/disk_writer.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include -#include "proclog.hpp" -#include "formats/formats.hpp" -#include "packet_writer.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include -#include - -class DiskPacketWriter : public PacketWriterMethod { -public: - DiskPacketWriter(int fd) - : PacketWriterMethod(fd) {} - ssize_t send_packets(char* hdrs, - int hdr_size, - char* data, - int data_size, - int npackets, - int flags=0) { - ssize_t status, nsent = 0; - for(int i=0; i -#include -#include -#include "proclog.hpp" -#include "packet_writer.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include - -class UDPPacketSender : public PacketWriterMethod { -public: - UDPPacketSender(int fd) - : PacketWriterMethod(fd) {} - ssize_t send_packets(char* hdrs, - int hdr_size, - char* data, - int data_size, - int npackets, - int flags=0) { - struct mmsghdr *mmsg = NULL; - struct iovec *iovs = NULL; - mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - iovs = (struct iovec *) malloc(sizeof(struct iovec)*2*npackets); - memset(mmsg, 0, sizeof(struct mmsghdr)*npackets); - - for(int i=0; i Date: Mon, 8 Jul 2019 13:41:14 -0600 Subject: [PATCH 041/424] Consolidated the disk_reader, udp_capture, and udp_sniffer modules under packet_capture. Cleaned up the associated Python module. --- src/Makefile | 3 - src/bifrost/disk_reader.h | 54 ---------- src/bifrost/packet_capture.h | 72 +++++++++---- src/bifrost/udp_capture.h | 55 ---------- src/bifrost/udp_sniffer.h | 55 ---------- src/disk_reader.cpp | 119 --------------------- src/packet_capture.cpp | 71 ++++++++++++ src/packet_capture.hpp | 202 ++++++++++++++++++++++++++++++++++- src/udp_capture.cpp | 174 ------------------------------ src/udp_sniffer.cpp | 176 ------------------------------ 10 files changed, 326 insertions(+), 655 deletions(-) delete mode 100644 src/bifrost/disk_reader.h delete mode 100644 src/bifrost/udp_capture.h delete mode 100644 src/bifrost/udp_sniffer.h delete mode 100644 src/disk_reader.cpp delete mode 100644 src/udp_capture.cpp delete mode 100644 src/udp_sniffer.cpp diff --git a/src/Makefile b/src/Makefile index 31e98ab03..46c50b7cc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,9 +16,6 @@ LIBBIFROST_OBJS = \ udp_socket.o \ hw_locality.o \ packet_capture.o \ - disk_reader.o \ - udp_capture.o \ - udp_sniffer.o \ packet_writer.o \ unpack.o \ quantize.o \ diff --git a/src/bifrost/disk_reader.h b/src/bifrost/disk_reader.h deleted file mode 100644 index 0b9339e01..000000000 --- a/src/bifrost/disk_reader.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_DISK_READER_H_INCLUDE_GUARD_ -#define BF_DISK_READER_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -BFstatus bfDiskReaderCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_DISK_READER_H_INCLUDE_GUARD_ diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 1d8bbde56..522bc7a00 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -35,24 +35,7 @@ extern "C" { #include -typedef struct BFpacketcapture_impl* BFpacketcapture; - -typedef enum BFpacketcapture_status_ { - BF_CAPTURE_STARTED, - BF_CAPTURE_ENDED, - BF_CAPTURE_CONTINUED, - BF_CAPTURE_CHANGED, - BF_CAPTURE_NO_DATA, - BF_CAPTURE_INTERRUPTED, - BF_CAPTURE_ERROR -} BFpacketcapture_status; - -BFstatus bfPacketCaptureDestroy(BFpacketcapture obj); -BFstatus bfPacketCaptureRecv(BFpacketcapture obj, - BFpacketcapture_status* result); -BFstatus bfPacketCaptureFlush(BFpacketcapture obj); -BFstatus bfPacketCaptureEnd(BFpacketcapture obj); -// TODO: bfPacketCaptureGetXX +// Callback setup typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); @@ -76,6 +59,59 @@ BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, BFpacketcapture_drx_sequence_callback callback); +// Capture setup + +typedef struct BFpacketcapture_impl* BFpacketcapture; + +typedef enum BFpacketcapture_status_ { + BF_CAPTURE_STARTED, + BF_CAPTURE_ENDED, + BF_CAPTURE_CONTINUED, + BF_CAPTURE_CHANGED, + BF_CAPTURE_NO_DATA, + BF_CAPTURE_INTERRUPTED, + BF_CAPTURE_ERROR +} BFpacketcapture_status; + +BFstatus bfDiskReaderCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); +BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); +BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); +BFstatus bfPacketCaptureDestroy(BFpacketcapture obj); +BFstatus bfPacketCaptureRecv(BFpacketcapture obj, + BFpacketcapture_status* result); +BFstatus bfPacketCaptureFlush(BFpacketcapture obj); +BFstatus bfPacketCaptureEnd(BFpacketcapture obj); +// TODO: bfPacketCaptureGetXX + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bifrost/udp_capture.h b/src/bifrost/udp_capture.h deleted file mode 100644 index b3f55d14f..000000000 --- a/src/bifrost/udp_capture.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_UDP_CAPTURE_H_INCLUDE_GUARD_ -#define BF_UDP_CAPTURE_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_UDP_CAPTURE_H_INCLUDE_GUARD_ diff --git a/src/bifrost/udp_sniffer.h b/src/bifrost/udp_sniffer.h deleted file mode 100644 index 457a5a514..000000000 --- a/src/bifrost/udp_sniffer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef BF_UDP_SNIFFER_H_INCLUDE_GUARD_ -#define BF_UDP_SNIFFER_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_UDP_SNIFFER_H_INCLUDE_GUARD_ diff --git a/src/disk_reader.cpp b/src/disk_reader.cpp deleted file mode 100644 index 87d6c62e4..000000000 --- a/src/disk_reader.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2017, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include -#include -using bifrost::ring::RingWrapper; -using bifrost::ring::RingWriter; -using bifrost::ring::WriteSpan; -using bifrost::ring::WriteSequence; -#include "proclog.hpp" -#include "formats/formats.hpp" -#include "packet_capture.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include -#include - -class DiskPacketReader : public PacketCaptureMethod { -public: - DiskPacketReader(int fd, size_t pkt_size_max=9000) - : PacketCaptureMethod(fd, pkt_size_max) {} - int recv_packet(uint8_t** pkt_ptr, int flags=0) { - *pkt_ptr = &_buf[0]; - return ::read(_fd, &_buf[0], _buf.size()); - } - inline const char* get_name() { return "disk_reader"; } -}; - -BFstatus bfDiskReaderCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core) { - BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - - size_t max_payload_size = JUMBO_FRAME_SIZE; - if( std::string(format).substr(0, 6) == std::string("chips_") ) { - int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); - max_payload_size = sizeof(chips_hdr_type) + 32*nchan; - } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { - int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); - max_payload_size = sizeof(cor_hdr_type) + (8*4*nchan); - } else if( format == std::string("tbn") ) { - max_payload_size = TBN_FRAME_SIZE; - } else if( format == std::string("drx") ) { - max_payload_size = DRX_FRAME_SIZE; - } - - DiskPacketReader* method = new DiskPacketReader(fd, max_payload_size); - PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); - - if( std::string(format).substr(0, 6) == std::string("chips_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else { - return BF_STATUS_UNSUPPORTED; - } -} diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 7fe18a01e..28d5606a3 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -216,6 +216,77 @@ BFpacketcapture_status BFpacketcapture_impl::recv() { return ret; } +BFstatus bfDiskReaderCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { + return BFpacketcapture_create(obj, + format, + fd, + ring, + nsrc, + src0, + buffer_ntime, + slot_ntime, + sequence_callback, + core, + BF_IO_DISK); +} + +BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { + return BFpacketcapture_create(obj, + format, + fd, + ring, + nsrc, + src0, + buffer_ntime, + slot_ntime, + sequence_callback, + core, + BF_IO_UDP); +} + +BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { + return BFpacketcapture_create(obj, + format, + fd, + ring, + nsrc, + src0, + buffer_ntime, + slot_ntime, + sequence_callback, + core, + BF_IO_SNIFFER); +} + BFstatus bfPacketCaptureDestroy(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 852df6932..3dca0aa33 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -39,11 +39,19 @@ using bifrost::ring::WriteSequence; #include "formats/formats.hpp" #include "hw_locality.hpp" +#include // For ntohs +#include // For recvfrom + +#include +#include +#include #include // For posix_memalign #include // For memcpy, memset #include -#include +#include +#include +#include #include #ifndef BF_HWLOC_ENABLED @@ -146,6 +154,123 @@ class PacketCaptureMethod { inline const size_t get_max_size() {return _pkt_size_max; } }; +class DiskPacketReader : public PacketCaptureMethod { +public: + DiskPacketReader(int fd, size_t pkt_size_max=9000) + : PacketCaptureMethod(fd, pkt_size_max) {} + int recv_packet(uint8_t** pkt_ptr, int flags=0) { + *pkt_ptr = &_buf[0]; + return ::read(_fd, &_buf[0], _buf.size()); + } + inline const char* get_name() { return "disk_reader"; } +}; + +// TODO: The VMA API is returning unaligned buffers, which prevents use of SSE +#ifndef BF_VMA_ENABLED +#define BF_VMA_ENABLED 0 +//#define BF_VMA_ENABLED 1 +#endif + +#if BF_VMA_ENABLED +#include +class VMAReceiver { + int _fd; + vma_api_t* _api; + vma_packet_t* _pkt; + inline void clean_cache() { + if( _pkt ) { + _api->free_packets(_fd, _pkt, 1); + _pkt = 0; + } + } +public: + VMAReceiver(int fd) + : _fd(fd), _api(vma_get_api()), _pkt(0) {} + VMAReceiver(VMAReceiver const& other) + : _fd(other._fd), _api(other._api), _pkt(0) {} + VMAReceiver& operator=(VMAReceiver const& other) { + if( &other != this ) { + this->clean_cache(); + _fd = other._fd; + _api = other._api; + } + return *this; + } + ~VMAReceiver() { this->clean_cache(); } + inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { + this->clean_cache(); + int ret = _api->recvfrom_zcopy(_fd, buf, bufsize, &flags, 0, 0); + if( ret < 0 ) { + return ret; + } + if( flags & MSG_VMA_ZCOPY ) { + _pkt = &((vma_packets_t*)buf)->pkts[0]; + *pkt_ptr = (uint8_t*)_pkt->iov[0].iov_base; + } else { + *pkt_ptr = buf; + } + return ret; + } + inline operator bool() const { return _api != NULL; } +}; +#endif // BF_VMA_ENABLED + +class UDPPacketReceiver : public PacketCaptureMethod { +#if BF_VMA_ENABLED + VMAReceiver _vma; +#endif +public: + UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : PacketCaptureMethod(fd, pkt_size_max) +#if BF_VMA_ENABLED + , _vma(fd) +#endif + {} + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { +#if BF_VMA_ENABLED + if( _vma ) { + *pkt_ptr = 0; + return _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); + } else { +#endif + *pkt_ptr = &_buf[0]; + return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0); +#if BF_VMA_ENABLED + } +#endif + } + inline const char* get_name() { return "udp_capture"; } +}; + +class UDPPacketSniffer : public PacketCaptureMethod { +#if BF_VMA_ENABLED + VMAReceiver _vma; +#endif +public: + UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : PacketCaptureMethod(fd, pkt_size_max) +#if BF_VMA_ENABLED + , _vma(fd) +#endif + {} + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { +#if BF_VMA_ENABLED + if( _vma ) { + *pkt_ptr = 0; + int rc = _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags) - 28; + *pkt_ptr = *(pkt_ptr + 28); + return rc; + } else { +#endif + *pkt_ptr = &_buf[28]; // Offset for the IP+UDP headers + return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0) - 28; +#if BF_VMA_ENABLED + } +#endif + } + inline const char* get_name() { return "udp_sniffer"; } +}; + struct PacketStats { size_t ninvalid; size_t ninvalid_bytes; @@ -695,3 +820,78 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { _type_log.update("type : %s\n", "drx"); } }; + +typedef enum BFiomethod_ { + BF_IO_DISK = 1, + BF_IO_UDP = 2, + BF_IO_SNIFFER = 3 +} BFiomethod; + +BFstatus BFpacketcapture_create(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core, + BFiomethod backend) { + BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); + + size_t max_payload_size = JUMBO_FRAME_SIZE; + if( std::string(format).substr(0, 5) == std::string("chips") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); + max_payload_size = sizeof(chips_hdr_type) + 32*nchan; + } + } else if(std::string(format).substr(0, 3) == std::string("cor") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); + max_payload_size = sizeof(cor_hdr_type) + (8*4*nchan); + } + } else if( format == std::string("tbn") ) { + max_payload_size = TBN_FRAME_SIZE; + } else if( format == std::string("drx") ) { + max_payload_size = DRX_FRAME_SIZE; + } + + PacketCaptureMethod* method; + if( backend == BF_IO_DISK ) { + method = new DiskPacketReader(fd, max_payload_size); + } else if( backend == BF_IO_UDP ) { + method = new UDPPacketReceiver(fd, max_payload_size); + } else if( backend == BF_IO_SNIFFER ) { + method = new UDPPacketSniffer(fd, max_payload_size); + } else { + return BF_STATUS_UNSUPPORTED; + } + PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); + + if( std::string(format).substr(0, 5) == std::string("chips") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( std::string(format).substr(0, 3) == std::string("cor") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( format == std::string("tbn") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( format == std::string("drx") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else { + return BF_STATUS_UNSUPPORTED; + } +} diff --git a/src/udp_capture.cpp b/src/udp_capture.cpp deleted file mode 100644 index 21c8ffeb6..000000000 --- a/src/udp_capture.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include -#include -using bifrost::ring::RingWrapper; -using bifrost::ring::RingWriter; -using bifrost::ring::WriteSpan; -using bifrost::ring::WriteSequence; -#include "proclog.hpp" -#include "formats/formats.hpp" -#include "packet_capture.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include -#include - -// TODO: The VMA API is returning unaligned buffers, which prevents use of SSE -#ifndef BF_VMA_ENABLED -#define BF_VMA_ENABLED 0 -//#define BF_VMA_ENABLED 1 -#endif - -#if BF_VMA_ENABLED -#include -class VMAReceiver { - int _fd; - vma_api_t* _api; - vma_packet_t* _pkt; - inline void clean_cache() { - if( _pkt ) { - _api->free_packets(_fd, _pkt, 1); - _pkt = 0; - } - } -public: - VMAReceiver(int fd) - : _fd(fd), _api(vma_get_api()), _pkt(0) {} - VMAReceiver(VMAReceiver const& other) - : _fd(other._fd), _api(other._api), _pkt(0) {} - VMAReceiver& operator=(VMAReceiver const& other) { - if( &other != this ) { - this->clean_cache(); - _fd = other._fd; - _api = other._api; - } - return *this; - } - ~VMAReceiver() { this->clean_cache(); } - inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { - this->clean_cache(); - int ret = _api->recvfrom_zcopy(_fd, buf, bufsize, &flags, 0, 0); - if( ret < 0 ) { - return ret; - } - if( flags & MSG_VMA_ZCOPY ) { - _pkt = &((vma_packets_t*)buf)->pkts[0]; - *pkt_ptr = (uint8_t*)_pkt->iov[0].iov_base; - } else { - *pkt_ptr = buf; - } - return ret; - } - inline operator bool() const { return _api != NULL; } -}; -#endif // BF_VMA_ENABLED - -class UDPPacketReceiver : public PacketCaptureMethod { -#if BF_VMA_ENABLED - VMAReceiver _vma; -#endif -public: - UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max) -#if BF_VMA_ENABLED - , _vma(fd) -#endif - {} - inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { -#if BF_VMA_ENABLED - if( _vma ) { - *pkt_ptr = 0; - return _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); - } else { -#endif - *pkt_ptr = &_buf[0]; - return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0); -#if BF_VMA_ENABLED - } -#endif - } - inline const char* get_name() { return "udp_capture"; } -}; - -BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core) { - BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - - UDPPacketReceiver* method = new UDPPacketReceiver(fd, max_payload_size); - PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); - - if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("cor") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else { - return BF_STATUS_UNSUPPORTED; - } -} - diff --git a/src/udp_sniffer.cpp b/src/udp_sniffer.cpp deleted file mode 100644 index cf7fb38dc..000000000 --- a/src/udp_sniffer.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "assert.hpp" -#include -#include -#include -#include -using bifrost::ring::RingWrapper; -using bifrost::ring::RingWriter; -using bifrost::ring::WriteSpan; -using bifrost::ring::WriteSequence; -#include "proclog.hpp" -#include "formats/formats.hpp" -#include "packet_capture.hpp" - -#include // For ntohs -#include // For recvfrom - -#include -#include -#include -#include // For posix_memalign -#include // For memcpy, memset -#include - -#include -#include -#include -#include - -// TODO: The VMA API is returning unaligned buffers, which prevents use of SSE -#ifndef BF_VMA_ENABLED -#define BF_VMA_ENABLED 0 -//#define BF_VMA_ENABLED 1 -#endif - -#if BF_VMA_ENABLED -#include -class VMAReceiver { - int _fd; - vma_api_t* _api; - vma_packet_t* _pkt; - inline void clean_cache() { - if( _pkt ) { - _api->free_packets(_fd, _pkt, 1); - _pkt = 0; - } - } -public: - VMAReceiver(int fd) - : _fd(fd), _api(vma_get_api()), _pkt(0) {} - VMAReceiver(VMAReceiver const& other) - : _fd(other._fd), _api(other._api), _pkt(0) {} - VMAReceiver& operator=(VMAReceiver const& other) { - if( &other != this ) { - this->clean_cache(); - _fd = other._fd; - _api = other._api; - } - return *this; - } - ~VMAReceiver() { this->clean_cache(); } - inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { - this->clean_cache(); - int ret = _api->recvfrom_zcopy(_fd, buf, bufsize, &flags, 0, 0); - if( ret < 0 ) { - return ret; - } - if( flags & MSG_VMA_ZCOPY ) { - _pkt = &((vma_packets_t*)buf)->pkts[0]; - *pkt_ptr = (uint8_t*)_pkt->iov[0].iov_base; - } else { - *pkt_ptr = buf; - } - return ret; - } - inline operator bool() const { return _api != NULL; } -}; -#endif // BF_VMA_ENABLED - -class UDPPacketSniffer : public PacketCaptureMethod { -#if BF_VMA_ENABLED - VMAReceiver _vma; -#endif -public: - UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max) -#if BF_VMA_ENABLED - , _vma(fd) -#endif - {} - inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { -#if BF_VMA_ENABLED - if( _vma ) { - *pkt_ptr = 0; - int rc = _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags) - 28; - *pkt_ptr = *(pkt_ptr + 28); - return rc; - } else { -#endif - *pkt_ptr = &_buf[28]; // Offset for the IP+UDP headers - return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0) - 28; -#if BF_VMA_ENABLED - } -#endif - } - inline const char* get_name() { return "udp_sniffer"; } -}; - -BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core) { - BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - - UDPPacketSniffer* method = new UDPPacketSniffer(fd, max_payload_size); - PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); - - if( format == std::string("chips") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("cor") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("tbn") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( format == std::string("drx") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else { - return BF_STATUS_UNSUPPORTED; - } -} - From ec61411cc94874d716c7109de16fd80c979eec83 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 8 Jul 2019 14:37:52 -0600 Subject: [PATCH 042/424] Cleaned up a few formatting things in packet_writer.h. --- src/bifrost/packet_writer.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index c558ff39d..b600dec65 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -55,13 +55,13 @@ BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, typedef struct BFpacketwriter_impl* BFpacketwriter; BFstatus bfDiskWriterCreate(BFpacketwriter* obj, - const char* format, - int fd, - int core); + const char* format, + int fd, + int core); BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, - const char* format, - int fd, - int core); + const char* format, + int fd, + int core); BFstatus bfPacketWriterDestroy(BFpacketwriter obj); BFstatus bfPacketWriterResetCounter(BFpacketwriter obj); BFstatus bfPacketWriterSend(BFpacketwriter obj, From be5d931f175fbbf8f9c707fd82b019753fae7f0a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 8 Jul 2019 14:45:05 -0600 Subject: [PATCH 043/424] Moved packet_writer over to use the BFiomethod enum. Is this a viable path to further code cleanup? --- src/bifrost/io.h | 46 ++++++++++++++++++++++++++++++++++++++++++ src/packet_capture.hpp | 7 +------ src/packet_writer.cpp | 4 ++-- src/packet_writer.hpp | 9 ++++++--- 4 files changed, 55 insertions(+), 11 deletions(-) create mode 100644 src/bifrost/io.h diff --git a/src/bifrost/io.h b/src/bifrost/io.h new file mode 100644 index 000000000..d91a767e1 --- /dev/null +++ b/src/bifrost/io.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_IO_H_INCLUDE_GUARD_ +#define BF_IO_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum BFiomethod_ { + BF_IO_DISK = 1, + BF_IO_UDP = 2, + BF_IO_SNIFFER = 3 +} BFiomethod; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_IO_H_INCLUDE_GUARD_ diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 3dca0aa33..eb89a02b6 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -29,6 +29,7 @@ #pragma once #include "assert.hpp" +#include #include #include using bifrost::ring::RingWrapper; @@ -821,12 +822,6 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { } }; -typedef enum BFiomethod_ { - BF_IO_DISK = 1, - BF_IO_UDP = 2, - BF_IO_SNIFFER = 3 -} BFiomethod; - BFstatus BFpacketcapture_create(BFpacketcapture* obj, const char* format, int fd, diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index eefa4c3ff..a3d08998c 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -135,14 +135,14 @@ BFstatus bfDiskWriterCreate(BFpacketwriter* obj, const char* format, int fd, int core) { - return BFpacketwriter_create(obj, format, fd, core, true); + return BFpacketwriter_create(obj, format, fd, core, BF_IO_DISK); } BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, const char* format, int fd, int core) { - return BFpacketwriter_create(obj, format, fd, core, false); + return BFpacketwriter_create(obj, format, fd, core, BF_IO_UDP); } BFstatus bfPacketWriterDestroy(BFpacketwriter obj) { diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 622b11739..e294cea0f 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -27,6 +27,7 @@ */ #include "assert.hpp" +#include #include #include "proclog.hpp" #include "formats/formats.hpp" @@ -321,7 +322,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, const char* format, int fd, int core, - bool disk_based) { + BFiomethod backend) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); int nsamples = 0; @@ -345,10 +346,12 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } PacketWriterMethod* method; - if( disk_based ) { + if( backend == BF_IO_DISK ) { method = new DiskPacketWriter(fd); - } else { + } else if( backend == BF_IO_UDP ) { method = new UDPPacketSender(fd); + } else { + return BF_STATUS_UNSUPPORTED; } PacketWriterThread* writer = new PacketWriterThread(method, core); From 60d7642f650d20fe09ff6976fc06b9285d4b7c5a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 9 Jul 2019 16:06:06 -0600 Subject: [PATCH 044/424] Even more work on the COR format reader. Getting closer. --- src/formats/cor.hpp | 5 ++--- src/packet_capture.hpp | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 094ae4bef..1c9373038 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -78,7 +78,7 @@ class CORDecoder : virtual public PacketDecoder { + (server - 1); pkt->chan0 = be16toh(pkt_hdr->first_chan) \ - nchan_pkt * (server - 1); - pkt->nchan = nchan_pkt * nserver; // Stores the total number of channels + pkt->nchan = nchan_pkt; pkt->tuning = (nserver << 8) | (server - 1); // Stores the number of servers and // the server that sent this packet pkt->gain = be16toh(pkt_hdr->gain); @@ -130,8 +130,7 @@ class CORProcessor : virtual public PacketProcessor { // Convenience int bl_server = pkt->src; - int nserver = (pkt->tuning >> 8) & 0xFF; - int nchan = pkt->nchan/nserver; + int nchan = pkt->nchan; int chan = 0; for( ; chantuning >> 8) & 0xFF), _navg, _nsrc/((pkt->tuning >> 8) & 0xFF), hdr, @@ -645,7 +645,7 @@ class BFpacketcapture_cor_impl : public BFpacketcapture_impl { } _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "nchan : " << _nchan << "\n" + << "nchan : " << _nchan*((pkt->tuning >> 8) & 0xFF) << "\n" << "payload_size : " << _payload_size << "\n"; } public: From f10fe0348b3981e860f5789423fa3f9b9470904f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 10 Jul 2019 12:59:59 -0600 Subject: [PATCH 045/424] Initial work on adding support for receiving UDP multicast packets. --- python/bifrost/udp_socket.py | 2 ++ src/Socket.hpp | 31 ++++++++++++++++++++++++++++++- src/bifrost/udp_socket.h | 1 + src/udp_socket.cpp | 5 +++++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/python/bifrost/udp_socket.py b/python/bifrost/udp_socket.py index abe4595c2..00d2bcd50 100644 --- a/python/bifrost/udp_socket.py +++ b/python/bifrost/udp_socket.py @@ -36,6 +36,8 @@ def bind(self, local_addr): _check( _bf.bfUdpSocketBind(self.obj, local_addr.obj) ) def sniff(self, local_addr): _check( _bf.bfUdpSocketSniff(self.obj, local_addr.obj) ) + def multibind(self, local_addr): + _check( _bf.bfUdpSocketMultibind(self.obj, local_addr.obj) ) def connect(self, remote_addr): _check( _bf.bfUdpSocketConnect(self.obj, remote_addr.obj) ) def shutdown(self): diff --git a/src/Socket.hpp b/src/Socket.hpp index fba9edd15..615a9bdc5 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -191,6 +191,8 @@ class Socket { int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); inline void sniff(sockaddr_storage local_address, int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); + inline void multibind(sockaddr_storage local_address, + int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); // Client initialisation inline void connect(sockaddr_storage remote_address); // Accept incoming SOCK_STREAM connection requests @@ -520,7 +522,34 @@ void Socket::sniff(sockaddr_storage local_address, // Make the socket promiscuous this->set_promiscuous(true); } - +void Socket::multibind(sockaddr_storage local_address, + int max_conn_queue) { + if( _mode != Socket::MODE_CLOSED ) { + throw Socket::Error("Socket is already open"); + } + this->open(local_address.ss_family); + + // Validate + if( _type == SOCK_STREAM ) { + throw Socket::Error("SOCK_STREAM is not supported with multicast receive"); + } + + // Setup the INADDR_ANY socket base to bind to + struct sockaddr_in base_address; + memset(&base_address, 0, sizeof(sockaddr_in)); + base_address.sin_family = reinterpret_cast(&local_address)->sin_family; + base_address.sin_addr.s_addr = htonl(INADDR_ANY); + base_address.sin_port = htons(reinterpret_cast(&local_address)->sin_port); + this->bind(*reinterpret_cast(&base_address), max_conn_queue); + + // Deal with joining the multicast group + struct ip_mreq mreq; + memset(&mreq, 0, sizeof(ip_mreq)); + mreq.imr_multiaddr.s_addr = reinterpret_cast(&local_address)->sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + this->set_option(IP_ADD_MEMBERSHIP, mreq, IPPROTO_IP); + _mode = Socket::MODE_BOUND; +} // TODO: Add timeout support? Bit of a pain to implement. void Socket::connect(sockaddr_storage remote_address) { bool can_reuse = (_fd != -1 && diff --git a/src/bifrost/udp_socket.h b/src/bifrost/udp_socket.h index e773256cc..af6b7856a 100644 --- a/src/bifrost/udp_socket.h +++ b/src/bifrost/udp_socket.h @@ -42,6 +42,7 @@ BFstatus bfUdpSocketDestroy(BFudpsocket obj); BFstatus bfUdpSocketConnect(BFudpsocket obj, BFaddress remote_addr); BFstatus bfUdpSocketBind( BFudpsocket obj, BFaddress local_addr); BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr); +BFstatus bfUdpSocketMultibind( BFudpsocket obj, BFaddress local_addr); BFstatus bfUdpSocketShutdown(BFudpsocket obj); // Unblocks recv in another thread BFstatus bfUdpSocketClose(BFudpsocket obj); BFstatus bfUdpSocketSetTimeout(BFudpsocket obj, double secs); diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 61391de98..0e6e4f7e2 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -60,6 +60,11 @@ BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr) { BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); BF_TRY_RETURN(obj->sniff(*(sockaddr_storage*)local_addr)); } +BFstatus bfUdpSocketMultibind( BFudpsocket obj, BFaddress local_addr) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); + BF_TRY_RETURN(obj->multibind(*(sockaddr_storage*)local_addr)); +} BFstatus bfUdpSocketShutdown(BFudpsocket obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->shutdown()); From 90a4004d389514f8db8b155ca4936e421d4bc918 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 10 Jul 2019 13:01:06 -0600 Subject: [PATCH 046/424] Worked on cleaning up the classes in packet_capture.py. --- python/bifrost/packet_capture.py | 50 +++++++++----------------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 58dbfa619..e7148aac4 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -46,16 +46,7 @@ def set_drx(self, fnc): _check(_bf.bfPacketCaptureCallbackSetDRX( self.obj, _bf.BFpacketcapture_drx_sequence_callback(fnc))) -class UDPCapture(BifrostObject): - def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): - if core is None: - core = -1 - BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, - max_payload_size, buffer_ntime, slot_ntime, - sequence_callback.obj, core) +class _CaptureBase(BifrostObject): def __enter__(self): return self def __exit__(self, type, value, tb): @@ -69,7 +60,18 @@ def flush(self): def end(self): _check(_bf.bfPacketCaptureEnd(self.obj)) -class UDPSniffer(BifrostObject): +class UDPCapture(_CaptureBase): + def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) + +class UDPSniffer(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None): if core is None: @@ -79,20 +81,8 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.end() - def recv(self): - status = _bf.BFpacketcapture_status() - _check(_bf.bfPacketCaptureRecv(self.obj, status)) - return status.value - def flush(self): - _check(_bf.bfPacketCaptureFlush(self.obj)) - def end(self): - _check(_bf.bfPacketCaptureEnd(self.obj)) -class DiskReader(BifrostObject): +class DiskReader(_CaptureBase): def __init__(self, fmt, fh, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core=None): if core is None: @@ -102,15 +92,3 @@ def __init__(self, fmt, fh, ring, nsrc, src0, fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback.obj, core) - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.end() - def recv(self): - status = _bf.BFpacketcapture_status() - _check(_bf.bfPacketCaptureRecv(self.obj, status)) - return status.value - def flush(self): - _check(_bf.bfPacketCaptureFlush(self.obj)) - def end(self): - _check(_bf.bfPacketCaptureEnd(self.obj)) From 91bb99ef0e71d526c8cbbc35b352fd91b8efae7c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 10 Jul 2019 13:37:33 -0600 Subject: [PATCH 047/424] A little more work on IPv4 UDP multicast support. --- python/bifrost/address.py | 3 +++ src/Socket.hpp | 3 +++ src/address.cpp | 18 ++++++++++++++++++ src/bifrost/address.h | 1 + 4 files changed, 25 insertions(+) diff --git a/python/bifrost/address.py b/python/bifrost/address.py index 0baf6ecdf..839de77b2 100644 --- a/python/bifrost/address.py +++ b/python/bifrost/address.py @@ -45,6 +45,9 @@ def family(self): def port(self): return _get(_bf.bfAddressGetPort, self.obj) @property + def is_multicast(self): + return True if _get(_bf.bfAddressIsMulticast, self.obj) else False + @property def mtu(self): return _get(_bf.bfAddressGetMTU, self.obj) @property diff --git a/src/Socket.hpp b/src/Socket.hpp index 615a9bdc5..35283a3aa 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -530,6 +530,9 @@ void Socket::multibind(sockaddr_storage local_address, this->open(local_address.ss_family); // Validate + if( reinterpret_cast(&local_address)->sin_family != AF_INET ) { + throw Socket::Error("Only IPv4 is supported with multicast receive"); + } if( _type == SOCK_STREAM ) { throw Socket::Error("SOCK_STREAM is not supported with multicast receive"); } diff --git a/src/address.cpp b/src/address.cpp index 7026ecdc1..542bd1977 100644 --- a/src/address.cpp +++ b/src/address.cpp @@ -61,6 +61,24 @@ BFstatus bfAddressGetPort(BFaddress addr, int* port) { BF_TRY_RETURN_ELSE(*port = ntohs(((sockaddr_in*)addr)->sin_port), *port = 0); } +BFstatus bfAddressIsMulticast(BFaddress addr, int* multicast) { + BF_ASSERT(addr, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(multicast, BF_STATUS_INVALID_POINTER); + + // Only IPv4 for now + unsigned family; + bfAddressGetFamily(addr, &family); + + *multicast = 0; + if( family == AF_INET ) { + sockaddr_in *sa4 = reinterpret_cast(addr); + if( ((sa4->sin_addr.s_addr & 0xFF) >= 224) \ + && ((sa4->sin_addr.s_addr & 0xFF) < 240) ) { + *multicast = 1; + } + } + return BF_STATUS_SUCCESS; +} BFstatus bfAddressGetMTU(BFaddress addr, int* mtu) { BF_ASSERT(addr, BF_STATUS_INVALID_HANDLE); BF_ASSERT(mtu, BF_STATUS_INVALID_POINTER); diff --git a/src/bifrost/address.h b/src/bifrost/address.h index 83af21df8..a078f4ece 100644 --- a/src/bifrost/address.h +++ b/src/bifrost/address.h @@ -44,6 +44,7 @@ BFstatus bfAddressCreate(BFaddress* addr, BFstatus bfAddressDestroy(BFaddress addr); BFstatus bfAddressGetFamily(BFaddress addr, unsigned* family); BFstatus bfAddressGetPort(BFaddress addr, int* port); +BFstatus bfAddressIsMulticast(BFaddress addr, int* multicast); BFstatus bfAddressGetMTU(BFaddress addr, int* mtu); BFstatus bfAddressGetString(BFaddress addr, BFsize bufsize, // 128 should always be enough From be217b14d94ca328c57c880d6748491144f9c5e4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 10 Jul 2019 14:11:29 -0600 Subject: [PATCH 048/424] Merged Socket::bind() and Socket::multibind() together. Removed support for IPv6 multicast since it is tricky. --- python/bifrost/udp_socket.py | 2 - src/Socket.hpp | 85 +++++++++++++++++++----------------- src/address.cpp | 4 +- src/bifrost/udp_socket.h | 1 - src/udp_socket.cpp | 5 --- 5 files changed, 46 insertions(+), 51 deletions(-) diff --git a/python/bifrost/udp_socket.py b/python/bifrost/udp_socket.py index 00d2bcd50..abe4595c2 100644 --- a/python/bifrost/udp_socket.py +++ b/python/bifrost/udp_socket.py @@ -36,8 +36,6 @@ def bind(self, local_addr): _check( _bf.bfUdpSocketBind(self.obj, local_addr.obj) ) def sniff(self, local_addr): _check( _bf.bfUdpSocketSniff(self.obj, local_addr.obj) ) - def multibind(self, local_addr): - _check( _bf.bfUdpSocketMultibind(self.obj, local_addr.obj) ) def connect(self, remote_addr): _check( _bf.bfUdpSocketConnect(self.obj, remote_addr.obj) ) def shutdown(self): diff --git a/src/Socket.hpp b/src/Socket.hpp index 35283a3aa..f3b90324a 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -191,8 +191,6 @@ class Socket { int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); inline void sniff(sockaddr_storage local_address, int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); - inline void multibind(sockaddr_storage local_address, - int max_conn_queue=DEFAULT_MAX_CONN_QUEUE); // Client initialisation inline void connect(sockaddr_storage remote_address); // Accept incoming SOCK_STREAM connection requests @@ -463,15 +461,51 @@ void Socket::bind(sockaddr_storage local_address, #warning "Kernel version does not support SO_REUSEPORT; multithreaded send/recv will not be possible" #endif - check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), - "bind socket"); - if( _type == SOCK_STREAM ) { - check_error(::listen(_fd, max_conn_queue), - "set socket to listen"); - _mode = Socket::MODE_LISTENING; + // Determine multicast status... + int multicast = 0; + if( local_address.ss_family == AF_INET ) { + sockaddr_in *sa4 = reinterpret_cast(&local_address); + if( ((sa4->sin_addr.s_addr & 0xFF) >= 224) \ + && ((sa4->sin_addr.s_addr & 0xFF) < 240) ) { + multicast = 1; + } } - else { - _mode = Socket::MODE_BOUND; + + // ... and work accordingly + if( !multicast ) { + // Normal address + check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), + "bind socket"); + if( _type == SOCK_STREAM ) { + check_error(::listen(_fd, max_conn_queue), + "set socket to listen"); + _mode = Socket::MODE_LISTENING; + } + else { + _mode = Socket::MODE_BOUND; + } + } else { + // Multicast address + // Setup the INADDR_ANY socket base to bind to + struct sockaddr_in base_address; + memset(&base_address, 0, sizeof(sockaddr_in)); + base_address.sin_family = reinterpret_cast(&local_address)->sin_family; + base_address.sin_addr.s_addr = htonl(INADDR_ANY); + base_address.sin_port = htons(reinterpret_cast(&local_address)->sin_port); + check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), + "bind socket"); + + if( _type == SOCK_STREAM ) { + throw Socket::Error("SOCK_STREAM is not supported with multicast receive"); + } else { + // Deal with joining the multicast group + struct ip_mreq mreq; + memset(&mreq, 0, sizeof(ip_mreq)); + mreq.imr_multiaddr.s_addr = reinterpret_cast(&local_address)->sin_addr.s_addr; + mreq.imr_interface.s_addr = htonl(INADDR_ANY); + this->set_option(IP_ADD_MEMBERSHIP, mreq, IPPROTO_IP); + _mode = Socket::MODE_BOUND; + } } } void Socket::sniff(sockaddr_storage local_address, @@ -522,37 +556,6 @@ void Socket::sniff(sockaddr_storage local_address, // Make the socket promiscuous this->set_promiscuous(true); } -void Socket::multibind(sockaddr_storage local_address, - int max_conn_queue) { - if( _mode != Socket::MODE_CLOSED ) { - throw Socket::Error("Socket is already open"); - } - this->open(local_address.ss_family); - - // Validate - if( reinterpret_cast(&local_address)->sin_family != AF_INET ) { - throw Socket::Error("Only IPv4 is supported with multicast receive"); - } - if( _type == SOCK_STREAM ) { - throw Socket::Error("SOCK_STREAM is not supported with multicast receive"); - } - - // Setup the INADDR_ANY socket base to bind to - struct sockaddr_in base_address; - memset(&base_address, 0, sizeof(sockaddr_in)); - base_address.sin_family = reinterpret_cast(&local_address)->sin_family; - base_address.sin_addr.s_addr = htonl(INADDR_ANY); - base_address.sin_port = htons(reinterpret_cast(&local_address)->sin_port); - this->bind(*reinterpret_cast(&base_address), max_conn_queue); - - // Deal with joining the multicast group - struct ip_mreq mreq; - memset(&mreq, 0, sizeof(ip_mreq)); - mreq.imr_multiaddr.s_addr = reinterpret_cast(&local_address)->sin_addr.s_addr; - mreq.imr_interface.s_addr = htonl(INADDR_ANY); - this->set_option(IP_ADD_MEMBERSHIP, mreq, IPPROTO_IP); - _mode = Socket::MODE_BOUND; -} // TODO: Add timeout support? Bit of a pain to implement. void Socket::connect(sockaddr_storage remote_address) { bool can_reuse = (_fd != -1 && diff --git a/src/address.cpp b/src/address.cpp index 542bd1977..52366623d 100644 --- a/src/address.cpp +++ b/src/address.cpp @@ -65,17 +65,17 @@ BFstatus bfAddressIsMulticast(BFaddress addr, int* multicast) { BF_ASSERT(addr, BF_STATUS_INVALID_HANDLE); BF_ASSERT(multicast, BF_STATUS_INVALID_POINTER); - // Only IPv4 for now unsigned family; bfAddressGetFamily(addr, &family); - *multicast = 0; if( family == AF_INET ) { sockaddr_in *sa4 = reinterpret_cast(addr); if( ((sa4->sin_addr.s_addr & 0xFF) >= 224) \ && ((sa4->sin_addr.s_addr & 0xFF) < 240) ) { *multicast = 1; } + } else { + *multicast = 0; } return BF_STATUS_SUCCESS; } diff --git a/src/bifrost/udp_socket.h b/src/bifrost/udp_socket.h index af6b7856a..e773256cc 100644 --- a/src/bifrost/udp_socket.h +++ b/src/bifrost/udp_socket.h @@ -42,7 +42,6 @@ BFstatus bfUdpSocketDestroy(BFudpsocket obj); BFstatus bfUdpSocketConnect(BFudpsocket obj, BFaddress remote_addr); BFstatus bfUdpSocketBind( BFudpsocket obj, BFaddress local_addr); BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr); -BFstatus bfUdpSocketMultibind( BFudpsocket obj, BFaddress local_addr); BFstatus bfUdpSocketShutdown(BFudpsocket obj); // Unblocks recv in another thread BFstatus bfUdpSocketClose(BFudpsocket obj); BFstatus bfUdpSocketSetTimeout(BFudpsocket obj, double secs); diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 0e6e4f7e2..61391de98 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -60,11 +60,6 @@ BFstatus bfUdpSocketSniff( BFudpsocket obj, BFaddress local_addr) { BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); BF_TRY_RETURN(obj->sniff(*(sockaddr_storage*)local_addr)); } -BFstatus bfUdpSocketMultibind( BFudpsocket obj, BFaddress local_addr) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_ASSERT(local_addr, BF_STATUS_INVALID_ARGUMENT); - BF_TRY_RETURN(obj->multibind(*(sockaddr_storage*)local_addr)); -} BFstatus bfUdpSocketShutdown(BFudpsocket obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->shutdown()); From cc094a95a5d4b0145d57a8a2ed20bbed0eaad808 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 11 Jul 2019 09:02:09 -0600 Subject: [PATCH 049/424] Added an internal reference cache to the PacketCaptureCallback class to make sure that we don't get segfaults when Python does garbage collection. --- python/bifrost/packet_capture.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index e7148aac4..21d32b3e2 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -30,21 +30,26 @@ from libbifrost import _bf, _check, _get, BifrostObject class PacketCaptureCallback(BifrostObject): + _ref_cache = {} def __init__(self): BifrostObject.__init__( self, _bf.bfPacketCaptureCallbackCreate, _bf.bfPacketCaptureCallbackDestroy) def set_chips(self, fnc): + self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc)) _check(_bf.bfPacketCaptureCallbackSetCHIPS( - self.obj, _bf.BFpacketcapture_chips_sequence_callback(fnc))) + self.obj, self._ref_cache['chips']) def set_cor(self, fnc): + self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( - self.obj, _bf.BFpacketcapture_cor_sequence_callback(fnc))) + self.obj, self._ref_cache['cor'])) def set_tbn(self, fnc): + self._ref_cache['tbn'] = _bf.BFpacketcapture_tbn_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetTBN( - self.obj, _bf.BFpacketcapture_tbn_sequence_callback(fnc))) + self.obj, self._ref_cache['tbn'])) def set_drx(self, fnc): + self._ref_cache['drx'] = _bf.BFpacketcapture_drx_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetDRX( - self.obj, _bf.BFpacketcapture_drx_sequence_callback(fnc))) + self.obj, self._ref_cache['drx'])) class _CaptureBase(BifrostObject): def __enter__(self): From 6eab807491fe0df7bf99ca77c0a35b9be7f2bfa3 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 11 Jul 2019 09:02:57 -0600 Subject: [PATCH 050/424] Small formatting changes to the packet_capture.[ch]pp files. --- src/packet_capture.cpp | 78 +++++++++++++++++++++--------------------- src/packet_capture.hpp | 18 +++++----- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 28d5606a3..5c26fc263 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -114,6 +114,45 @@ int PacketCaptureThread::run(uint64_t seq_beg, return ret; } +BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_callback_impl(), + *obj = 0); +} + +BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, + BFpacketcapture_chips_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_chips(callback); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, + BFpacketcapture_cor_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_cor(callback); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, + BFpacketcapture_tbn_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_tbn(callback); + return BF_STATUS_SUCCESS; +} + +BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, + BFpacketcapture_drx_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_drx(callback); + return BF_STATUS_SUCCESS; +} + BFpacketcapture_status BFpacketcapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); @@ -309,42 +348,3 @@ BFstatus bfPacketCaptureEnd(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->end_writing()); } - -BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_callback_impl(), - *obj = 0); -} - -BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - delete obj; - return BF_STATUS_SUCCESS; -} - -BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, - BFpacketcapture_chips_sequence_callback callback) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - obj->set_chips(callback); - return BF_STATUS_SUCCESS; -} - -BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, - BFpacketcapture_cor_sequence_callback callback) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - obj->set_cor(callback); - return BF_STATUS_SUCCESS; -} - -BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, - BFpacketcapture_tbn_sequence_callback callback) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - obj->set_tbn(callback); - return BF_STATUS_SUCCESS; -} - -BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, - BFpacketcapture_drx_sequence_callback callback) { - BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - obj->set_drx(callback); - return BF_STATUS_SUCCESS; -} diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 1b3730463..28e14e18b 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -629,7 +629,7 @@ class BFpacketcapture_cor_impl : public BFpacketcapture_impl { *time_tag, _chan0, _nchan*((pkt->tuning >> 8) & 0xFF), - _navg, + _navg, _nsrc/((pkt->tuning >> 8) & 0xFF), hdr, hdr_size); @@ -868,23 +868,23 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, if( std::string(format).substr(0, 5) == std::string("chips") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), + buffer_ntime, slot_ntime, + sequence_callback), *obj = 0); } else if( std::string(format).substr(0, 3) == std::string("cor") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), + buffer_ntime, slot_ntime, + sequence_callback), *obj = 0); } else if( format == std::string("tbn") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), + buffer_ntime, slot_ntime, + sequence_callback), *obj = 0); } else if( format == std::string("drx") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx_impl(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), + buffer_ntime, slot_ntime, + sequence_callback), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; From 5778178b8483af63387d20907abb5f14910efcd2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 11 Jul 2019 09:07:48 -0600 Subject: [PATCH 051/424] Typo. --- python/bifrost/packet_capture.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 21d32b3e2..daf4de978 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -35,9 +35,9 @@ def __init__(self): BifrostObject.__init__( self, _bf.bfPacketCaptureCallbackCreate, _bf.bfPacketCaptureCallbackDestroy) def set_chips(self, fnc): - self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc)) + self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( - self.obj, self._ref_cache['chips']) + self.obj, self._ref_cache['chips'])) def set_cor(self, fnc): self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( From 288b353e7a91b54b414aaefb31c2a0fb146981cf Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 31 Jul 2019 10:27:16 -0600 Subject: [PATCH 052/424] Added support for seek and tell operations for BFpacketcapture objects. This is avaliable for all I/O modes but only exposed in the Python API for the disk-based objects. Also, worked on getting VDIF support to actually work. Full VDIF support, at least for LWA/eLWA, will require some tweaks to the Bifrost data types to deal with i4 data. --- python/bifrost/packet_capture.py | 14 +++ src/bifrost/io.h | 9 ++ src/bifrost/packet_capture.h | 10 +++ src/formats/formats.hpp | 1 + src/packet_capture.cpp | 19 +++- src/packet_capture.hpp | 146 ++++++++++++++++++++++++++++--- 6 files changed, 188 insertions(+), 11 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index daf4de978..8485916e3 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -29,6 +29,8 @@ from libbifrost import _bf, _check, _get, BifrostObject +import ctypes + class PacketCaptureCallback(BifrostObject): _ref_cache = {} def __init__(self): @@ -42,6 +44,10 @@ def set_cor(self, fnc): self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( self.obj, self._ref_cache['cor'])) + def set_vdif(self, fnc): + self._ref_cache['vdif'] = _bf.BFpacketcapture_vdif_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetVDIF( + self.obj, self._ref_cache['vdif'])) def set_tbn(self, fnc): self._ref_cache['tbn'] = _bf.BFpacketcapture_tbn_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetTBN( @@ -97,3 +103,11 @@ def __init__(self, fmt, fh, ring, nsrc, src0, fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback.obj, core) + def seek(self, offset, whence=_bf.BF_WHENCE_CUR): + position = ctypes.c_ulong(0) + _check(_bf.bfPacketCaptureSeek(self.obj, offset, whence, position)) + return position.value + def tell(self): + position = ctypes.c_ulong(0) + _check(_bf.bfPacketCaptureTell(self.obj, position)) + return position.value diff --git a/src/bifrost/io.h b/src/bifrost/io.h index d91a767e1..086dc8de7 100644 --- a/src/bifrost/io.h +++ b/src/bifrost/io.h @@ -29,16 +29,25 @@ #ifndef BF_IO_H_INCLUDE_GUARD_ #define BF_IO_H_INCLUDE_GUARD_ +#include + #ifdef __cplusplus extern "C" { #endif typedef enum BFiomethod_ { + BF_IO_GENERIC = 0, BF_IO_DISK = 1, BF_IO_UDP = 2, BF_IO_SNIFFER = 3 } BFiomethod; +typedef enum BFiowhence_ { + BF_WHENCE_SET = SEEK_SET, + BF_WHENCE_CUR = SEEK_CUR, + BF_WHENCE_END = SEEK_END +} BFiowhence; + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 522bc7a00..5e4231f07 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -41,6 +41,8 @@ typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); +typedef int (*BFpacketcapture_vdif_sequence_callback)(BFoffset, BFoffset, int, int, int, + int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, void const**, size_t*); typedef int (*BFpacketcapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, @@ -54,6 +56,8 @@ BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, BFpacketcapture_cor_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetVDIF(BFpacketcapture_callback obj, + BFpacketcapture_vdif_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, BFpacketcapture_tbn_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, @@ -109,6 +113,12 @@ BFstatus bfPacketCaptureDestroy(BFpacketcapture obj); BFstatus bfPacketCaptureRecv(BFpacketcapture obj, BFpacketcapture_status* result); BFstatus bfPacketCaptureFlush(BFpacketcapture obj); +BFstatus bfPacketCaptureSeek(BFpacketcapture obj, + BFoffset offset, + BFiowhence whence, + BFoffset* position); +BFstatus bfPacketCaptureTell(BFpacketcapture obj, + BFoffset* position); BFstatus bfPacketCaptureEnd(BFpacketcapture obj); // TODO: bfPacketCaptureGetXX diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 4ab419dea..afc491a29 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -30,6 +30,7 @@ #include "chips.hpp" #include "cor.hpp" +#include "vdif.hpp" #include "drx.hpp" #include "tbn.hpp" #include "tbf.hpp" diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 5c26fc263..2faea6f92 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -139,6 +139,13 @@ BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetVDIF(BFpacketcapture_callback obj, + BFpacketcapture_vdif_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_vdif(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, BFpacketcapture_tbn_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); @@ -340,8 +347,18 @@ BFstatus bfPacketCaptureRecv(BFpacketcapture obj, } BFstatus bfPacketCaptureFlush(BFpacketcapture obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->flush()); +} + +BFstatus bfPacketCaptureSeek(BFpacketcapture obj, BFoffset offset, BFiowhence whence, BFoffset* position) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->flush()); + BF_TRY_RETURN(*position = obj->seek(offset, whence)); +} + +BFstatus bfPacketCaptureTell(BFpacketcapture obj, BFoffset* position) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(*position = obj->tell()); } BFstatus bfPacketCaptureEnd(BFpacketcapture obj) { diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 28e14e18b..33d8c73b6 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -145,25 +145,32 @@ class PacketCaptureMethod { int _fd; size_t _pkt_size_max; AlignedBuffer _buf; + BFiomethod _io_method; public: - PacketCaptureMethod(int fd, size_t pkt_size_max=9000) - : _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max) {} + PacketCaptureMethod(int fd, size_t pkt_size_max=9000, BFiomethod io_method=BF_IO_GENERIC) + : _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max), _io_method(io_method) {} virtual int recv_packet(uint8_t** pkt_ptr, int flags=0) { return 0; } virtual const char* get_name() { return "generic_capture"; } - inline const size_t get_max_size() {return _pkt_size_max; } + inline const size_t get_max_size() { return _pkt_size_max; } + inline const BFiomethod get_io_method() { return _io_method; } + virtual inline BFoffset seek(BFoffset offset, BFiowhence whence=BF_WHENCE_CUR) { return 0; } + inline BFoffset tell() { return this->seek(0, BF_WHENCE_CUR); } }; class DiskPacketReader : public PacketCaptureMethod { public: DiskPacketReader(int fd, size_t pkt_size_max=9000) - : PacketCaptureMethod(fd, pkt_size_max) {} + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_DISK) {} int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); } inline const char* get_name() { return "disk_reader"; } + inline BFoffset seek(BFoffset offset, BFiowhence whence=BF_WHENCE_CUR) { + return ::lseek64(_fd, offset, whence); + } }; // TODO: The VMA API is returning unaligned buffers, which prevents use of SSE @@ -222,7 +229,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -249,7 +256,7 @@ class UDPPacketSniffer : public PacketCaptureMethod { #endif public: UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_SNIFFER) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -314,7 +321,10 @@ class PacketCaptureThread : public BoundThread { PPC* process); inline const char* get_name() { return _method->get_name(); } inline const size_t get_max_size() { return _method->get_max_size(); } + inline const BFiomethod get_io_method() { return _method->get_io_method(); } inline const int get_core() { return _core; } + inline BFoffset seek(BFoffset offset, BFiowhence whence=BF_WHENCE_CUR) { return _method->seek(offset, whence); } + inline BFoffset tell() { return _method->tell(); } inline const PacketDesc* get_last_packet() const { return _have_pkt ? &_pkt : NULL; } @@ -340,12 +350,14 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { class BFpacketcapture_callback_impl { BFpacketcapture_chips_sequence_callback _chips_callback; - BFpacketcapture_cor_sequence_callback _cor_callback; - BFpacketcapture_tbn_sequence_callback _tbn_callback; - BFpacketcapture_drx_sequence_callback _drx_callback; + BFpacketcapture_cor_sequence_callback _cor_callback; + BFpacketcapture_vdif_sequence_callback _vdif_callback; + BFpacketcapture_tbn_sequence_callback _tbn_callback; + BFpacketcapture_drx_sequence_callback _drx_callback; public: BFpacketcapture_callback_impl() - : _chips_callback(NULL), _cor_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} + : _chips_callback(NULL), _cor_callback(NULL), _vdif_callback(NULL), + _tbn_callback(NULL), _drx_callback(NULL) {} inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } @@ -358,6 +370,12 @@ class BFpacketcapture_callback_impl { inline BFpacketcapture_cor_sequence_callback get_cor() { return _cor_callback; } + inline void set_vdif(BFpacketcapture_vdif_sequence_callback callback) { + _vdif_callback = callback; + } + inline BFpacketcapture_vdif_sequence_callback get_vdif() { + return _vdif_callback; + } inline void set_tbn(BFpacketcapture_tbn_sequence_callback callback) { _tbn_callback = callback; } @@ -510,6 +528,18 @@ class BFpacketcapture_impl { this->end_sequence(); } } + inline BFoffset seek(BFoffset offset, BFiowhence whence=BF_WHENCE_CUR) { + BF_ASSERT(_capture->get_io_method() == BF_IO_DISK, BF_STATUS_UNSUPPORTED); + std::cout << "Here with " << offset << " and " << whence << " from " << _capture->tell() << std::endl; + BFoffset moved = _capture->seek(offset, whence); + std::cout << "-> Moved to " << moved << std::endl; + this->flush(); + return moved; + } + inline BFoffset tell() { + BF_ASSERT(_capture->get_io_method() == BF_IO_DISK, BF_STATUS_UNSUPPORTED); + return _capture->tell(); + } inline void end_writing() { this->flush(); _oring.close(); @@ -666,6 +696,91 @@ class BFpacketcapture_cor_impl : public BFpacketcapture_impl { } }; +class BFpacketcapture_vdif_impl : public BFpacketcapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_vdif_sequence_callback _sequence_callback; + + BFoffset _time_tag; + int _tuning; + int _sample_rate; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest time_tag, tuning = " << pkt->time_tag << ", " << pkt->tuning << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return ((pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan) \ + || (pkt->tuning != _tuning)); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _tuning = pkt->tuning; + _sample_rate = pkt->sync; + _payload_size = pkt->payload_size; + + int ref_epoch = (_tuning >> 16) & 0xFF; + int bit_depth = (_tuning >> 8) & 0xFF; + int is_complex = (_tuning & 1); + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + *time_tag, + ref_epoch, + _sample_rate, + _chan0, + bit_depth, + is_complex, + _nsrc, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "nchan : " << _chan0 << "\n" + << "bitdepth : " << bit_depth << "\n" + << "complex : " << is_complex << "\n" + << "payload_size : " << (_payload_size*8) << "\n"; + } +public: + inline BFpacketcapture_vdif_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_vdif()) { + _decoder = new VDIFDecoder(nsrc, src0); + _processor = new VDIFProcessor(); + _type_log.update("type : %s\n", "vdif"); + } +}; + class BFpacketcapture_tbn_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; @@ -848,6 +963,12 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); max_payload_size = sizeof(cor_hdr_type) + (8*4*nchan); } + } else if(std::string(format).substr(0, 4) == std::string("vdif") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(5, std::string(format).length())).c_str()); + max_payload_size = nchan; + } } else if( format == std::string("tbn") ) { max_payload_size = TBN_FRAME_SIZE; } else if( format == std::string("drx") ) { @@ -876,6 +997,11 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( std::string(format).substr(0, 4) == std::string("vdif") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_vdif_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else if( format == std::string("tbn") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_tbn_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, From 0beb0ddca5884921db1068424d4f7e8690680077 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 16 Aug 2019 15:18:17 -0600 Subject: [PATCH 053/424] Added basic unit tests for the disk and UDP socket writers. --- test/test_disk_io.py | 92 ++++++++++++++++++++++++++++++++++++++++++++ test/test_udp_io.py | 89 ++++++++++++++++++++++++++++++++++++++++++ test/travis.sh | 2 + 3 files changed, 183 insertions(+) create mode 100644 test/test_disk_io.py create mode 100644 test/test_udp_io.py diff --git a/test/test_disk_io.py b/test/test_disk_io.py new file mode 100644 index 000000000..0b6420bbb --- /dev/null +++ b/test/test_disk_io.py @@ -0,0 +1,92 @@ +# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +import os +import bifrost as bf +from bifrost.packet_writer import HeaderInfo, DiskWriter +from bifrost.packet_capture import DiskReader +from bifrost.quantize import quantize +import numpy as np + + +class DiskIOTest(unittest.TestCase): + """Test simple IO for the disk-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(128*4096*2) + w = 0.01 + self.s0 = 6*np.cos(w * t, dtype='float32') \ + + 5j*np.sin(w * t, dtype='float32') + + def test_write_tbn(self): + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(500) + + fh = open('test_tbn.dat', 'wb') + op = DiskWriter('tbn', fh) + + # Reorder as packets, stands, time + data = self.s0.reshape(512,32,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci8 for TBN + data_q = bf.ndarray(shape=data.shape, dtype='ci8') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + fh.close() + + self.assertEqual(os.path.getsize('test_tbn.dat'), \ + 1048*data_q.shape[0]*data_q.shape[1]) + os.unlink('test_tbn.dat') + + def test_write_drx(self): + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(10) + + fh = open('test_drx.dat', 'wb') + op = DiskWriter('drx', fh) + + # Reorder as packets, beams, time + data = self.s0.reshape(4096,4,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci4 for DRX + data_q = bf.ndarray(shape=data.shape, dtype='ci4') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + fh.close() + + self.assertEqual(os.path.getsize('test_drx.dat'), \ + 4128*data_q.shape[0]*data_q.shape[1]) + os.unlink('test_drx.dat') diff --git a/test/test_udp_io.py b/test/test_udp_io.py new file mode 100644 index 000000000..c85d47576 --- /dev/null +++ b/test/test_udp_io.py @@ -0,0 +1,89 @@ +# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import unittest +import os +import bifrost as bf +from bifrost.address import Address +from bifrost.udp_socket import UDPSocket +from bifrost.packet_writer import HeaderInfo, UDPTransmit +from bifrost.packet_capture import UDPCapture +from bifrost.quantize import quantize +import numpy as np + + +class UDPIOTest(unittest.TestCase): + """Test simple IO for the UDP-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(128*4096*2) + w = 0.01 + self.s0 = 6*np.cos(w * t, dtype='float32') \ + + 5j*np.sin(w * t, dtype='float32') + + def test_write_tbn(self): + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(500) + + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Reorder as packets, stands, time + data = self.s0.reshape(512,32,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci8 for TBN + data_q = bf.ndarray(shape=data.shape, dtype='ci8') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + sock.close() + + def test_write_drx(self): + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(10) + + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Reorder as packets, beams, time + data = self.s0.reshape(4096,4,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci4 for DRX + data_q = bf.ndarray(shape=data.shape, dtype='ci4') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) diff --git a/test/travis.sh b/test/travis.sh index 1eb7f8a82..fed4c8c26 100755 --- a/test/travis.sh +++ b/test/travis.sh @@ -12,4 +12,6 @@ coverage run --source=bifrost.ring,bifrost,bifrost.pipeline -m unittest \ test_pipeline_cpu \ test_serialize \ test_binary_io \ + test_disk_io \ + test_udp_io \ test_address From 8dad544e0697876f680595a9506f503ef7528689 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 16 Aug 2019 15:34:46 -0600 Subject: [PATCH 054/424] Cleaned up the new unit tests and also added file cleanup to test_binary_io and test_disk_io. --- test/test_binary_io.py | 5 +++ test/test_disk_io.py | 100 ++++++++++++++++++++++------------------- test/test_udp_io.py | 84 +++++++++++++++++----------------- 3 files changed, 100 insertions(+), 89 deletions(-) diff --git a/test/test_binary_io.py b/test/test_binary_io.py index ddc117627..a02f55a69 100644 --- a/test/test_binary_io.py +++ b/test/test_binary_io.py @@ -25,6 +25,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import unittest +import os import bifrost as bf import numpy as np from bifrost import blocks @@ -97,3 +98,7 @@ def data_callback(ispan, ospan): callback = CallbackBlock(b_read, seq_callback, data_callback) pipeline.run() + def tearDown(self): + for filename in self.filenames: + os.unlink(filename) + os.unlink(filename+".out") \ No newline at end of file diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 0b6420bbb..f1c339ac4 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -41,52 +41,58 @@ def setUp(self): t = np.arange(128*4096*2) w = 0.01 self.s0 = 6*np.cos(w * t, dtype='float32') \ - + 5j*np.sin(w * t, dtype='float32') - + + 5j*np.sin(w * t, dtype='float32') + # Filename cache so we can cleanup later + self._cache = [] + def _open(self, filename, mode): + fh = open(filename, mode) + if filename not in self._cache: + self._cache.append(filename) + return fh def test_write_tbn(self): - desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(500) - - fh = open('test_tbn.dat', 'wb') - op = DiskWriter('tbn', fh) - - # Reorder as packets, stands, time - data = self.s0.reshape(512,32,-1) - data = data.transpose(2,1,0).copy() - # Convert to ci8 for TBN - data_q = bf.ndarray(shape=data.shape, dtype='ci8') - quantize(data, data_q) - - # Go! - desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) - fh.close() - - self.assertEqual(os.path.getsize('test_tbn.dat'), \ - 1048*data_q.shape[0]*data_q.shape[1]) - os.unlink('test_tbn.dat') - + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(500) + + fh = self._open('test_tbn.dat', 'wb') + op = DiskWriter('tbn', fh) + + # Reorder as packets, stands, time + data = self.s0.reshape(512,32,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci8 for TBN + data_q = bf.ndarray(shape=data.shape, dtype='ci8') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + fh.close() + + self.assertEqual(os.path.getsize('test_tbn.dat'), \ + 1048*data_q.shape[0]*data_q.shape[1]) def test_write_drx(self): - desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(10) - - fh = open('test_drx.dat', 'wb') - op = DiskWriter('drx', fh) - - # Reorder as packets, beams, time - data = self.s0.reshape(4096,4,-1) - data = data.transpose(2,1,0).copy() - # Convert to ci4 for DRX - data_q = bf.ndarray(shape=data.shape, dtype='ci4') - quantize(data, data_q) - - # Go! - desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) - fh.close() - - self.assertEqual(os.path.getsize('test_drx.dat'), \ - 4128*data_q.shape[0]*data_q.shape[1]) - os.unlink('test_drx.dat') + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(10) + + fh = self._open('test_drx.dat', 'wb') + op = DiskWriter('drx', fh) + + # Reorder as packets, beams, time + data = self.s0.reshape(4096,4,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci4 for DRX + data_q = bf.ndarray(shape=data.shape, dtype='ci4') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + fh.close() + + self.assertEqual(os.path.getsize('test_drx.dat'), \ + 4128*data_q.shape[0]*data_q.shape[1]) + def tearDown(self): + for filename in self._cache: + os.unlink(filename) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index c85d47576..d863422be 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -43,47 +43,47 @@ def setUp(self): t = np.arange(128*4096*2) w = 0.01 self.s0 = 6*np.cos(w * t, dtype='float32') \ - + 5j*np.sin(w * t, dtype='float32') - + + 5j*np.sin(w * t, dtype='float32') + def test_write_tbn(self): - desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(500) - - addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Reorder as packets, stands, time - data = self.s0.reshape(512,32,-1) - data = data.transpose(2,1,0).copy() - # Convert to ci8 for TBN - data_q = bf.ndarray(shape=data.shape, dtype='ci8') - quantize(data, data_q) - - # Go! - desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) - sock.close() - + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(500) + + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Reorder as packets, stands, time + data = self.s0.reshape(512,32,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci8 for TBN + data_q = bf.ndarray(shape=data.shape, dtype='ci8') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) + sock.close() + def test_write_drx(self): - desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(10) - - addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('drx', sock) - - # Reorder as packets, beams, time - data = self.s0.reshape(4096,4,-1) - data = data.transpose(2,1,0).copy() - # Convert to ci4 for DRX - data_q = bf.ndarray(shape=data.shape, dtype='ci4') - quantize(data, data_q) - - # Go! - desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) + desc = HeaderInfo() + desc.set_chan0(1) + desc.set_decimation(10) + + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Reorder as packets, beams, time + data = self.s0.reshape(4096,4,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci4 for DRX + data_q = bf.ndarray(shape=data.shape, dtype='ci4') + quantize(data, data_q) + + # Go! + desc.set_nsrc(data_q.shape[1]) + op.send(desc, 0, 1, 0, 1, data_q) From 31b26e6aed880f283e3dadc618ba83b837881288 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 29 Aug 2019 16:24:16 -0600 Subject: [PATCH 055/424] Fixed a few problems with the DRX and TBN packet readers. Changed the DRX and TBN callback functions to include a slot for the bandwidth. --- src/bifrost/packet_capture.h | 4 ++-- src/formats/drx.hpp | 3 +++ src/formats/tbn.hpp | 40 +++++++++++++++++++++++++++++---- src/packet_capture.hpp | 43 ++++++++++++++++++++++-------------- 4 files changed, 67 insertions(+), 23 deletions(-) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 5e4231f07..5897690ab 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -44,9 +44,9 @@ typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, in typedef int (*BFpacketcapture_vdif_sequence_callback)(BFoffset, BFoffset, int, int, int, int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_tbn_sequence_callback)(BFoffset, BFoffset, int, int, - void const**, size_t*); + int, void const**, size_t*); typedef int (*BFpacketcapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, - void const**, size_t*); + int, void const**, size_t*); typedef struct BFpacketcapture_callback_impl* BFpacketcapture_callback; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 5837bbd33..5bdc4652a 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -67,6 +67,9 @@ class DRXDecoder : virtual public PacketDecoder { int pkt_id = pkt_hdr->frame_count_word & 0xFF; pkt->beam = (pkt_id & 0x7) - 1; int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; + if( _nsrc == 2 ) { + pkt_tune = 0; + } int pkt_pol = ((pkt_id >> 7) & 0x1); pkt_id = (pkt_tune << 1) | pkt_pol; pkt->sync = pkt_hdr->sync_word; diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index 43cc1c4e5..6dc02f709 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -42,7 +42,32 @@ struct tbn_hdr_type { uint64_t time_tag; }; +class TBNCache { + uint64_t _timestamp_last = 0; + int _pid_last = -1000; + uint16_t _decimation = 1; + bool _active = false; +public: + TBNCache() {} + inline uint16_t get_decimation() { return _decimation; } + inline bool update(int packet_id, + uint64_t timestamp) { + if( !_active ) { + if( packet_id == _pid_last ) { + _decimation = ((timestamp - _timestamp_last) / 512); + _active = true; + } else if( _pid_last == -1000 ) { + _pid_last = packet_id; + _timestamp_last = timestamp; + } + } + return _active; + } +}; + class TBNDecoder : virtual public PacketDecoder { + TBNCache* _cache; + inline bool valid_packet(const PacketDesc* pkt) const { return (pkt->sync == 0x5CDEC0DE && pkt->src >= 0 && @@ -52,7 +77,10 @@ class TBNDecoder : virtual public PacketDecoder { pkt->valid_mode == 0); } public: - TBNDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + TBNDecoder(int nsrc, int src0) + : PacketDecoder(nsrc, src0) { + _cache = new TBNCache(); + } inline bool operator()(const uint8_t* pkt_ptr, int pkt_size, PacketDesc* pkt) const { @@ -64,16 +92,20 @@ class TBNDecoder : virtual public PacketDecoder { int pld_size = pkt_size - sizeof(tbn_hdr_type); pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag); - pkt->seq = pkt->time_tag / 1960 / 512; pkt->nsrc = _nsrc; pkt->src = (be16toh(pkt_hdr->tbn_id) & 1023) - 1 - _src0; pkt->tuning = be32toh(pkt_hdr->tuning_word); - pkt->decimation = 1960; pkt->valid_mode = (be16toh(pkt_hdr->tbn_id) >> 15) & 1; pkt->gain = (be16toh(pkt_hdr->gain)); pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; - return this->valid_packet(pkt); + bool valid = this->valid_packet(pkt); + if( valid ) { + valid &= _cache->update(pkt->src, pkt->time_tag); + pkt->decimation = _cache->get_decimation(); + pkt->seq = pkt->time_tag / pkt->decimation / 512; + } + return valid; } }; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 33d8c73b6..ddcb1808c 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -788,7 +788,8 @@ class BFpacketcapture_tbn_impl : public BFpacketcapture_impl { BFpacketcapture_tbn_sequence_callback _sequence_callback; BFoffset _time_tag; - + uint16_t _decim; + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); @@ -802,19 +803,22 @@ class BFpacketcapture_tbn_impl : public BFpacketcapture_impl { } } inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->tuning != _chan0); + return ( (pkt->tuning != _chan0 ) + || ( pkt->decimation != _decim) ); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { //cout << "Sequence changed" << endl; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; _time_tag = pkt->time_tag; + _decim = pkt->decimation; _chan0 = pkt->tuning; _payload_size = pkt->payload_size; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, + _decim, pkt->tuning, _nsrc, hdr, @@ -844,7 +848,8 @@ class BFpacketcapture_tbn_impl : public BFpacketcapture_impl { : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), - _sequence_callback(sequence_callback->get_tbn()) { + _sequence_callback(sequence_callback->get_tbn()), + _decim(0) { _decoder = new TBNDecoder(nsrc, src0); _processor = new TBNProcessor(); _type_log.update("type : %s\n", "tbn"); @@ -858,6 +863,7 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { BFpacketcapture_drx_sequence_callback _sequence_callback; BFoffset _time_tag; + uint16_t _decim; int _chan1; uint8_t _tstate; @@ -868,36 +874,38 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { void on_sequence_active(const PacketDesc* pkt) { if( pkt ) { //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + if( pkt->src / 2 == 0 ) { + if( pkt->tuning != _chan0 ) { + _tstate |= 1; + _chan0 = pkt->tuning; + } + } else { + if( pkt->tuning != _chan1 ) { + _tstate |= 2; + _chan1 = pkt->tuning; + } + } } else { //cout << "No latest packet" << endl; } - - if( pkt->src / 2 == 0 ) { - if( pkt->tuning != _chan0 ) { - _tstate |= 1; - _chan0 = pkt->tuning; - } - } else { - if( pkt->tuning != _chan1 ) { - _tstate |= 2; - _chan1 = pkt->tuning; - } - } } inline bool has_sequence_changed(const PacketDesc* pkt) { return ( (_tstate == 3 && _nsrc == 4) - || (_tstate != 0 && _nsrc == 2) ); + || (_tstate != 0 && _nsrc == 2) + || (_decim != pkt->decimation ) ); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; _time_tag = pkt->time_tag; + _decim = pkt->decimation; _payload_size = pkt->payload_size; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, + _decim, _chan0, _chan1, _nsrc, @@ -914,6 +922,7 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { *hdr_size = 0; } + _tstate = 0; _chan_log.update() << "chan0 : " << _chan0 << "\n" << "chan1 : " << _chan1 << "\n" << "payload_size : " << _payload_size << "\n"; @@ -930,7 +939,7 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_drx()), - _chan1(), _tstate(0) { + _decim(0), _chan1(0), _tstate(0) { _decoder = new DRXDecoder(nsrc, src0); _processor = new DRXProcessor(); _type_log.update("type : %s\n", "drx"); From 41bae0e2958ad087dd0aa9f1fe57c83643b99479 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 29 Aug 2019 16:25:37 -0600 Subject: [PATCH 056/424] Beefed up the unit tests for the packet readers and writers. --- test/test_disk_io.py | 306 +++++++++++++++++++++++++++++++--- test/test_udp_io.py | 383 ++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 641 insertions(+), 48 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index f1c339ac4..bc8d4ba07 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -26,22 +26,119 @@ import unittest import os +import json +import ctypes +import threading import bifrost as bf +from bifrost.ring import Ring from bifrost.packet_writer import HeaderInfo, DiskWriter -from bifrost.packet_capture import DiskReader +from bifrost.packet_capture import PacketCaptureCallback, DiskReader from bifrost.quantize import quantize +from bifrost.pipeline import SourceBlock, SinkBlock import numpy as np +class TBNReader(object): + def __init__(self, sock, ring): + self.sock = sock + self.ring = ring + def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq': 196e6 * chan0/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 8} + #print "******** CFREQ:", hdr['cfreq'] + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_tbn(self.callback) + with DiskReader("tbn", self.sock, self.ring, 32, 0, 49, 196, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + +class DRXReader(object): + def __init__(self, sock, ring, nsrc=4): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'chan1': chan1, + 'cfreq0': 196e6 * chan0/2.**32, + 'cfreq1': 196e6 * chan1/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 4} + #print "******** CFREQ:", hdr['cfreq'] + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_drx(self.callback) + with DiskReader("drx", self.sock, self.ring, self.nsrc, 0, 49, 49, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + +class AccumulateOp(object): + def __init__(self, ring, output, size): + self.ring = ring + self.output = output + self.size = size + + def main(self): + for iseq in self.ring.read(guarantee=True): + iseq_spans = iseq.read(self.size) + while not self.ring.writing_ended(): + for ispan in iseq_spans: + idata = ispan.data_view(np.uint8) + self.output.append(idata) + + class DiskIOTest(unittest.TestCase): """Test simple IO for the disk-based packet reader and writing""" def setUp(self): """Generate some dummy data to read""" # Generate test vector and save to file - t = np.arange(128*4096*2) - w = 0.01 - self.s0 = 6*np.cos(w * t, dtype='float32') \ - + 5j*np.sin(w * t, dtype='float32') + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') # Filename cache so we can cleanup later self._cache = [] def _open(self, filename, mode): @@ -49,35 +146,86 @@ def _open(self, filename, mode): if filename not in self._cache: self._cache.append(filename) return fh - def test_write_tbn(self): - desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(500) - fh = self._open('test_tbn.dat', 'wb') - op = DiskWriter('tbn', fh) + def _get_tbn_data(self): + # Setup the packet HeaderInfo + desc = HeaderInfo() + desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + desc.set_gain(20) # Reorder as packets, stands, time data = self.s0.reshape(512,32,-1) data = data.transpose(2,1,0).copy() # Convert to ci8 for TBN data_q = bf.ndarray(shape=data.shape, dtype='ci8') - quantize(data, data_q) + quantize(data, data_q, scale=10) - # Go! + # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) + return desc, data_q + def test_write_tbn(self): + fh = self._open('test_tbn.dat', 'wb') + oop = DiskWriter('tbn', fh) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + oop.send(desc, 0, 1960*512, 0, 1, data) fh.close() self.assertEqual(os.path.getsize('test_tbn.dat'), \ - 1048*data_q.shape[0]*data_q.shape[1]) - def test_write_drx(self): + 1048*data.shape[0]*data.shape[1]) + def test_read_tbn(self): + # Write + fh = self._open('test_tbn.dat', 'wb') + oop = DiskWriter('tbn', fh) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + oop.send(desc, 0, 1960*512, 0, 1, data) + fh.close() + + # Read + fh = self._open('test_tbn.dat', 'rb') + ring = Ring(name="capture_tbn") + iop = TBNReader(fh, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + fh.close() + + def _get_drx_data(self): + # Setup the packet HeaderInfo desc = HeaderInfo() - desc.set_chan0(1) desc.set_decimation(10) - - fh = self._open('test_drx.dat', 'wb') - op = DiskWriter('drx', fh) + desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) # Reorder as packets, beams, time data = self.s0.reshape(4096,4,-1) @@ -86,13 +234,125 @@ def test_write_drx(self): data_q = bf.ndarray(shape=data.shape, dtype='ci4') quantize(data, data_q) - # Go! + # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) + return desc, data_q + def test_write_drx(self): + fh = self._open('test_drx.dat', 'wb') + oop = DiskWriter('drx', fh) + + # Get DRX data + desc, data = self._get_drx_data() + + # Go! + oop.send(desc, 0, 10*4096, (1<<3), 128, data) fh.close() self.assertEqual(os.path.getsize('test_drx.dat'), \ - 4128*data_q.shape[0]*data_q.shape[1]) + 4128*data.shape[0]*data.shape[1]) + def test_read_drx(self): + # Write + fh = self._open('test_drx.dat', 'wb') + oop = DiskWriter('drx', fh) + + # Get DRX data and write it out + desc, data = self._get_drx_data() + for p in range(data.shape[0]): + oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + fh.close() + + # Read + fh = self._open('test_drx.dat', 'rb') + ring = Ring(name="capture_drx") + iop = DRXReader(fh, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*4*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,4) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + fh.close() + def test_write_drx_single(self): + fh = self._open('test_drx_single.dat', 'wb') + oop = DiskWriter('drx', fh) + + # Get DRX data + desc, data = self._get_drx_data() + desc.set_nsrc(2) + + # Go! + oop.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + fh.close() + + self.assertEqual(os.path.getsize('test_drx_single.dat'), \ + 4128*data.shape[0]*data.shape[1]/2) + def test_read_drx_single(self): + # Write + fh = self._open('test_drx_single.dat', 'wb') + oop = DiskWriter('drx', fh) + + # Get DRX data and write it out + desc, data = self._get_drx_data() + desc.set_nsrc(2) + oop.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + fh.close() + + # Read + fh = self._open('test_drx_single.dat', 'rb') + ring = Ring(name="capture_drx_single") + iop = DRXReader(fh, ring, nsrc=2) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*2*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,2) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + data = data[:,[0,1],:] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + fh.close() + def tearDown(self): for filename in self._cache: os.unlink(filename) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index d863422be..be0ac63a5 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -26,56 +26,204 @@ import unittest import os +import json +import time +import ctypes +import threading import bifrost as bf +from bifrost.ring import Ring from bifrost.address import Address from bifrost.udp_socket import UDPSocket from bifrost.packet_writer import HeaderInfo, UDPTransmit -from bifrost.packet_capture import UDPCapture +from bifrost.packet_capture import PacketCaptureCallback, UDPCapture from bifrost.quantize import quantize import numpy as np +class TBNReader(object): + def __init__(self, sock, ring): + self.sock = sock + self.ring = ring + def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq': 196e6 * chan0/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 8} + #print "******** CFREQ:", hdr['cfreq'] + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_tbn(self.callback) + with UDPCapture("tbn", self.sock, self.ring, 32, 0, 9000, 49, 196, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + +class DRXReader(object): + def __init__(self, sock, ring, nsrc=4): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'chan1': chan1, + 'cfreq0': 196e6 * chan0/2.**32, + 'cfreq1': 196e6 * chan1/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 4} + #print "******** CFREQ:", hdr['cfreq'] + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_drx(self.callback) + with UDPCapture("drx", self.sock, self.ring, self.nsrc, 0, 9000, 49, 49, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + +class AccumulateOp(object): + def __init__(self, ring, output, size): + self.ring = ring + self.output = output + self.size = size + + def main(self): + for iseq in self.ring.read(guarantee=True): + iseq_spans = iseq.read(self.size) + while not self.ring.writing_ended(): + for ispan in iseq_spans: + idata = ispan.data_view(np.uint8) + self.output.append(idata) + + class UDPIOTest(unittest.TestCase): """Test simple IO for the UDP-based packet reader and writing""" def setUp(self): """Generate some dummy data to read""" # Generate test vector and save to file - t = np.arange(128*4096*2) - w = 0.01 - self.s0 = 6*np.cos(w * t, dtype='float32') \ - + 5j*np.sin(w * t, dtype='float32') + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') - def test_write_tbn(self): + def _get_tbn_data(self): + # Setup the packet HeaderInfo desc = HeaderInfo() - desc.set_chan0(1) - desc.set_decimation(500) - - addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) + desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + desc.set_gain(20) # Reorder as packets, stands, time data = self.s0.reshape(512,32,-1) data = data.transpose(2,1,0).copy() # Convert to ci8 for TBN data_q = bf.ndarray(shape=data.shape, dtype='ci8') - quantize(data, data_q) + quantize(data, data_q, scale=10) - # Go! + # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) + return desc, data_q + def test_write_tbn(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + op.send(desc, 0, 1960*512, 0, 1, data) sock.close() + def test_read_tbn(self): + # Setup the ring + ring = Ring(name="capture_tbn") - def test_write_drx(self): + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = TBNReader(isock, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + desc, data = self._get_tbn_data() + for p in range(data.shape[0]): + oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + time.sleep(1e-3) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + isock.close() + osock.close() + + def _get_drx_data(self): + # Setup the packet HeaderInfo desc = HeaderInfo() - desc.set_chan0(1) desc.set_decimation(10) - - addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('drx', sock) + desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) # Reorder as packets, beams, time data = self.s0.reshape(4096,4,-1) @@ -84,6 +232,191 @@ def test_write_drx(self): data_q = bf.ndarray(shape=data.shape, dtype='ci4') quantize(data, data_q) - # Go! + # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) - op.send(desc, 0, 1, 0, 1, data_q) + return desc, data_q + def test_write_drx(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Get TBN data + desc, data = self._get_drx_data() + + # Go! + op.send(desc, 0, 10*4096, (1<<3), 128, data) + sock.close() + def test_read_drx(self): + # Setup the ring + ring = Ring(name="capture_drx") + + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = DRXReader(isock, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*4*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + desc, data = self._get_drx_data() + for p in range(data.shape[0]): + oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + time.sleep(1e-3) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,4) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + isock.close() + osock.close() + def test_write_drx_single(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Get DRX data + desc, data = self._get_drx_data() + desc.set_nsrc(2) + + # Go! + op.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + sock.close() + def test_read_drx_single(self): + # Setup the ring + ring = Ring(name="capture_drx_single") + + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = DRXReader(isock, ring, nsrc=2) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*2*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + desc, data = self._get_drx_data() + desc.set_nsrc(2) + for p in range(data.shape[0]): + oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) + time.sleep(1e-3) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,2) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + data = data[:,[0,1],:] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + isock.close() + osock.close() + + def test_write_multicast(self): + addr = Address('224.0.0.101', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + op.send(desc, 0, 1960*512, 0, 1, data) + sock.close() + def test_read_multicast(self): + # Setup the ring + ring = Ring(name="capture_multi") + + # Setup the blocks + addr = Address('224.0.0.101', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = TBNReader(isock, ring) + # Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + desc, data = self._get_tbn_data() + for p in range(data.shape[0]): + oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + time.sleep(1e-3) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + isock.close() + osock.close() \ No newline at end of file From 492f5ab81bfd2fef2903ff5e8118027a3030d4e7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 29 Aug 2019 16:28:20 -0600 Subject: [PATCH 057/424] Initial commit of a VDIF packet reader for Bifrost. This still needs some testing and will probably require some other tweaks to support the i4 data that we expect from eLWA. --- src/formats/vdif.hpp | 205 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 src/formats/vdif.hpp diff --git a/src/formats/vdif.hpp b/src/formats/vdif.hpp new file mode 100644 index 000000000..4b94f8998 --- /dev/null +++ b/src/formats/vdif.hpp @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +#pragma pack(1) +struct vdif_hdr_type { + struct word_1_ { + uint32_t seconds_from_epoch:30; + uint8_t is_legacy:1; + uint8_t is_invalid:1; + } word_1; + struct word_2_ { + uint32_t frame_in_second:24; + uint16_t ref_epoch:6; + uint8_t unassigned:2; + } word_2; + struct word_3_ { + uint32_t frame_length:24; + uint32_t log2_nchan:5; + uint8_t version:3; + } word_3; + struct word_4_ { + uint16_t station_id:16; + uint16_t thread_id:10; + uint8_t bits_per_sample_minus_one:5; + uint8_t is_complex:1; + } word_4; +}; + +#pragma pack(1) +struct vdif_ext_type { + uint32_t extended_word_1; + uint32_t extended_word_2; + uint32_t extended_word_3; + uint32_t extended_word_4; +}; + +class VDIFCache { + BFoffset _frame_last = 0; + uint32_t _frames_per_second = 0; + uint32_t _sample_rate = 0; + bool _active = false; +public: + VDIFCache() {} + inline uint32_t get_frames_per_second() { return _frames_per_second; } + inline uint32_t get_sample_rate() { return _sample_rate; } + inline bool update(uint32_t seconds_from_epoch, + uint32_t frame_in_second, + uint32_t samples_per_frame) { + if( !_active ) { + if( frame_in_second < _frame_last ) { + _frames_per_second = _frame_last + 1; + _sample_rate = _frames_per_second * samples_per_frame; + _active = true; + } + _frame_last = frame_in_second; + } + return _active; + } +}; + +class VDIFDecoder : virtual public PacketDecoder { + VDIFCache* _cache; + + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->src >= 0 && + pkt->src < _nsrc && + pkt->valid_mode == 0); + } +public: + VDIFDecoder(int nsrc, int src0) + : PacketDecoder(nsrc, src0) { + _cache = new VDIFCache(); + } + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(vdif_hdr_type) ) { + return false; + } + const vdif_hdr_type* pkt_hdr = (vdif_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(vdif_hdr_type); + int pld_size = pkt_size - sizeof(vdif_hdr_type); + if( pkt_hdr->word_1.is_legacy == 0 ) { + // Do not try to decode the extended header entries + pkt_pld += sizeof(vdif_ext_type); + pld_size -= sizeof(vdif_ext_type); + } + + uint32_t nsamples = pld_size * 8 \ + / (pkt_hdr->word_4.bits_per_sample_minus_one + 1) \ + / ((int) 1 << pkt_hdr->word_3.log2_nchan) \ + / (1 + pkt_hdr->word_4.is_complex); + bool is_active = _cache->update(pkt_hdr->word_1.seconds_from_epoch, + pkt_hdr->word_2.frame_in_second, + nsamples); + + pkt->seq = (BFoffset) pkt_hdr->word_1.seconds_from_epoch*_cache->get_frames_per_second() \ + + (BFoffset) pkt_hdr->word_2.frame_in_second; + pkt->time_tag = pkt->seq*_cache->get_sample_rate(); + pkt->src = pkt_hdr->word_4.thread_id - _src0; + pkt->nsrc = _nsrc; + pkt->chan0 = (int) 1 << pkt_hdr->word_3.log2_nchan; + pkt->nchan = pld_size / 8; + pkt->sync = _cache->get_sample_rate(); + pkt->tuning = (((int) pkt_hdr->word_2.ref_epoch) << 16) \ + | (((int) pkt_hdr->word_4.bits_per_sample_minus_one + 1) << 8) \ + | pkt_hdr->word_4.is_complex; + pkt->valid_mode = pkt_hdr->word_1.is_invalid || (not is_active); + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + /* + if( this->valid_packet(pkt) && (pkt_hdr->word_2.frame_in_second == 1) ) { + std::cout << "pld_size: " << pld_size << std::endl; + std::cout << " : " << pkt_hdr->word_3.frame_length*8 - 32 + 16*pkt_hdr->word_1.is_legacy<< std::endl; + std::cout << "seconds_from_epoch: " << pkt_hdr->word_1.seconds_from_epoch << std::endl; + std::cout << "frame_in_second: " << pkt_hdr->word_2.frame_in_second << std::endl; + std::cout << "frames_per_second: " << _cache->get_frames_per_second() << std::endl; + std::cout << "sample_rate: " << _cache->get_sample_rate() << std::endl; + std::cout << "src: " << pkt->src << std::endl; + std::cout << "is_legacy: " << pkt_hdr->word_1.is_legacy << std::endl; + std::cout << "valid: " << this->valid_packet(pkt) << std::endl; + } + */ + return this->valid_packet(pkt); + } +}; + +class VDIFProcessor : virtual public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef uint64_t itype; // 8-byte chunks in the file + typedef uint64_t otype; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + // Convenience + int src = pkt->src; + int nchan = pkt->nchan; + + int chan = 0; + for( ; chan Date: Fri, 27 Sep 2019 11:40:05 -0600 Subject: [PATCH 058/424] Updated the DiskReader class to make sure that Bifrost starts in the same place in a file that Python is at. --- python/bifrost/packet_capture.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 8485916e3..0b503a5cd 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -103,6 +103,8 @@ def __init__(self, fmt, fh, ring, nsrc, src0, fmt, fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback.obj, core) + # Make sure we start in the same place in the file + self.seek(fh.tell(), _bf.BF_WHENCE_SET) def seek(self, offset, whence=_bf.BF_WHENCE_CUR): position = ctypes.c_ulong(0) _check(_bf.bfPacketCaptureSeek(self.obj, offset, whence, position)) From 4d4af24ea5ce48fc6cfb9e28ec8fa056d38b99e1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 27 Sep 2019 13:51:17 -0600 Subject: [PATCH 059/424] Fixed a bug in test_binary_io introduced when the file cleanup was added. --- test/test_binary_io.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/test_binary_io.py b/test/test_binary_io.py index a02f55a69..128217ee1 100644 --- a/test/test_binary_io.py +++ b/test/test_binary_io.py @@ -101,4 +101,7 @@ def data_callback(ispan, ospan): def tearDown(self): for filename in self.filenames: os.unlink(filename) - os.unlink(filename+".out") \ No newline at end of file + try: + os.unlink(filename+".out") + except OSError: + pass \ No newline at end of file From 4928b8e61cdc97554f7ead4005e3d5c62b3fa81c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 27 Sep 2019 14:07:55 -0600 Subject: [PATCH 060/424] Removed a few debugging statements from the packet capture code. Changed the DRX readers to make them a little cleaner/easier to follow. --- src/formats/base.hpp | 1 + src/formats/drx.hpp | 18 ++++++++++++------ src/packet_capture.hpp | 35 +++++++++++++---------------------- 3 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 2f5ec1679..f7b227232 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -55,6 +55,7 @@ struct PacketDesc { uint32_t sync; uint64_t time_tag; int tuning; + int tuning1 = 0; uint8_t beam; uint16_t gain; uint16_t decimation; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 5bdc4652a..9fab2a216 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -50,7 +50,12 @@ class DRXDecoder : virtual public PacketDecoder { pkt->src >= 0 && pkt->src < _nsrc && pkt->time_tag >= 0 && - pkt->tuning >= 0 && + (((_nsrc == 4) && + (pkt->tuning > 0 && + pkt->tuning1 > 0)) || + (_nsrc == 2 && + (pkt->tuning > 0 || + pkt->tuning1 > 0))) && pkt->valid_mode == 0); } public: @@ -67,17 +72,18 @@ class DRXDecoder : virtual public PacketDecoder { int pkt_id = pkt_hdr->frame_count_word & 0xFF; pkt->beam = (pkt_id & 0x7) - 1; int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; - if( _nsrc == 2 ) { - pkt_tune = 0; - } - int pkt_pol = ((pkt_id >> 7) & 0x1); + int pkt_pol = ((pkt_id >> 7) & 0x1); pkt_id = (pkt_tune << 1) | pkt_pol; pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag) - be16toh(pkt_hdr->time_offset); pkt->seq = pkt->time_tag / be16toh(pkt_hdr->decimation) / 4096; pkt->nsrc = _nsrc; pkt->src = pkt_id - _src0; - pkt->tuning = be32toh(pkt_hdr->tuning_word); + if( pkt->src / 2 == 0 ) { + pkt->tuning = be32toh(pkt_hdr->tuning_word); + } else { + pkt->tuning1 = be32toh(pkt_hdr->tuning_word); + } pkt->decimation = be16toh(pkt_hdr->decimation); pkt->valid_mode = ((pkt_id >> 6) & 0x1); pkt->payload_size = pld_size; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index ddcb1808c..d880bd9f5 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -530,9 +530,7 @@ class BFpacketcapture_impl { } inline BFoffset seek(BFoffset offset, BFiowhence whence=BF_WHENCE_CUR) { BF_ASSERT(_capture->get_io_method() == BF_IO_DISK, BF_STATUS_UNSUPPORTED); - std::cout << "Here with " << offset << " and " << whence << " from " << _capture->tell() << std::endl; BFoffset moved = _capture->seek(offset, whence); - std::cout << "-> Moved to " << moved << std::endl; this->flush(); return moved; } @@ -865,7 +863,6 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { BFoffset _time_tag; uint16_t _decim; int _chan1; - uint8_t _tstate; void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { _seq = round_nearest(pkt->seq, _nseq_per_buf); @@ -873,32 +870,27 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { } void on_sequence_active(const PacketDesc* pkt) { if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - if( pkt->src / 2 == 0 ) { - if( pkt->tuning != _chan0 ) { - _tstate |= 1; - _chan0 = pkt->tuning; - } - } else { - if( pkt->tuning != _chan1 ) { - _tstate |= 2; - _chan1 = pkt->tuning; - } - } - } + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } else { //cout << "No latest packet" << endl; } } inline bool has_sequence_changed(const PacketDesc* pkt) { - return ( (_tstate == 3 && _nsrc == 4) - || (_tstate != 0 && _nsrc == 2) - || (_decim != pkt->decimation ) ); + return ( (pkt->tuning != _chan0) + || (pkt->tuning1 != _chan1) + || (pkt->decimation != _decim) ); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); *time_tag = pkt->time_tag; _time_tag = pkt->time_tag; + _chan0 = pkt->tuning; + _chan1 = pkt->tuning1; + if( _nsrc == 2 ) { + _chan0 = std::max(_chan0, _chan1); + _chan1 = 0; + } _decim = pkt->decimation; _payload_size = pkt->payload_size; @@ -922,8 +914,7 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { *hdr_size = 0; } - _tstate = 0; - _chan_log.update() << "chan0 : " << _chan0 << "\n" + _chan_log.update() << "chan0 : " << _chan0 << "\n" << "chan1 : " << _chan1 << "\n" << "payload_size : " << _payload_size << "\n"; } @@ -939,7 +930,7 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), _sequence_callback(sequence_callback->get_drx()), - _decim(0), _chan1(0), _tstate(0) { + _decim(0), _chan1(0) { _decoder = new DRXDecoder(nsrc, src0); _processor = new DRXProcessor(); _type_log.update("type : %s\n", "drx"); From 470fa43698da9d0d1f3e5d506b9004e7dd443f3a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 19 Nov 2019 13:50:22 -0700 Subject: [PATCH 061/424] Added subbeam3 and subbeam4 to to the list of valid output formats. These probably need some work since they aren't drop in compatible with the CHIPS reader. Maybe they should ultimately become their own formats. --- src/packet_writer.hpp | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index e294cea0f..88cc4262b 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -175,7 +175,7 @@ class BFheaderinfo_impl { PacketDesc _desc; public: inline BFheaderinfo_impl() { - memset(&_desc, 0, sizeof(PacketDesc)); + ::memset(&_desc, 0, sizeof(PacketDesc)); } inline PacketDesc* get_description() { return &_desc; } inline void set_nsrc(int nsrc) { _desc.nsrc = nsrc; } @@ -270,6 +270,30 @@ class BFpacketwriter_subbeam2_impl : public BFpacketwriter_impl { } }; +class BFpacketwriter_subbeam3_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_subbeam3_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new CHIPSHeaderFiller(); + _type_log.update("type : %s\n", "subbeam3"); + } +}; + +class BFpacketwriter_subbeam4_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_subbeam4_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new CHIPSHeaderFiller(); + _type_log.update("type : %s\n", "subbeam4"); + } +}; + class BFpacketwriter_cor_impl : public BFpacketwriter_impl { ProcLog _type_log; public: @@ -334,6 +358,12 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); nsamples = 4*nchan; + } else if( std::string(format).substr(0, 9) == std::string("subbeam3_") ) { + int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); + nsamples = 6*nchan; + } else if( std::string(format).substr(0, 9) == std::string("subbeam4_") ) { + int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); + nsamples = 8*nchan; } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); nsamples = 4*nchan; @@ -364,6 +394,12 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam2_impl(writer, nsamples), *obj = 0); + } else if( std::string(format).substr(0, 9) == std::string("subbeam3_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam3_impl(writer, nsamples), + *obj = 0); + } else if( std::string(format).substr(0, 9) == std::string("subbeam4_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam4_impl(writer, nsamples), + *obj = 0); } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_cor_impl(writer, nsamples), *obj = 0); From d99fcd29387a859344b87d4a5441c89c1b075cab Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 6 Dec 2019 10:51:22 -0700 Subject: [PATCH 062/424] Added in a new 'ibeam' format for the internal (server->T engine) LWA beam at Sevilleta. --- src/bifrost/packet_capture.h | 4 + src/formats/base.hpp | 3 + src/formats/ibeam.hpp | 160 +++++++++++++++++++++++++++++++++++ src/packet_capture.cpp | 7 ++ src/packet_capture.hpp | 121 +++++++++++++++++++++++++- src/packet_writer.hpp | 66 +++++---------- 6 files changed, 314 insertions(+), 47 deletions(-) create mode 100644 src/formats/ibeam.hpp diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 5897690ab..b32af9bdb 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -39,6 +39,8 @@ extern "C" { typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); +typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_vdif_sequence_callback)(BFoffset, BFoffset, int, int, int, @@ -54,6 +56,8 @@ BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj); BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj); BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, + BFpacketcapture_ibeam_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, BFpacketcapture_cor_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetVDIF(BFpacketcapture_callback obj, diff --git a/src/formats/base.hpp b/src/formats/base.hpp index f7b227232..36a6195c2 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -38,6 +38,9 @@ #define JUMBO_FRAME_SIZE 9000 +struct __attribute__((aligned(16))) aligned128_type { + uint8_t data[16]; +}; struct __attribute__((aligned(32))) aligned256_type { uint8_t data[32]; }; diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp new file mode 100644 index 000000000..f70457829 --- /dev/null +++ b/src/formats/ibeam.hpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +//#include // SSE + +#pragma pack(1) +struct ibeam_hdr_type { + uint8_t server; // Note: 1-based + uint8_t gbe; // (AKA tuning) + uint8_t nchan; // 109 + uint8_t nbeam; // 2 + uint8_t nserver; // 6 + // Note: Big endian + uint16_t chan0; // First chan in packet + uint64_t seq; // Note: 1-based +}; + +template +class IBeamDecoder: virtual public PacketDecoder { + uint8_t _nbeam = B; + + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->seq >= 0 && + pkt->src >= 0 && pkt->src < _nsrc && + pkt->beam == _nbeam && + pkt->chan0 >= 0); + } +public: + IBeamDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(ibeam_hdr_type) ) { + return false; + } + const ibeam_hdr_type* pkt_hdr = (ibeam_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(ibeam_hdr_type); + int pld_size = pkt_size - sizeof(ibeam_hdr_type); + pkt->seq = be64toh(pkt_hdr->seq) - 1; + //pkt->nsrc = pkt_hdr->nserver; + pkt->nsrc = _nsrc; + pkt->src = (pkt_hdr->server - 1) - _src0; + pkt->beam = pkt_hdr->nbeam; + pkt->nchan = pkt_hdr->nchan; + pkt->chan0 = ntohs(pkt_hdr->chan0) - pkt->nchan * pkt->src; + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + +template +class IBeamProcessor : virtual public PacketProcessor { + uint8_t _nbeam = B; + +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + // **CHANGED RECENTLY + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef aligned128_type itype; // cf32 * 1 beam * 2 pol + typedef aligned128_type otype; + + obuf_offset *= BF_UNPACK_FACTOR; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + int chan = 0; + int beam = 0; + for( ; channchan; ++chan ) { + for( ; beam<_nbeam; ++beam) { + out[pkt->nchan*_nbeam*pkt->src + chan*_nbeam + beam] = in[chan*_nbeam + beam]; + } + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + typedef aligned128_type otype; + otype* __restrict__ aligned_data = (otype*)data; + for( int t=0; t +class IBeamHeaderFiller : virtual public PacketHeaderFiller { + uint8_t _nbeam = B; + +public: + inline int get_size() { return sizeof(ibeam_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, + char* hdr) { + ibeam_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(ibeam_hdr_type)); + + header->server = hdr_base->src + 1; + header->gbe = hdr_base->tuning; + header->nchan = hdr_base->nchan; + header->nbeam = _nbeam; + header->nserver = hdr_base->nsrc; + header->chan0 = htons(hdr_base->chan0); + header->seq = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 2faea6f92..ca594764f 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -132,6 +132,13 @@ BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, + BFpacketcapture_ibeam_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_ibeam(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, BFpacketcapture_cor_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index d880bd9f5..bce215344 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -350,20 +350,27 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { class BFpacketcapture_callback_impl { BFpacketcapture_chips_sequence_callback _chips_callback; + BFpacketcapture_ibeam_sequence_callback _ibeam_callback; BFpacketcapture_cor_sequence_callback _cor_callback; BFpacketcapture_vdif_sequence_callback _vdif_callback; BFpacketcapture_tbn_sequence_callback _tbn_callback; BFpacketcapture_drx_sequence_callback _drx_callback; public: BFpacketcapture_callback_impl() - : _chips_callback(NULL), _cor_callback(NULL), _vdif_callback(NULL), - _tbn_callback(NULL), _drx_callback(NULL) {} + : _chips_callback(NULL), _ibeam_callback(NULL), _cor_callback(NULL), + _vdif_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } inline BFpacketcapture_chips_sequence_callback get_chips() { return _chips_callback; } + inline void set_ibeam(BFpacketcapture_ibeam_sequence_callback callback) { + _ibeam_callback = callback; + } + inline BFpacketcapture_ibeam_sequence_callback get_ibeam() { + return _ibeam_callback; + } inline void set_cor(BFpacketcapture_cor_sequence_callback callback) { _cor_callback = callback; } @@ -618,6 +625,81 @@ class BFpacketcapture_chips_impl : public BFpacketcapture_impl { } }; +template +class BFpacketcapture_ibeam_impl : public BFpacketcapture_impl { + uint8_t _nbeam = B; + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_ibeam_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan*_nsrc, + _nbeam, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFpacketcapture_ibeam_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_ibeam()) { + _decoder = new IBeamDecoder(nsrc, src0); + _processor = new IBeamProcessor(); + _type_log.update("type : %s%i\n", "ibeam", _nbeam); + } +}; + class BFpacketcapture_cor_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; @@ -657,7 +739,7 @@ class BFpacketcapture_cor_impl : public BFpacketcapture_impl { *time_tag, _chan0, _nchan*((pkt->tuning >> 8) & 0xFF), - _navg, + _navg, _nsrc/((pkt->tuning >> 8) & 0xFF), hdr, hdr_size); @@ -957,6 +1039,24 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); max_payload_size = sizeof(chips_hdr_type) + 32*nchan; } + } else if( std::string(format).substr(0, 6) == std::string("ibeam2") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + max_payload_size = sizeof(ibeam_hdr_type) + 64*2*2*nchan; + } + } else if( std::string(format).substr(0, 6) == std::string("ibeam3") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + max_payload_size = sizeof(ibeam_hdr_type) + 64*2*3*nchan; + } + } else if( std::string(format).substr(0, 6) == std::string("ibeam4") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + max_payload_size = sizeof(ibeam_hdr_type) + 64*2*4*nchan; + } } else if(std::string(format).substr(0, 3) == std::string("cor") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time @@ -992,6 +1092,21 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( std::string(format).substr(0, 6) == std::string("ibeam2") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<2>(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( std::string(format).substr(0, 6) == std::string("ibeam3") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<3>(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); + } else if( std::string(format).substr(0, 6) == std::string("ibeam4") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<4>(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else if( std::string(format).substr(0, 3) == std::string("cor") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 88cc4262b..dbdc70e84 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -258,39 +258,17 @@ class BFpacketwriter_chips_impl : public BFpacketwriter_impl { } }; -class BFpacketwriter_subbeam2_impl : public BFpacketwriter_impl { +template +class BFpacketwriter_ibeam_impl : public BFpacketwriter_impl { + uint8_t _nbeam = B; ProcLog _type_log; public: - inline BFpacketwriter_subbeam2_impl(PacketWriterThread* writer, - int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), - _type_log((std::string(writer->get_name())+"/type").c_str()) { - _filler = new CHIPSHeaderFiller(); - _type_log.update("type : %s\n", "subbeam2"); - } -}; - -class BFpacketwriter_subbeam3_impl : public BFpacketwriter_impl { - ProcLog _type_log; -public: - inline BFpacketwriter_subbeam3_impl(PacketWriterThread* writer, - int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), - _type_log((std::string(writer->get_name())+"/type").c_str()) { - _filler = new CHIPSHeaderFiller(); - _type_log.update("type : %s\n", "subbeam3"); - } -}; - -class BFpacketwriter_subbeam4_impl : public BFpacketwriter_impl { - ProcLog _type_log; -public: - inline BFpacketwriter_subbeam4_impl(PacketWriterThread* writer, - int nsamples) + inline BFpacketwriter_ibeam_impl(PacketWriterThread* writer, + int nsamples) : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), _type_log((std::string(writer->get_name())+"/type").c_str()) { - _filler = new CHIPSHeaderFiller(); - _type_log.update("type : %s\n", "subbeam4"); + _filler = new IBeamHeaderFiller(); + _type_log.update("type : %s%i\n", "ibeam", _nbeam); } }; @@ -355,15 +333,15 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; - } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { - int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); - nsamples = 4*nchan; - } else if( std::string(format).substr(0, 9) == std::string("subbeam3_") ) { - int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); - nsamples = 6*nchan; - } else if( std::string(format).substr(0, 9) == std::string("subbeam4_") ) { - int nchan = std::atoi((std::string(format).substr(9, std::string(format).length())).c_str()); - nsamples = 8*nchan; + } else if( std::string(format).substr(0, 7) == std::string("ibeam2_") ) { + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + nsamples = 2*2*nchan; + } else if( std::string(format).substr(0, 7) == std::string("ibeam3_") ) { + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + nsamples = 2*3*nchan; + } else if( std::string(format).substr(0, 7) == std::string("ibeam4_") ) { + int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); + nsamples = 2*4*nchan; } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); nsamples = 4*nchan; @@ -391,14 +369,14 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_chips_impl(writer, nsamples), *obj = 0); - } else if( std::string(format).substr(0, 9) == std::string("subbeam2_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam2_impl(writer, nsamples), + } else if( std::string(format).substr(0, 7) == std::string("ibeam2_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<2>(writer, nsamples), *obj = 0); - } else if( std::string(format).substr(0, 9) == std::string("subbeam3_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam3_impl(writer, nsamples), + } else if( std::string(format).substr(0, 7) == std::string("ibeam3_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<3>(writer, nsamples), *obj = 0); - } else if( std::string(format).substr(0, 9) == std::string("subbeam4_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_subbeam4_impl(writer, nsamples), + } else if( std::string(format).substr(0, 7) == std::string("ibeam4_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<4>(writer, nsamples), *obj = 0); } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_cor_impl(writer, nsamples), From 58c0624539abdf7f71408d51f5c73b7a5a753231 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 6 Dec 2019 13:03:08 -0700 Subject: [PATCH 063/424] Added in the Python portion of the 'ibeam' support. --- python/bifrost/packet_capture.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 0b503a5cd..c06e77da3 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -40,6 +40,10 @@ def set_chips(self, fnc): self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( self.obj, self._ref_cache['chips'])) + def set_ibeam(self, fnc): + self._ref_cache['ibeam'] = _bf.BFpacketcapture_ibeam_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetIBeam( + self.obj, self._ref_cache['ibeam'])) def set_cor(self, fnc): self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( From 0fef07c9148f2757f3894e08ca22a571cd3143db Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 6 Dec 2019 14:36:58 -0700 Subject: [PATCH 064/424] Fixed a couple of problems wit the ibeam format and adding in a missing file. --- src/formats/formats.hpp | 1 + src/formats/ibeam.hpp | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index afc491a29..311319169 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -34,3 +34,4 @@ #include "drx.hpp" #include "tbn.hpp" #include "tbf.hpp" +#include "ibeam.hpp" diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp index f70457829..17522e3ff 100644 --- a/src/formats/ibeam.hpp +++ b/src/formats/ibeam.hpp @@ -110,11 +110,10 @@ class IBeamProcessor : virtual public PacketProcessor { itype const* __restrict__ in = (itype const*)pkt->payload_ptr; otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; - int chan = 0; - int beam = 0; - for( ; channchan; ++chan ) { - for( ; beam<_nbeam; ++beam) { - out[pkt->nchan*_nbeam*pkt->src + chan*_nbeam + beam] = in[chan*_nbeam + beam]; + int chan, beam; + for(chan=0; channchan; ++chan ) { + for(beam=0; beam<_nbeam; ++beam) { + out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; } } } @@ -129,7 +128,7 @@ class IBeamProcessor : virtual public PacketProcessor { for( int t=0; t Date: Wed, 18 Mar 2020 14:25:03 -0600 Subject: [PATCH 065/424] Switched to unaligned data types for packet payload access since the VMA API only provides unaligned buffers. --- src/formats/base.hpp | 11 ++++++++++- src/formats/chips.hpp | 6 ++++-- src/formats/cor.hpp | 17 +++++++++-------- src/formats/ibeam.hpp | 26 ++++++++++++++------------ src/formats/tbn.hpp | 18 +++++++++--------- 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 36a6195c2..8bc05fedc 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -38,12 +38,21 @@ #define JUMBO_FRAME_SIZE 9000 +struct unaligned128_type { + uint8_t data[16]; +}; struct __attribute__((aligned(16))) aligned128_type { uint8_t data[16]; }; +struct unaligned256_type { + uint8_t data[32]; +}; struct __attribute__((aligned(32))) aligned256_type { uint8_t data[32]; }; +struct unaligned512_type { + uint8_t data[64]; +}; struct __attribute__((aligned(64))) aligned512_type { uint8_t data[64]; }; diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 013dcf08c..a4e96dfdb 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -97,7 +97,7 @@ class CHIPSProcessor : virtual public PacketProcessor { int payload_size = pkt->payload_size;//pkt->nchan*(PKT_NINPUT*2*PKT_NBIT/8); size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; - typedef aligned256_type itype; + typedef unaligned256_type itype; typedef aligned256_type otype; obuf_offset *= BF_UNPACK_FACTOR; @@ -143,7 +143,9 @@ class CHIPSProcessor : virtual public PacketProcessor { //if( pkt->src < 8 ) { // HACK TESTING //for( ; chan<32; ++chan ) { // HACK TESTING for( ; channchan; ++chan ) { // HACK TESTING - out[pkt->src + pkt->nsrc*chan] = in[chan]; + ::memcpy(&out[pkt->src + pkt->nsrc*chan], + &in[chan], sizeof(otype)); + //out[pkt->src + pkt->nsrc*chan] = in[chan]; //::memset( } //} diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 1c9373038..4379e27af 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -63,9 +63,9 @@ class CORDecoder : virtual public PacketDecoder { const cor_hdr_type* pkt_hdr = (cor_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(cor_hdr_type); int pld_size = pkt_size - sizeof(cor_hdr_type); - uint8_t nserver = (be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; - uint8_t server = be32toh(pkt_hdr->frame_count_word) & 0xFF; - uint16_t nchan_pkt = (pld_size/(8*4)); + uint8_t nserver = (be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; + uint8_t server = be32toh(pkt_hdr->frame_count_word) & 0xFF; + uint16_t nchan_pkt = (pld_size/(8*4)); uint16_t stand0 = be16toh(pkt_hdr->stand0) - 1; uint16_t stand1 = be16toh(pkt_hdr->stand1) - 1; uint16_t nstand = (sqrt(8*_nsrc/nserver+1)-1)/2; @@ -78,7 +78,7 @@ class CORDecoder : virtual public PacketDecoder { + (server - 1); pkt->chan0 = be16toh(pkt_hdr->first_chan) \ - nchan_pkt * (server - 1); - pkt->nchan = nchan_pkt; + pkt->nchan = nchan_pkt; pkt->tuning = (nserver << 8) | (server - 1); // Stores the number of servers and // the server that sent this packet pkt->gain = be16toh(pkt_hdr->gain); @@ -120,7 +120,7 @@ class CORProcessor : virtual public PacketProcessor { int payload_size = pkt->payload_size; size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; - typedef aligned256_type itype; // 32+32 * 4 pol. products + typedef unaligned256_type itype; // 32+32 * 4 pol. products typedef aligned256_type otype; // Note: Using these SSE types allows the compiler to use SSE instructions @@ -133,8 +133,9 @@ class CORProcessor : virtual public PacketProcessor { int nchan = pkt->nchan; int chan = 0; - for( ; channsrc = pkt_hdr->nserver; pkt->nsrc = _nsrc; pkt->src = (pkt_hdr->server - 1) - _src0; - pkt->beam = pkt_hdr->nbeam; + pkt->beam = pkt_hdr->nbeam; pkt->nchan = pkt_hdr->nchan; pkt->chan0 = ntohs(pkt_hdr->chan0) - pkt->nchan * pkt->src; pkt->payload_size = pld_size; @@ -100,7 +100,7 @@ class IBeamProcessor : virtual public PacketProcessor { int payload_size = pkt->payload_size; size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; - typedef aligned128_type itype; // cf32 * 1 beam * 2 pol + typedef unaligned128_type itype; // cf32 * 1 beam * 2 pol typedef aligned128_type otype; obuf_offset *= BF_UNPACK_FACTOR; @@ -112,10 +112,12 @@ class IBeamProcessor : virtual public PacketProcessor { int chan, beam; for(chan=0; channchan; ++chan ) { - for(beam=0; beam<_nbeam; ++beam) { - out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; - } - } + for(beam=0; beam<_nbeam; ++beam) { + ::memcpy(&out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam], + &in[chan*_nbeam + beam], sizeof(otype)); + //out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; + } + } } inline void blank_out_source(uint8_t* data, @@ -126,12 +128,12 @@ class IBeamProcessor : virtual public PacketProcessor { typedef aligned128_type otype; otype* __restrict__ aligned_data = (otype*)data; for( int t=0; tsync == 0x5CDEC0DE && - pkt->src >= 0 && - pkt->src < _nsrc && + pkt->src >= 0 && + pkt->src < _nsrc && pkt->time_tag >= 0 && pkt->tuning >= 0 && - pkt->valid_mode == 0); + pkt->valid_mode == 0); } public: TBNDecoder(int nsrc, int src0) @@ -99,12 +99,12 @@ class TBNDecoder : virtual public PacketDecoder { pkt->gain = (be16toh(pkt_hdr->gain)); pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; - bool valid = this->valid_packet(pkt); - if( valid ) { - valid &= _cache->update(pkt->src, pkt->time_tag); - pkt->decimation = _cache->get_decimation(); - pkt->seq = pkt->time_tag / pkt->decimation / 512; - } + bool valid = this->valid_packet(pkt); + if( valid ) { + valid &= _cache->update(pkt->src, pkt->time_tag); + pkt->decimation = _cache->get_decimation(); + pkt->seq = pkt->time_tag / pkt->decimation / 512; + } return valid; } }; From f0efaf285dc652d2471ec74092bf1fb0de9956b9 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 18 Mar 2020 14:31:44 -0600 Subject: [PATCH 066/424] Updated the .travis.yml file to use a newer version of PyPy. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c78e77149..ab22cc0ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ language: python python: - 2.7 # PyPy versions - - pypy-5.4.1 + - pypy2.7-6.0 services: - docker From 35142bd711836c8976be0e09365e4ec13e9f0ea4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 18 Mar 2020 14:38:15 -0600 Subject: [PATCH 067/424] More formatting fixes in drx.hpp and ibeam.hpp. --- src/formats/drx.hpp | 12 ++++++------ src/formats/ibeam.hpp | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 9fab2a216..9b12e9750 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -51,11 +51,11 @@ class DRXDecoder : virtual public PacketDecoder { pkt->src < _nsrc && pkt->time_tag >= 0 && (((_nsrc == 4) && - (pkt->tuning > 0 && - pkt->tuning1 > 0)) || - (_nsrc == 2 && - (pkt->tuning > 0 || - pkt->tuning1 > 0))) && + (pkt->tuning > 0 && + pkt->tuning1 > 0)) || + (_nsrc == 2 && + (pkt->tuning > 0 || + pkt->tuning1 > 0))) && pkt->valid_mode == 0); } public: @@ -72,7 +72,7 @@ class DRXDecoder : virtual public PacketDecoder { int pkt_id = pkt_hdr->frame_count_word & 0xFF; pkt->beam = (pkt_id & 0x7) - 1; int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; - int pkt_pol = ((pkt_id >> 7) & 0x1); + int pkt_pol = ((pkt_id >> 7) & 0x1); pkt_id = (pkt_tune << 1) | pkt_pol; pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag) - be16toh(pkt_hdr->time_offset); diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp index 876f798ec..a910527b6 100644 --- a/src/formats/ibeam.hpp +++ b/src/formats/ibeam.hpp @@ -111,13 +111,13 @@ class IBeamProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan, beam; - for(chan=0; channchan; ++chan ) { - for(beam=0; beam<_nbeam; ++beam) { - ::memcpy(&out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam], - &in[chan*_nbeam + beam], sizeof(otype)); - //out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; - } - } + for(chan=0; channchan; ++chan ) { + for(beam=0; beam<_nbeam; ++beam) { + ::memcpy(&out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam], + &in[chan*_nbeam + beam], sizeof(otype)); + //out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; + } + } } inline void blank_out_source(uint8_t* data, From ee098d55a3804aeed4430409d1dadf7d954d5e63 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 9 Jun 2020 11:00:22 -0600 Subject: [PATCH 068/424] Fixed the imports on packet_capture and packet_writer. --- python/bifrost/packet_capture.py | 4 ++-- python/bifrost/packet_writer.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index c06e77da3..62852d2c6 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -27,7 +27,7 @@ # **TODO: Write tests for this class -from libbifrost import _bf, _check, _get, BifrostObject +from bifrost.libbifrost import _bf, _check, _get, BifrostObject import ctypes diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 8410d028c..af7537574 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -27,8 +27,8 @@ # **TODO: Write tests for this class -from libbifrost import _bf, _check, _get, BifrostObject -from ndarray import asarray +from bifrost.libbifrost import _bf, _check, _get, BifrostObject +from bifrost.ndarray import asarray class HeaderInfo(BifrostObject): def __init__(self): From 91c928259cbb89170b4b6400de137f629b6441c8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 9 Jun 2020 11:05:41 -0600 Subject: [PATCH 069/424] Some light Python3 compatibility work. --- python/bifrost/packet_capture.py | 5 +++++ python/bifrost/packet_writer.py | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 62852d2c6..f5fc446ca 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -78,6 +78,11 @@ def end(self): class UDPCapture(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass if core is None: core = -1 BifrostObject.__init__( diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index af7537574..398caa39f 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -65,6 +65,11 @@ def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): class UDPTransmit(_WriterBase): def __init__(self, fmt, sock, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass if core is None: core = -1 BifrostObject.__init__( @@ -74,6 +79,11 @@ def __init__(self, fmt, sock, core=None): class DiskWriter(_WriterBase): def __init__(self, fmt, fh, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass if core is None: core = -1 BifrostObject.__init__( From 357283edddf7a74fc0c4264ba7296f297ea0f133 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 16 Jun 2020 08:23:01 -0700 Subject: [PATCH 070/424] Add LWA352 packet format --- python/bifrost/libbifrost.py | 1 + python/bifrost/packet_capture.py | 4 + src/bifrost/packet_capture.h | 4 + src/formats/base.hpp | 4 + src/formats/formats.hpp | 1 + src/formats/snap2.hpp | 190 +++++++++++++++++++++++++++++++ src/packet_capture.cpp | 10 ++ src/packet_capture.hpp | 90 ++++++++++++++- 8 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 src/formats/snap2.hpp diff --git a/python/bifrost/libbifrost.py b/python/bifrost/libbifrost.py index 897d9fd65..68e64654c 100644 --- a/python/bifrost/libbifrost.py +++ b/python/bifrost/libbifrost.py @@ -47,6 +47,7 @@ class BifrostObject(object): """Base class for simple objects with create/destroy functions""" def __init__(self, constructor, destructor, *args): self.obj = destructor.argtypes[0]() + print(self.obj) _check(constructor(ctypes.byref(self.obj), *args)) self._destructor = destructor def _destroy(self): diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index f5fc446ca..fc02d4ffb 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -40,6 +40,10 @@ def set_chips(self, fnc): self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( self.obj, self._ref_cache['chips'])) + def set_snap2(self, fnc): + self._ref_cache['snap2'] = _bf.BFpacketcapture_snap2_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetSNAP2( + self.obj, self._ref_cache['snap2'])) def set_ibeam(self, fnc): self._ref_cache['ibeam'] = _bf.BFpacketcapture_ibeam_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetIBeam( diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index b32af9bdb..0bf38c64e 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -39,6 +39,8 @@ extern "C" { typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); +typedef int (*BFpacketcapture_snap2_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, @@ -56,6 +58,8 @@ BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj); BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj); BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetSNAP2(BFpacketcapture_callback obj, + BFpacketcapture_snap2_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, BFpacketcapture_ibeam_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 8bc05fedc..8e545a611 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -64,6 +64,10 @@ struct PacketDesc { int src; int nchan; int chan0; + int nchan_tot; + int npol; + int pol0; + int npol_tot; uint32_t sync; uint64_t time_tag; int tuning; diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 311319169..6e2f4c527 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -35,3 +35,4 @@ #include "tbn.hpp" #include "tbf.hpp" #include "ibeam.hpp" +#include "snap2.hpp" diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp new file mode 100644 index 000000000..a63108c86 --- /dev/null +++ b/src/formats/snap2.hpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +//#include // SSE + +#define SNAP2_HEADER_MAGIC 0xaabbccdd + +// TODO: parameterize somewhere. This isn't +// related to the packet formatting +#define PIPELINE_NPOL 704 +#define PIPELINE_NCHAN 32 + +#pragma pack(1) +// All entries are network (i.e. big) endian +struct snap2_hdr_type { + uint64_t seq; // Spectra counter == packet counter + uint32_t magic; // = 0xaabbccdd + uint16_t npol; // Number of pols in this packet + uint16_t npol_tot; // Number of pols total + uint16_t nchan; // Number of channels in this packet + uint16_t nchan_tot; // Number of channels total (for this pipeline) + uint32_t chan_block_id; // ID of this block of chans + uint32_t chan0; // First channel in this packet + uint32_t pol0; // First pol in this packet +}; + +/* + * The PacketDecoder's job is to unpack + * a packet into a standard PacketDesc + * format, and verify that a packet + * is valid. + */ + +#define BF_SNAP2_DEBUG 0 + +class SNAP2Decoder : virtual public PacketDecoder { +protected: + inline bool valid_packet(const PacketDesc* pkt) const { +#if BFSNAP2_DEBUG + cout << "seq: "<< pkt->seq << endl; + cout << "src: "<< pkt->src << endl; + cout << "nsrc: "<< pkt->nsrc << endl; + cout << "nchan: "<< pkt->nchan << endl; + cout << "chan0: "<< pkt->chan0 << endl; +#endif + return ( + pkt->seq >= 0 + && pkt->src >= 0 + && pkt->src < _nsrc + && pkt->nsrc == _nsrc + && pkt->chan0 >= 0 + ); + } +public: + SNAP2Decoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(snap2_hdr_type) ) { + return false; + } + const snap2_hdr_type* pkt_hdr = (snap2_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(snap2_hdr_type); + int pld_size = pkt_size - sizeof(snap2_hdr_type); + if( be32toh(pkt_hdr->magic) != SNAP2_HEADER_MAGIC ) { + return false; + } + pkt->seq = be64toh(pkt_hdr->seq); + int npol_blocks = (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); + int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); + + pkt->nsrc = npol_blocks * nchan_blocks;// _nsrc; + pkt->src = (npol_blocks * be16toh(pkt_hdr->chan_block_id)) + (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); + pkt->nchan = be16toh(pkt_hdr->nchan); + pkt->chan0 = be32toh(pkt_hdr->chan_block_id) * be16toh(pkt_hdr->nchan); + pkt->nchan_tot = be16toh(pkt_hdr->nchan_tot); + pkt->npol = be16toh(pkt_hdr->npol); + pkt->npol_tot = be16toh(pkt_hdr->npol_tot); + pkt->pol0 = be32toh(pkt_hdr->pol0); + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + +class SNAP2Processor : virtual public PacketProcessor { +protected: + int _pipeline_nchan = PIPELINE_NCHAN; +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef unaligned256_type itype; //256 bits = 32 pols / word + typedef aligned256_type otype; + + obuf_offset *= BF_UNPACK_FACTOR; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + // Copy packet payload one channel at a time. + // Packets have payload format nchans x npols x complexity + // spacing with which channel chunks are copied depends + // on the total number of channels/pols in the system + for(int chan=0; channchan; chan++) { + // // TODO: AVX stores here will probably be much faster + // ::memcpy(&out[(((pkt->npol_tot) * (pkt->chan0 + chan)) + (pkt->pol0)) / 32], + // &in[(pkt->npol / 32) * chan], pkt->npol / 32); + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + typedef aligned256_type otype; + otype* __restrict__ aligned_data = (otype*)data; + for( int t=0; t(hdr); + memset(header, 0, sizeof(chips_hdr_type)); + + header->roach = hdr_base->src + 1; + header->gbe = hdr_base->tuning; + header->nchan = hdr_base->nchan; + header->nsubband = 1; // Should be changable? + header->subband = 0; // Should be changable? + header->nroach = hdr_base->nsrc; + header->chan0 = htons(hdr_base->chan0); + header->seq = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index ca594764f..05fadc816 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -132,6 +132,13 @@ BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetSNAP2(BFpacketcapture_callback obj, + BFpacketcapture_snap2_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_snap2(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, BFpacketcapture_ibeam_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); @@ -245,9 +252,12 @@ BFpacketcapture_status BFpacketcapture_impl::recv() { ret = BF_CAPTURE_CONTINUED; } } + BF_PRINTD("_bufs.size(): " << _bufs.size()); if( _bufs.size() == 2 ) { + BF_PRINTD("Committing buffer"); this->commit_buf(); } + BF_PRINTD("Rseerving buffer"); this->reserve_buf(); } else { diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index bce215344..e4eb55528 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -350,6 +350,7 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { class BFpacketcapture_callback_impl { BFpacketcapture_chips_sequence_callback _chips_callback; + BFpacketcapture_snap2_sequence_callback _snap2_callback; BFpacketcapture_ibeam_sequence_callback _ibeam_callback; BFpacketcapture_cor_sequence_callback _cor_callback; BFpacketcapture_vdif_sequence_callback _vdif_callback; @@ -358,13 +359,20 @@ class BFpacketcapture_callback_impl { public: BFpacketcapture_callback_impl() : _chips_callback(NULL), _ibeam_callback(NULL), _cor_callback(NULL), - _vdif_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} + _vdif_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL), + _snap2_callback(NULL) {} inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } inline BFpacketcapture_chips_sequence_callback get_chips() { return _chips_callback; } + inline void set_snap2(BFpacketcapture_snap2_sequence_callback callback) { + _snap2_callback = callback; + } + inline BFpacketcapture_snap2_sequence_callback get_snap2() { + return _snap2_callback; + } inline void set_ibeam(BFpacketcapture_ibeam_sequence_callback callback) { _ibeam_callback = callback; } @@ -625,6 +633,81 @@ class BFpacketcapture_chips_impl : public BFpacketcapture_impl { } }; +class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_snap2_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + // Has the configuration changed? I.e., different channels being sent. + inline bool has_sequence_changed(const PacketDesc* pkt) { + // TODO: sequence never changes? + //return false; + //return (pkt->seq % 128 == 0); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFpacketcapture_snap2_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_snap2()) { + _decoder = new SNAP2Decoder(nsrc, src0); + _processor = new SNAP2Processor(); + _type_log.update("type : %s\n", "snap2"); + } +}; + template class BFpacketcapture_ibeam_impl : public BFpacketcapture_impl { uint8_t _nbeam = B; @@ -1092,6 +1175,11 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( std::string(format).substr(0, 5) == std::string("snap2") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_snap2_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else if( std::string(format).substr(0, 6) == std::string("ibeam2") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<2>(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, From 9fb5a0940289e0b794a3468574223178894fdc39 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 18 Jun 2020 17:09:57 +0000 Subject: [PATCH 071/424] Add xGPU bindings This allows the DP4A library to be used, which is way faster --- src/Makefile | 7 +++++ src/bf_xgpu.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++ src/bifrost/bf_xgpu.h | 9 +++++++ 3 files changed, 76 insertions(+) create mode 100644 src/bf_xgpu.cpp create mode 100644 src/bifrost/bf_xgpu.h diff --git a/src/Makefile b/src/Makefile index 72619d2a4..a79c574de 100644 --- a/src/Makefile +++ b/src/Makefile @@ -37,6 +37,10 @@ ifndef NOCUDA fir.o \ guantize.o \ gunpack.o +ifdef XGPU + LIBBIFROST_OBJS += \ + bf_xgpu.o +endif endif JIT_SOURCES ?= \ @@ -110,6 +114,9 @@ endif ifndef NOCUDA CPPFLAGS += -DBF_CUDA_ENABLED=1 LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt +ifdef XGPU + LIB += -lxgpu +endif endif ifndef ANY_ARCH diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp new file mode 100644 index 000000000..66ea4d5b2 --- /dev/null +++ b/src/bf_xgpu.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +extern "C" { + +static XGPUContext context; +static XGPUInfo info; + +BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { + int xgpu_error; + xgpuInfo(&info); + if (num_contiguous_elements(in) != info.vecLength) { + return BF_STATUS_INVALID_SHAPE; + } + if (num_contiguous_elements(out) != info.matLength) { + return BF_STATUS_INVALID_SHAPE; + } + context.array_h = (ComplexInput *)in->data; + context.array_len = info.vecLength; + context.matrix_h = (Complex *)out->data; + context.matrix_len = info.matLength; + xgpu_error = xgpuInit(&context, gpu_dev); + if (xgpu_error != XGPU_OK) { + return BF_STATUS_INTERNAL_ERROR; + } else { + return BF_STATUS_SUCCESS; + } +} + +BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { + int xgpu_error; + context.array_h = (ComplexInput *)in->data; + context.array_len = info.vecLength; + context.matrix_h = (Complex *)out->data; + context.matrix_len = info.matLength; + xgpu_error = xgpuCudaXengineSwizzle(&context, doDump ? SYNCOP_DUMP : SYNCOP_SYNC_TRANSFER); + if (doDump) { + xgpuClearDeviceIntegrationBuffer(&context); + } + if (xgpu_error != XGPU_OK) { + return BF_STATUS_INTERNAL_ERROR; + } else { + return BF_STATUS_SUCCESS; + } +} + +} // C diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h new file mode 100644 index 000000000..120fc8232 --- /dev/null +++ b/src/bifrost/bf_xgpu.h @@ -0,0 +1,9 @@ +#include +#include + +//extern "C" { + +BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); +BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump); + +//} From 1cf8cdbbee181de1bade6cd5855ca7e445ee7976 Mon Sep 17 00:00:00 2001 From: JackH Date: Fri, 19 Jun 2020 13:39:50 +0000 Subject: [PATCH 072/424] remove print --- python/bifrost/libbifrost.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/bifrost/libbifrost.py b/python/bifrost/libbifrost.py index 68e64654c..897d9fd65 100644 --- a/python/bifrost/libbifrost.py +++ b/python/bifrost/libbifrost.py @@ -47,7 +47,6 @@ class BifrostObject(object): """Base class for simple objects with create/destroy functions""" def __init__(self, constructor, destructor, *args): self.obj = destructor.argtypes[0]() - print(self.obj) _check(constructor(ctypes.byref(self.obj), *args)) self._destructor = destructor def _destroy(self): From 6d088a2aba4a9280fe52de0f7fac7571c45ac5a0 Mon Sep 17 00:00:00 2001 From: JackH Date: Sun, 21 Jun 2020 16:36:44 +0000 Subject: [PATCH 073/424] Add Kernel-only xgpu functions I.e., call xGPU passing pointers to already transferred data on the device. This gives up xGPU's pipelining abilities, but makes it easier to use the xGPU kernel alongside other consumers also using the same GPU input buffer. --- src/Makefile | 2 +- src/bf_xgpu.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- src/bifrost/bf_xgpu.h | 1 + user.mk | 5 +++-- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index a79c574de..e3d83f592 100644 --- a/src/Makefile +++ b/src/Makefile @@ -113,7 +113,7 @@ endif ifndef NOCUDA CPPFLAGS += -DBF_CUDA_ENABLED=1 - LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt + LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt -lxgpu ifdef XGPU LIB += -lxgpu endif diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 66ea4d5b2..54e11b1f8 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -19,6 +19,11 @@ extern "C" { static XGPUContext context; static XGPUInfo info; +/* + * Initialize the xGPU library by providing + * a pointer to the input and output data (on the host), + * and a GPU device ID + */ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { int xgpu_error; xgpuInfo(&info); @@ -28,7 +33,7 @@ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { if (num_contiguous_elements(out) != info.matLength) { return BF_STATUS_INVALID_SHAPE; } - context.array_h = (ComplexInput *)in->data; + context.array_h = (SwizzleInput *)in->data; context.array_len = info.vecLength; context.matrix_h = (Complex *)out->data; context.matrix_len = info.matLength; @@ -40,9 +45,16 @@ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { } } +/* + * Call the xGPU kernel. + * in : pointer to input data array on host + * out: pointer to output data array on host + * doDump : if 1, this is the last call in an integration, and results + * will be copied to the host. + */ BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { int xgpu_error; - context.array_h = (ComplexInput *)in->data; + context.array_h = (SwizzleInput *)in->data; context.array_len = info.vecLength; context.matrix_h = (Complex *)out->data; context.matrix_len = info.matLength; @@ -57,4 +69,31 @@ BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { } } +/* + * Call the xGPU kernel having pre-copied data to device memory. + * Note that this means xGPU can't take advantage of its inbuild + * copy/compute pipelining. + * in : pointer to input data array on device + * out: pointer to output data array on device + * doDump : if 1, this is the last call in an integration, and results + * will be copied to the host. + */ +BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump) { + int xgpu_error; + context.array_h = (ComplexInput *)in->data; + context.array_len = info.vecLength; + context.matrix_h = (Complex *)out->data; + context.matrix_len = info.matLength; + xgpu_error = xgpuCudaXengineSwizzleKernel(&context, doDump ? SYNCOP_DUMP : SYNCOP_SYNC_TRANSFER, + (SwizzleInput *)in->data, (Complex *)out->data); + if (doDump) { + xgpuClearDeviceIntegrationBuffer(&context); + } + if (xgpu_error != XGPU_OK) { + return BF_STATUS_INTERNAL_ERROR; + } else { + return BF_STATUS_SUCCESS; + } +} + } // C diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 120fc8232..447c090e7 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -5,5 +5,6 @@ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump); +BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump); //} diff --git a/user.mk b/user.mk index 49cc2a199..256c674f2 100644 --- a/user.mk +++ b/user.mk @@ -28,5 +28,6 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #ANY_ARCH = 1 # Disable native architecture compilation #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) #NUMA = 1 # Enable use of numa library for setting affinity of ring memory -#HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture -#VMA = 1 # Enable use of Mellanox libvma in udp_capture +HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture +VMA = 1 # Enable use of Mellanox libvma in udp_capture +XGPU = 1 # build xGPU integrations (requires the xGPU library) From 93104062e745b571aa1c71d39329814defc321ee Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 22 Jun 2020 19:58:25 +0000 Subject: [PATCH 074/424] add xgpuSubSelect; fix xgpuKernel Add some checking for proper pointer spaces. More checking required --- src/bf_xgpu.cpp | 78 ++++++++++++++++++++++++++++++++++++++----- src/bifrost/bf_xgpu.h | 5 +-- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 54e11b1f8..82c923758 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -27,18 +27,33 @@ static XGPUInfo info; BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { int xgpu_error; xgpuInfo(&info); - if (num_contiguous_elements(in) != info.vecLength) { - return BF_STATUS_INVALID_SHAPE; - } - if (num_contiguous_elements(out) != info.matLength) { - return BF_STATUS_INVALID_SHAPE; + // Don't bother checking sizes if the input space is CUDA. + // We're not going to use these arrays anyway + if (in->space != BF_SPACE_CUDA) { + if (num_contiguous_elements(in) != info.vecLength) { + fprintf(stderr, "ERROR: xgpuInitialize: number of elements in != vecLength\n"); + fprintf(stderr, "number of elements in: %lu\n", num_contiguous_elements(in)); + fprintf(stderr, "vecLength: %llu\n", info.vecLength); + return BF_STATUS_INVALID_SHAPE; + } + if (num_contiguous_elements(out) != info.matLength) { + fprintf(stderr, "ERROR: xgpuInitialize: number of elements out != matLength\n"); + fprintf(stderr, "number of elements out: %lu\n", num_contiguous_elements(out)); + fprintf(stderr, "matLength: %llu\n", info.matLength); + return BF_STATUS_INVALID_SHAPE; + } } context.array_h = (SwizzleInput *)in->data; context.array_len = info.vecLength; context.matrix_h = (Complex *)out->data; context.matrix_len = info.matLength; - xgpu_error = xgpuInit(&context, gpu_dev); + if (in->space == BF_SPACE_CUDA) { + xgpu_error = xgpuInit(&context, gpu_dev | XGPU_DONT_REGISTER | XGPU_DONT_MALLOC_GPU); + } else { + xgpu_error = xgpuInit(&context, gpu_dev); + } if (xgpu_error != XGPU_OK) { + fprintf(stderr, "ERROR: xgpuInitialize: call returned %d\n", xgpu_error); return BF_STATUS_INTERNAL_ERROR; } else { return BF_STATUS_SUCCESS; @@ -53,6 +68,12 @@ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { * will be copied to the host. */ BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { + if (in->space == BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } + if (out->space == BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } int xgpu_error; context.array_h = (SwizzleInput *)in->data; context.array_len = info.vecLength; @@ -78,18 +99,59 @@ BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { * doDump : if 1, this is the last call in an integration, and results * will be copied to the host. */ +static int newAcc = 1; // flush vacc on the first call BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump) { + if (in->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } + if (out->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } int xgpu_error; context.array_h = (ComplexInput *)in->data; context.array_len = info.vecLength; context.matrix_h = (Complex *)out->data; context.matrix_len = info.matLength; - xgpu_error = xgpuCudaXengineSwizzleKernel(&context, doDump ? SYNCOP_DUMP : SYNCOP_SYNC_TRANSFER, + xgpu_error = xgpuCudaXengineSwizzleKernel(&context, doDump ? SYNCOP_DUMP : 0, newAcc, (SwizzleInput *)in->data, (Complex *)out->data); + + if (newAcc) { + newAcc = 0; + } if (doDump) { - xgpuClearDeviceIntegrationBuffer(&context); + newAcc = 1; + } + if (xgpu_error != XGPU_OK) { + fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); + return BF_STATUS_INTERNAL_ERROR; + } else { + return BF_STATUS_SUCCESS; + } +} + +/* + * Given an xGPU accumulation buffer, grab a subset of visibilities from + * and gather them in a new buffer, in order chan x visibility x complexity [int32] + * BFarray *in : Pointer to a BFarray with storage in device memory, where xGPU results reside + * BFarray *in : Pointer to a BFarray with storage in device memory where collated visibilities should be written. + * int **vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. + * int nvis : The number of visibilities to colate (length of the vismap array) + */ +BFstatus xgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap) { + long long unsigned nvis = num_contiguous_elements(vismap); + int xgpu_error; + if (in->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } + if (out->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } + if (vismap->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; } + xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, nvis); if (xgpu_error != XGPU_OK) { + fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); return BF_STATUS_INTERNAL_ERROR; } else { return BF_STATUS_SUCCESS; diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 447c090e7..2de082067 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -1,10 +1,7 @@ #include #include -//extern "C" { - BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump); - -//} +BFstatus xgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap); From d18fbe9ffb4143c80bd48f204247c2a88ba3a63c Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 30 Jun 2020 11:17:54 -0400 Subject: [PATCH 075/424] Add beamforming code to bifrost Inspired by the CUBLAS usage in https://github.com/devincody/DSAbeamformer Operates in 3 steps -- 1. Tranpose data and promote to float 2. Compute beams 3. Compute beam dynamic spectra, and sum to (in LWA352's case) 1ms Assumes no polarization ordering of input, but relies on user to upload beamforming coefficients which create X-pol and Y-pol beams. This is an easy way to deal with the arbitrary input ordering at runtime, but isn't very efficient (half the beamforming coeffs are zero). The kernel assumes the beams are constructed like this and uses the fact to generate averaged dynamic spectra (XX, YY, XY_r, XY_i). May well have synchronization bugs which make the benchmarks meaningless, but currently obtains ~50 Gbps throughput (~9MHz bandwidth for 4-bit inputs) with NANTS = 352 NPOLS = 2 NCHANS = 192 (4.4 MHz for LWA352) NBEAMS = 32 (16 x 2-pols) NTIMES = 480 NTIMES_SUM = 24 (1ms) --- src/Makefile | 4 +- src/beamform.cpp | 62 +++++++++++ src/bifrost/beamform.h | 17 +++ src/cublas_beamform.cu | 237 ++++++++++++++++++++++++++++++++++++++++ src/cublas_beamform.cuh | 35 ++++++ 5 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 src/beamform.cpp create mode 100644 src/bifrost/beamform.h create mode 100644 src/cublas_beamform.cu create mode 100644 src/cublas_beamform.cuh diff --git a/src/Makefile b/src/Makefile index e3d83f592..a03efd2a3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -36,7 +36,9 @@ ifndef NOCUDA reduce.o \ fir.o \ guantize.o \ - gunpack.o + gunpack.o \ + beamform.o \ + cublas_beamform.o ifdef XGPU LIBBIFROST_OBJS += \ bf_xgpu.o diff --git a/src/beamform.cpp b/src/beamform.cpp new file mode 100644 index 000000000..ba40d9e87 --- /dev/null +++ b/src/beamform.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cublas_beamform.cuh" + +extern "C" { + + +/* + * Initialize the beamformer library + */ + +BFstatus beamformInitialize( + int gpudev, + int ninputs, + int nchans, + int ntimes, + int nbeams, + int ntime_blocks +) { + // TODO: array size checking + // TODO: use complex data types + cublas_beamform_init( + gpudev, + ninputs, + nchans, + ntimes, + nbeams, + ntime_blocks + ); + return BF_STATUS_SUCCESS; +} + +BFstatus beamformRun(BFarray *in, BFarray *out, BFarray *weights) { + if (in->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + if (out->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + if (weights->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer weights buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + cublas_beamform((unsigned char *)in->data, (float *)out->data, (float *)weights->data); + return BF_STATUS_SUCCESS; +} + +} // C diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h new file mode 100644 index 000000000..5b2e486b4 --- /dev/null +++ b/src/bifrost/beamform.h @@ -0,0 +1,17 @@ +#include +#include + +BFstatus beamformInitialize( + int gpudev, + int ninputs, + int nchans, + int ntimes, + int nbeams, + int ntime_blocks +); + +BFstatus beamformRun( + BFarray *in, + BFarray *out, + BFarray *weights +); diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu new file mode 100644 index 000000000..a98ae32ff --- /dev/null +++ b/src/cublas_beamform.cu @@ -0,0 +1,237 @@ +#include +#include +#include + +#include "cublas_beamform.cuh" + +__constant__ float lut[16] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0}; + +// Transpose time x chan x pol x 4+4 bit to +// chan x pol x time x 32+32 bit float +__global__ void trans_4bit_to_float(unsigned char *in, + float *out, + int n_pol, + int n_chan, + int n_time + ) { + //long long int tid = blockDim.y*blockDim.x*blockIdx.y + blockDim.x*blockIdx.x + threadIdx.x; + //int pol = tid % n_pol; + //int chan = (tid / n_pol) % n_chan; + //int time = (tid / (n_pol * n_chan)); + int time = blockIdx.x; + int chan = blockIdx.y; + int pol = TRANSPOSE_POL_BLOCK_SIZE*threadIdx.x; + unsigned char *in_off = in + time*n_chan*n_pol + chan*n_pol + pol; + float *out_off = out + 2*( chan*n_pol*n_time + pol*n_time + time); + //long long int old_index = time*n_chan*n_pol + chan*n_pol + pol; + //long long int new_index = chan*n_pol*n_time + pol*n_time + time; + float real, imag; + unsigned char temp; + #pragma unroll + for (int i=0; i> 4]; + //imag = lut[in[old_index+i] & 0b1111]; + //out[2*(new_index+i)] = real; + //out[2*(new_index+i)+1] = imag; + real = lut[temp >> 4]; + imag = lut[temp & 255]; + *out_off++ = real; + *out_off++ = imag; + } +} + +// Transpose chan x beam x pol x time x 32+32 float to +// beam x time[part-summed] x chan x [XX,YY,XY*_r,XY*_i] x 32 float +// Each thread deals with two pols of a beam, and sums over n_time_sum time samples +__global__ void trans_output_and_sum(float *in, + float *out, + int n_chan, + int n_beam, + int n_time, + int n_time_sum + ) { + int chan = blockIdx.x; + int beam = blockIdx.y; + int time = threadIdx.x; + long long int old_index = chan*n_beam*n_time*2 + beam*n_time*2 + time*n_time_sum; // start index for n_time/n_time_sum samples + long long int new_index = beam*(n_time / n_time_sum)*n_chan + time*n_chan + chan; + float xx=0., yy=0., xy_r=0., xy_i=0.; + float x_r, x_i, y_r, y_i; + int t; + for (t=0; t>>( + in4_d, + context.in32_d, + context.ninputs, + context.nchans, + context.ntimes + ); + cudaStreamSynchronize(context.stream); + + // Beamform using GEMM + float alpha = 1.0; + float beta = 0.0; + // GEMM: + // C <= alpha*AB + beta*C + // alpha = 1.0 + // beta = 0.0 + // A matrix: beamforming coeffs (NBEAMS * NANTS) + // B matrix: data matrix (NANTS * NTIMES) + gpuBLASchk(cublasGemmStridedBatchedEx( + context.handle, + CUBLAS_OP_N, // transpose A? + CUBLAS_OP_N, // transpose B? + context.nbeams, // m + context.ntimes, // n + context.ninputs, // k + // Coeffs + &alpha, // alpha + weights_d, // A + CUDA_C_32F, // A type + context.nbeams, // Lda + context.nbeams*context.ninputs,// strideA : stride size + // Data + context.in32_d, // B + CUDA_C_32F, // B type + context.ninputs, // Ldb + context.ninputs*context.ntimes,// strideB : stride size + &beta, // beta + // Results + context.out_d, // C + CUDA_C_32F, // Ctype + context.nbeams, // Ldc + context.nbeams*context.ntimes,// Stride C + context.nchans, // batchCount + CUDA_C_32F, // compute type + CUBLAS_GEMM_DEFAULT_TENSOR_OP // algo + )); + cudaStreamSynchronize(context.stream); + + // Create XX, YY, XY beam powers. + // Sum over `ntimes_sum` samples + int ntimes_sum = context.ntimes / context.ntimeblocks; + dim3 sumBlockGrid(context.nchans, context.nbeams/2); + dim3 sumThreadGrid(context.ntimes / ntimes_sum); + trans_output_and_sum<<>>( + context.out_d, + sum_out_d, + context.nchans, + context.nbeams/2, + context.ntimes, + ntimes_sum + ); + cudaStreamSynchronize(context.stream); +} diff --git a/src/cublas_beamform.cuh b/src/cublas_beamform.cuh new file mode 100644 index 000000000..eca2d63f2 --- /dev/null +++ b/src/cublas_beamform.cuh @@ -0,0 +1,35 @@ +#ifndef _CUBLAS_BEAMFORM_H +#define _CUBLAS_BEAMFORM_H + +#include +#include +#include + +// Transpose time x chan x pol x 4+4 bit to +#define TRANSPOSE_POL_BLOCK_SIZE 8 +// chan x pol x time x 32+32 bit float +__global__ void trans_4bit_to_float(unsigned char *in, + float *out, + int n_pol, + int n_chan, + int n_time + ); + +// Transpose chan x beam x pol x time x 32+32 float to +// beam x time[part-summed] x chan x [XX,YY,XY*_r,XY*_i] x 32 float +// Each thread deals with two pols of a beam, and sums over n_time_sum time samples +__global__ void trans_output_and_sum(float *in, + float *out, + int n_chan, + int n_beam, + int n_time, + int n_time_sum + ); + +__global__ void complex2pow(float *in, float *out, int N); + +void cublas_beamform_destroy(); +void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d); +void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks); + +#endif From 056d98c74fc18da8a667c2ea66790cf7621a1b92 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 30 Jun 2020 16:24:01 +0000 Subject: [PATCH 076/424] gitignore ctags files --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index 74a87e23a..46cd88933 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,9 @@ target/ # Benchmarking files test/benchmarks/development_vs_gpuspec/with_bifrost/ test/benchmarks/development_vs_gpuspec/without_bifrost/ + +# ctags files +python/bifrost/tags +python/tags +src/tags +tags From 55b2d6f4a3f0151264b555512e5f2b6afd605891 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 30 Jun 2020 16:25:02 +0000 Subject: [PATCH 077/424] Update GPU arch --- user.mk | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/user.mk b/user.mk index 256c674f2..bb2908a26 100644 --- a/user.mk +++ b/user.mk @@ -11,7 +11,8 @@ PYINSTALLFLAGS ?= #GPU_ARCHS ?= 30 32 35 37 50 52 53 # Nap time! #GPU_ARCHS ?= 35 52 -GPU_ARCHS ?= 35 61 +#GPU_ARCHS ?= 35 61 +GPU_ARCHS ?= 75 GPU_SHAREDMEM ?= 16384 # GPU shared memory size From 08129378fae6ef959626e404904feef079bf4294 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 30 Jun 2020 19:25:16 +0000 Subject: [PATCH 078/424] Add embryonic ibverbs packet RX support --- src/Makefile | 6 ++++ src/packet_capture.hpp | 68 ++++++++++++++++++++++++++++++++++++++++++ user.mk | 1 + 3 files changed, 75 insertions(+) diff --git a/src/Makefile b/src/Makefile index a03efd2a3..cf8b69db7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -105,6 +105,12 @@ ifdef VMA CPPFLAGS += -DBF_VMA_ENABLED=1 endif +ifdef IBV + # Requires ibverbs/hashpipe to be installed + LIB += -libverbs -lhashpipe + CPPFLAGS += -DBF_HPIBV_ENABLED=1 +endif + ifdef ALIGNMENT CPPFLAGS += -DBF_ALIGNMENT=$(ALIGNMENT) endif diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index e4eb55528..5bdc30221 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -223,6 +223,74 @@ class VMAReceiver { }; #endif // BF_VMA_ENABLED +#ifndef BF_HPIBV_ENABLED +#define BF_HPIBV_ENABLED 0 +#endif + +#if BF_HPIBV_ENABLED +#include "hashpipe_ibverbs.h" +#define IBV_UDP_PAYLOAD_OFFSET 42 +class IBVReceiver { + struct hashpipe_ibv_context _hibv_ctx; + struct hashpipe_ibv_recv_pkt* _hibv_rpkt; // Current packet chain + struct hashpipe_ibv_recv_pkt* _pkt; // Current packet +public: + IBVReceiver(int port, int pkt_size_max, char *ifname) + : _pkt(NULL), _hibv_rpkt(NULL) { + strncpy(_hibv_ctx.interface_name, ifname, IFNAMSIZ); + _hibv_ctx.interface_name[IFNAMSIZ-1] = '\0'; // Ensure NUL termination + _hibv_ctx.send_pkt_num = 1; + _hibv_ctx.recv_pkt_num = 8192; + _hibv_ctx.pkt_size_max = pkt_size_max; + _hibv_ctx.max_flows = 1; + int ret = hashpipe_ibv_init(&_hibv_ctx); + if( ret ) { + //PANIC + } + // Subscribe to RX flow + ret = hashpipe_ibv_flow( + &_hibv_ctx, + 0, IBV_FLOW_SPEC_UDP, + _hibv_ctx.mac, NULL, NULL, NULL, NULL, NULL, + NULL, port); + if( ret ) { + //PANIC + } + } + ~IBVReceiver() { } + inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { + // If we don't have a work-request queue on the go, + // get some new packets. + // If we do, walk through the packets in this queue. + // Once at the end of the queue, release the current queue and wait + // for another + if ( !_hibv_rpkt ) { + _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, -1); //infinite timeout + _pkt = _hibv_rpkt; + } else { + _pkt = (struct hashpipe_ibv_recv_pkt *)_pkt->wr.next; + } + if ( !_pkt ) { + hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); + _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, -1); //infinite timeout + _pkt = _hibv_rpkt; + } + if ( _pkt ) { + // IBV returns Eth/UDP/IP headers. Strip them off here. + *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; + return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; + } else { + //TODO: can we ever get here? And is returning 0 if no packets + // are available allowed? + hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); + _hibv_rpkt = 0; + return 0; + } + } +}; +#endif // BF_HPIBV_ENABLED + + class UDPPacketReceiver : public PacketCaptureMethod { #if BF_VMA_ENABLED VMAReceiver _vma; diff --git a/user.mk b/user.mk index bb2908a26..7e76cc48f 100644 --- a/user.mk +++ b/user.mk @@ -32,3 +32,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) +IBV = 1 # Build IB Verbs support using the hashpipe library From f5d60e488ad7a8fbb5d90d574b3105e3bd052584 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 2 Jul 2020 14:50:05 +0000 Subject: [PATCH 079/424] IBVerbs integration Move IB verbs receiving class to a dedicated C file. When using the hashpipe_ibverbs library within packet_capture.hpp directly something in that file messes up the compatibility of the ibverbs structs (their sizes are different) to those interpretted by hashpipe. Odd, but working around for now. --- src/Makefile | 6 +++- src/bf_ibverbs.cpp | 58 ++++++++++++++++++++++++++++++ src/bifrost/bf_ibverbs.h | 17 +++++++++ src/bifrost/io.h | 3 +- src/bifrost/packet_capture.h | 13 +++++++ src/packet_capture.cpp | 24 +++++++++++++ src/packet_capture.hpp | 70 +++++++----------------------------- user.mk | 5 ++- 8 files changed, 136 insertions(+), 60 deletions(-) create mode 100644 src/bf_ibverbs.cpp create mode 100644 src/bifrost/bf_ibverbs.h diff --git a/src/Makefile b/src/Makefile index cf8b69db7..27819cb0b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,6 +44,10 @@ ifdef XGPU bf_xgpu.o endif endif +ifdef IBV + LIBBIFROST_OBJS += \ + bf_ibverbs.o +endif JIT_SOURCES ?= \ Complex.hpp.jit \ @@ -107,7 +111,7 @@ endif ifdef IBV # Requires ibverbs/hashpipe to be installed - LIB += -libverbs -lhashpipe + LIB += -lhashpipe_ibverbs CPPFLAGS += -DBF_HPIBV_ENABLED=1 endif diff --git a/src/bf_ibverbs.cpp b/src/bf_ibverbs.cpp new file mode 100644 index 000000000..7d859f474 --- /dev/null +++ b/src/bf_ibverbs.cpp @@ -0,0 +1,58 @@ +#include +#include "hashpipe_ibverbs.h" +#include + +#define IBV_UDP_PAYLOAD_OFFSET 42 + +extern "C" { +struct hashpipe_ibv_context _hibv_ctx = {0}; +struct hashpipe_ibv_recv_pkt* _hibv_rpkt; // Current packet chain +struct hashpipe_ibv_recv_pkt* _pkt; // Current packet + +BFstatus ibv_init(size_t pkt_size_max) { + fprintf(stderr, "Configuring IBV socket\n"); + int port = 10000; + char ifname[IFNAMSIZ] = "ens1f1"; + strncpy(_hibv_ctx.interface_name, ifname, IFNAMSIZ); + _hibv_ctx.interface_name[IFNAMSIZ-1] = '\0'; // Ensure NUL termination + _hibv_ctx.send_pkt_num = 1; + _hibv_ctx.recv_pkt_num = 8192; + _hibv_ctx.pkt_size_max = pkt_size_max; + _hibv_ctx.max_flows = 1; + int ret = hashpipe_ibv_init(&_hibv_ctx); + if( ret ) { + fprintf(stderr, "ERROR: haspipe_ibv_init returned %d\n", ret); + } + + // Subscribe to RX flow + ret = hashpipe_ibv_flow( + &_hibv_ctx, + 0, IBV_FLOW_SPEC_UDP, + _hibv_ctx.mac, NULL, 0, 0, 0, 0, 0, port); + if( ret ) { + fprintf(stderr, "ERROR: haspipe_ibv_flow returned %d\n", ret); + } + + return BF_STATUS_SUCCESS; +} + +int ibv_recv_packet(uint8_t** pkt_ptr, int flags) { + // If we don't have a work-request queue on the go, + // get some new packets. + if ( _pkt ) { + _pkt = (struct hashpipe_ibv_recv_pkt *)_pkt->wr.next; + if ( !_pkt ) { + hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); + _hibv_rpkt = NULL; + } + } + while (!_hibv_rpkt) { + _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, 1); + _pkt = _hibv_rpkt; + } + // IBV returns Eth/UDP/IP headers. Strip them off here. + *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; + return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; +} + +} diff --git a/src/bifrost/bf_ibverbs.h b/src/bifrost/bf_ibverbs.h new file mode 100644 index 000000000..ce1206c74 --- /dev/null +++ b/src/bifrost/bf_ibverbs.h @@ -0,0 +1,17 @@ +#ifndef BF_IBVERBS_H_INCLUDE_GUARD_ +#define BF_IBVERBS_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +BFstatus ibv_init(size_t pkt_size_max); +int ibv_recv_packet(uint8_t** pkt_ptr, int flags); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_IBVERBS_INCLUDE_GUARD_ diff --git a/src/bifrost/io.h b/src/bifrost/io.h index 086dc8de7..53746a365 100644 --- a/src/bifrost/io.h +++ b/src/bifrost/io.h @@ -39,7 +39,8 @@ typedef enum BFiomethod_ { BF_IO_GENERIC = 0, BF_IO_DISK = 1, BF_IO_UDP = 2, - BF_IO_SNIFFER = 3 + BF_IO_SNIFFER = 3, + BF_IO_IBV_UDP = 4 } BFiomethod; typedef enum BFiowhence_ { diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 0bf38c64e..9f05a2be0 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -106,6 +106,19 @@ BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, BFsize slot_ntime, BFpacketcapture_callback sequence_callback, int core); + +BFstatus bfIbvUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); + BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, const char* format, int fd, diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 05fadc816..317ed901f 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -326,6 +326,30 @@ BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, BF_IO_UDP); } +BFstatus bfIbvUdpCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { + return BFpacketcapture_create(obj, + format, + fd, + ring, + nsrc, + src0, + buffer_ntime, + slot_ntime, + sequence_callback, + core, + BF_IO_IBV_UDP); +} + BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, const char* format, int fd, diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 5bdc30221..c028d36c0 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -228,69 +228,22 @@ class VMAReceiver { #endif #if BF_HPIBV_ENABLED -#include "hashpipe_ibverbs.h" -#define IBV_UDP_PAYLOAD_OFFSET 42 -class IBVReceiver { - struct hashpipe_ibv_context _hibv_ctx; - struct hashpipe_ibv_recv_pkt* _hibv_rpkt; // Current packet chain - struct hashpipe_ibv_recv_pkt* _pkt; // Current packet +#include + +class IBVUDPPacketReceiver : public PacketCaptureMethod { public: - IBVReceiver(int port, int pkt_size_max, char *ifname) - : _pkt(NULL), _hibv_rpkt(NULL) { - strncpy(_hibv_ctx.interface_name, ifname, IFNAMSIZ); - _hibv_ctx.interface_name[IFNAMSIZ-1] = '\0'; // Ensure NUL termination - _hibv_ctx.send_pkt_num = 1; - _hibv_ctx.recv_pkt_num = 8192; - _hibv_ctx.pkt_size_max = pkt_size_max; - _hibv_ctx.max_flows = 1; - int ret = hashpipe_ibv_init(&_hibv_ctx); - if( ret ) { - //PANIC - } - // Subscribe to RX flow - ret = hashpipe_ibv_flow( - &_hibv_ctx, - 0, IBV_FLOW_SPEC_UDP, - _hibv_ctx.mac, NULL, NULL, NULL, NULL, NULL, - NULL, port); - if( ret ) { - //PANIC - } + IBVUDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_IBV_UDP) + { + ibv_init(pkt_size_max); } - ~IBVReceiver() { } - inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { - // If we don't have a work-request queue on the go, - // get some new packets. - // If we do, walk through the packets in this queue. - // Once at the end of the queue, release the current queue and wait - // for another - if ( !_hibv_rpkt ) { - _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, -1); //infinite timeout - _pkt = _hibv_rpkt; - } else { - _pkt = (struct hashpipe_ibv_recv_pkt *)_pkt->wr.next; - } - if ( !_pkt ) { - hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); - _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, -1); //infinite timeout - _pkt = _hibv_rpkt; - } - if ( _pkt ) { - // IBV returns Eth/UDP/IP headers. Strip them off here. - *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; - return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; - } else { - //TODO: can we ever get here? And is returning 0 if no packets - // are available allowed? - hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); - _hibv_rpkt = 0; - return 0; - } + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + return ibv_recv_packet(pkt_ptr, flags); } + inline const char* get_name() { return "ibv_udp_capture"; } }; #endif // BF_HPIBV_ENABLED - class UDPPacketReceiver : public PacketCaptureMethod { #if BF_VMA_ENABLED VMAReceiver _vma; @@ -728,6 +681,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // TODO: sequence never changes? //return false; //return (pkt->seq % 128 == 0); + return false; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); @@ -1231,6 +1185,8 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new DiskPacketReader(fd, max_payload_size); } else if( backend == BF_IO_UDP ) { method = new UDPPacketReceiver(fd, max_payload_size); + } else if( backend == BF_IO_IBV_UDP ) { + method = new IBVUDPPacketReceiver(fd, max_payload_size); } else if( backend == BF_IO_SNIFFER ) { method = new UDPPacketSniffer(fd, max_payload_size); } else { diff --git a/user.mk b/user.mk index 7e76cc48f..43fc3d96a 100644 --- a/user.mk +++ b/user.mk @@ -23,6 +23,9 @@ CUDA_INCDIR ?= $(CUDA_HOME)/include ALIGNMENT ?= 4096 # Memory allocation alignment +# Defining the below will turn on various compilation +# ifdef clauses. +# ***defining as 0 is the same as defining as 1!*** #NODEBUG = 1 # Disable debugging mode (use this for production releases) #TRACE = 1 # Enable tracing mode (generates annotations for use with nvprof/nvvp) #NOCUDA = 1 # Disable CUDA support @@ -30,6 +33,6 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) #NUMA = 1 # Enable use of numa library for setting affinity of ring memory HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture -VMA = 1 # Enable use of Mellanox libvma in udp_capture +#VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) IBV = 1 # Build IB Verbs support using the hashpipe library From 324bb2ca317a0ddd848507a026b090623e398ab1 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 2 Jul 2020 14:51:47 +0000 Subject: [PATCH 080/424] Add flag to use ibverbs --- python/bifrost/packet_capture.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index fc02d4ffb..a375e6126 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -81,7 +81,8 @@ def end(self): class UDPCapture(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): + buffer_ntime, slot_ntime, sequence_callback, core=None, + ibverbs=False, interface='', port=-1): try: fmt = fmt.encode() except AttributeError: @@ -89,11 +90,19 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, pass if core is None: core = -1 - BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, - max_payload_size, buffer_ntime, slot_ntime, - sequence_callback.obj, core) + if not ibverbs: + BifrostObject.__init__( + self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) + else: + print("Using IBVerbs") + BifrostObject.__init__( + self, _bf.bfIbvUdpCaptureCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) class UDPSniffer(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, From 30217af5a5d92d494eb11cbdaef01019763d0009 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 2 Jul 2020 14:52:29 +0000 Subject: [PATCH 081/424] Change function names to match `bfFunctionName` convention --- src/beamform.cpp | 4 ++-- src/bf_xgpu.cpp | 8 ++++---- src/bifrost/beamform.h | 4 ++-- src/bifrost/bf_xgpu.h | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/beamform.cpp b/src/beamform.cpp index ba40d9e87..190a6232e 100644 --- a/src/beamform.cpp +++ b/src/beamform.cpp @@ -21,7 +21,7 @@ extern "C" { * Initialize the beamformer library */ -BFstatus beamformInitialize( +BFstatus bfBeamformInitialize( int gpudev, int ninputs, int nchans, @@ -42,7 +42,7 @@ BFstatus beamformInitialize( return BF_STATUS_SUCCESS; } -BFstatus beamformRun(BFarray *in, BFarray *out, BFarray *weights) { +BFstatus bfBeamformRun(BFarray *in, BFarray *out, BFarray *weights) { if (in->space != BF_SPACE_CUDA) { fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); return BF_STATUS_INVALID_SPACE; diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 82c923758..25c3774eb 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -24,7 +24,7 @@ static XGPUInfo info; * a pointer to the input and output data (on the host), * and a GPU device ID */ -BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { +BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { int xgpu_error; xgpuInfo(&info); // Don't bother checking sizes if the input space is CUDA. @@ -67,7 +67,7 @@ BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { * doDump : if 1, this is the last call in an integration, and results * will be copied to the host. */ -BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { +BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump) { if (in->space == BF_SPACE_CUDA) { return BF_STATUS_UNSUPPORTED_SPACE; } @@ -100,7 +100,7 @@ BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump) { * will be copied to the host. */ static int newAcc = 1; // flush vacc on the first call -BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump) { +BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump) { if (in->space != BF_SPACE_CUDA) { return BF_STATUS_UNSUPPORTED_SPACE; } @@ -137,7 +137,7 @@ BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump) { * int **vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. * int nvis : The number of visibilities to colate (length of the vismap array) */ -BFstatus xgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap) { +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap) { long long unsigned nvis = num_contiguous_elements(vismap); int xgpu_error; if (in->space != BF_SPACE_CUDA) { diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 5b2e486b4..8fa43a66f 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -1,7 +1,7 @@ #include #include -BFstatus beamformInitialize( +BFstatus bfBeamformInitialize( int gpudev, int ninputs, int nchans, @@ -10,7 +10,7 @@ BFstatus beamformInitialize( int ntime_blocks ); -BFstatus beamformRun( +BFstatus bfBeamformRun( BFarray *in, BFarray *out, BFarray *weights diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 2de082067..ede805053 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -1,7 +1,7 @@ #include #include -BFstatus xgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); -BFstatus xgpuCorrelate(BFarray *in, BFarray *out, int doDump); -BFstatus xgpuKernel(BFarray *in, BFarray *out, int doDump); -BFstatus xgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap); +BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); +BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); +BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap); From faca6c02d781d81f2a2cd6f13f493c802b172c57 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 2 Jul 2020 15:29:19 +0000 Subject: [PATCH 082/424] Change IB verbs packet capture method name to "udp_capture" Evidently, this is the trigger to make `like_bmon` work its magic --- src/packet_capture.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c028d36c0..cd9f41d57 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -240,7 +240,7 @@ class IBVUDPPacketReceiver : public PacketCaptureMethod { inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { return ibv_recv_packet(pkt_ptr, flags); } - inline const char* get_name() { return "ibv_udp_capture"; } + inline const char* get_name() { return "udp_capture"; } }; #endif // BF_HPIBV_ENABLED From c411072dc8c34b23495d6b5af45b7192c6ca9ff1 Mon Sep 17 00:00:00 2001 From: JackH Date: Fri, 3 Jul 2020 16:36:51 +0000 Subject: [PATCH 083/424] Packet receiver OK @ ~28Gb/s Increase RX packet depth of IB verbs interface to 32k (this seems to be the maximum). Make packet handler use AVX stream store instructions. 1. The receiver is currently hard coded for 64 pols per packet. It would be trivial to parameterize this, but it may have some small performance implication. 2. Code loads 64-bit values into a 256-bit AVX register before writing to memory. If the IBV interface can be tweaked to enforce alignment (talk to DM about this) the first stage won't be necessary. 3. 64 pols per packet = 512 bits per memory write (1 freq channel of data). Newer machines supporting AVX512 could probably run faster than the current code by using _mm512_stream_si512 in place of _mm256_stream_si256 --- src/bf_ibverbs.cpp | 4 +++- src/formats/snap2.hpp | 29 ++++++++++++++++++++++------- user.mk | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/bf_ibverbs.cpp b/src/bf_ibverbs.cpp index 7d859f474..38fa2e6a0 100644 --- a/src/bf_ibverbs.cpp +++ b/src/bf_ibverbs.cpp @@ -16,8 +16,10 @@ BFstatus ibv_init(size_t pkt_size_max) { strncpy(_hibv_ctx.interface_name, ifname, IFNAMSIZ); _hibv_ctx.interface_name[IFNAMSIZ-1] = '\0'; // Ensure NUL termination _hibv_ctx.send_pkt_num = 1; - _hibv_ctx.recv_pkt_num = 8192; + _hibv_ctx.recv_pkt_num = 32768; _hibv_ctx.pkt_size_max = pkt_size_max; + fprintf(stderr, "IBV: pkt_size_max: %d\n", _hibv_ctx.pkt_size_max); + fprintf(stderr, "IBV: recv_pkt_num: %d\n", _hibv_ctx.recv_pkt_num); _hibv_ctx.max_flows = 1; int ret = hashpipe_ibv_init(&_hibv_ctx); if( ret ) { diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index a63108c86..ff401123b 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -30,7 +30,8 @@ #include "base.hpp" -//#include // SSE +#include // SSE +#include #define SNAP2_HEADER_MAGIC 0xaabbccdd @@ -141,15 +142,29 @@ class SNAP2Processor : virtual public PacketProcessor { // However, they require aligned memory (otherwise segfault) itype const* __restrict__ in = (itype const*)pkt->payload_ptr; otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + int words_per_chan_in = pkt->npol >> 5; // 32 pols per 256-bit word + int words_per_chan_out = pkt->npol_tot >> 5; + int pol_offset_out = pkt->pol0 >> 5; + int pkt_chan = pkt->chan0; // The first channel in this packet // Copy packet payload one channel at a time. - // Packets have payload format nchans x npols x complexity - // spacing with which channel chunks are copied depends + // Packets have payload format nchans x npols x complexity. + // Output buffer order is chans * npol_total * complexity + // Spacing with which channel chunks are copied depends // on the total number of channels/pols in the system - for(int chan=0; channchan; chan++) { - // // TODO: AVX stores here will probably be much faster - // ::memcpy(&out[(((pkt->npol_tot) * (pkt->chan0 + chan)) + (pkt->pol0)) / 32], - // &in[(pkt->npol / 32) * chan], pkt->npol / 32); + __m256i *dest_p; + __m256i vecbuf[2]; + uint64_t *in64 = (uint64_t *)in; + int c, i; + dest_p = (__m256i *)(out + (words_per_chan_out * (pkt_chan)) + pol_offset_out); + for(c=0; cnchan; c++) { + vecbuf[0] = _mm256_set_epi64x(in64[3], in64[2], in64[1], in64[0]); + vecbuf[1] = _mm256_set_epi64x(in64[7], in64[6], in64[5], in64[4]); + _mm256_stream_si256(dest_p, vecbuf[0]); + _mm256_stream_si256(dest_p+1, vecbuf[1]); + in64 += 8; + dest_p += words_per_chan_out; } } diff --git a/user.mk b/user.mk index 43fc3d96a..e8067c8e5 100644 --- a/user.mk +++ b/user.mk @@ -33,6 +33,6 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) #NUMA = 1 # Enable use of numa library for setting affinity of ring memory HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture -#VMA = 1 # Enable use of Mellanox libvma in udp_capture +VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) IBV = 1 # Build IB Verbs support using the hashpipe library From 42c696acb597b34f99738a8188f98dac44cdd226 Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 6 Jul 2020 13:00:03 +0000 Subject: [PATCH 084/424] Py2->3 decode; tweak exception raising The behaviour of the traceback library has changed in py3, so remove the now nonexistent call. Tweak error handling to properly pass an exception to the cleanup print Fix missing decode() --- tools/like_top.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/like_top.py b/tools/like_top.py index 9af42e2b6..c4750a7f4 100755 --- a/tools/like_top.py +++ b/tools/like_top.py @@ -189,7 +189,7 @@ def get_gpu_memory_usage(): pass else: # Parse the ouptut and turn everything into something useful, if possible - lines = output.split('\n')[:-1] + lines = output.decode().split('\n')[:-1] for line in lines: used, total, free, draw, limit, load = line.split(',') data['devCount'] += 1 @@ -402,7 +402,8 @@ def main(args): except KeyboardInterrupt: pass - except Exception as error: + except Exception as err: + error = err exc_type, exc_value, exc_traceback = sys.exc_info() fileObject = StringIO() traceback.print_tb(exc_traceback, file=fileObject) @@ -428,7 +429,7 @@ def main(args): # Final reporting try: ## Error - print("%s: failed with %s at line %i" % (os.path.basename(__file__), str(error), traceback.tb_lineno(exc_traceback))) + print("%s: failed with %s" % (os.path.basename(__file__), str(error))) for line in tbString.split('\n'): print(line) except NameError: From 2ec319c3dfb4a51c0b0bb0f61ff29d48eafb518c Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 6 Jul 2020 15:03:53 +0000 Subject: [PATCH 085/424] Add gbps throughput to like_top Time metrics for processing / waiting for input/output data are helpful for figuringout the bottlenecks in the pipeline, but aren't particularly intuitive (IMO) measures of whether things are "fast enough" --- tools/like_top.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/like_top.py b/tools/like_top.py index c4750a7f4..d2b1fd18d 100755 --- a/tools/like_top.py +++ b/tools/like_top.py @@ -333,10 +333,11 @@ def main(args): ac = max([0.0, log['acquire_time']]) pr = max([0.0, log['process_time']]) re = max([0.0, log['reserve_time']]) + gb = max([0.0, log.get('gbps', 0.0)]) except KeyError: - ac, pr, re = 0.0, 0.0, 0.0 + ac, pr, re, gb = 0.0, 0.0, 0.0, 0.0 - blockList['%i-%s' % (pid, block)] = {'pid': pid, 'name':block, 'cmd': cmd, 'core': cr, 'acquire': ac, 'process': pr, 'reserve': re, 'total':ac+pr+re} + blockList['%i-%s' % (pid, block)] = {'pid': pid, 'name':block, 'cmd': cmd, 'core': cr, 'acquire': ac, 'process': pr, 'reserve': re, 'total':ac+pr+re, 'gbps':gb} ## Sort order = sorted(blockList, key=lambda x: blockList[x][sort_key], reverse=sort_rev) @@ -374,7 +375,7 @@ def main(args): k = _add_line(scr, k, 0, output, std) ### Header k = _add_line(scr, k, 0, ' ', std) - output = '%6s %15s %4s %5s %7s %7s %7s %7s Cmd' % ('PID', 'Block', 'Core', '%CPU', 'Total', 'Acquire', 'Process', 'Reserve') + output = '%6s %15s %4s %5s %7s %7s %7s %7s %7s Cmd' % ('PID', 'Block', 'Core', '%CPU', 'Total', 'Acquire', 'Process', 'Reserve', 'Gbits/s') csize = size[1]-len(output) output += ' '*csize output += '\n' @@ -387,7 +388,7 @@ def main(args): c = '%5.1f' % c except KeyError: c = '%5s' % ' ' - output = '%6i %15s %4i %5s %7.3f %7.3f %7.3f %7.3f %s' % (d['pid'], d['name'][:15], d['core'], c, d['total'], d['acquire'], d['process'], d['reserve'], d['cmd'][:csize+3]) + output = '%6i %15s %4i %5s %7.3f %7.3f %7.3f %7.3f %7.3f %s' % (d['pid'], d['name'][:15], d['core'], c, d['total'], d['acquire'], d['process'], d['reserve'], d['gbps'], d['cmd'][:csize+3]) k = _add_line(scr, k, 0, output, std) if k >= size[0] - 1: break From 498034ea3623e08a5ba23450ee05c51096575e94 Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 6 Jul 2020 15:04:58 +0000 Subject: [PATCH 086/424] Create new sequences every 480 time samples for SNAP2 packets This is a gross thing to hardcode, so FIXME. But, having new sequences periodically means that the header timestamps can be used as actual timestamps, rather than just counting bytes in some infinite data stream (which doesn't seem like a good idea when the input stream is from a network, and could conceivably behave strangely). Having timestamps derived from actual packet headers periodically seems sensible(?) --- src/packet_capture.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index cd9f41d57..c61454098 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -678,10 +678,9 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { } // Has the configuration changed? I.e., different channels being sent. inline bool has_sequence_changed(const PacketDesc* pkt) { - // TODO: sequence never changes? + // TODO: Decide what a sequence actually is! + return (pkt->seq % 480 == 0); //return false; - //return (pkt->seq % 128 == 0); - return false; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); From 756e59bc5109025507de6dc1e6e6e09efa95f00e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 11 Jul 2020 13:39:26 -0600 Subject: [PATCH 087/424] Started working on an IB verbs interface for Bifrost using hashpipe as a template. It compiles. --- src/Makefile | 10 + src/ib_verbs.cpp | 458 +++++++++++++++++++++++++++++++++++++++++ src/ib_verbs.hpp | 208 +++++++++++++++++++ src/packet_capture.hpp | 29 ++- user.mk | 1 + 5 files changed, 700 insertions(+), 6 deletions(-) create mode 100644 src/ib_verbs.cpp create mode 100644 src/ib_verbs.hpp diff --git a/src/Makefile b/src/Makefile index 46c50b7cc..071888f80 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,6 +20,10 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o +ifdef IBVERBS + # These files require IB verbs to combine + LIBBIFROST_OBJS += \ + ib_verbs.o \ ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ @@ -97,6 +101,12 @@ ifdef VMA CPPFLAGS += -DBF_VMA_ENABLED=1 endif +ifdef IBVERBS + # Requires Mellanox libvma to be installed + LIB += -lvma + CPPFLAGS += -DBF_IBVERBS_ENABLED=1 +endif + ifdef ALIGNMENT CPPFLAGS += -DBF_ALIGNMENT=$(ALIGNMENT) endif diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp new file mode 100644 index 000000000..03e859250 --- /dev/null +++ b/src/ib_verbs.cpp @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2020, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ib_verbs.hpp" + +void IBVerbsReceiver::create_context() { + int d, p, g; + int ndev, found; + struct ibv_context* ibv_ctx = NULL; + struct ibv_device_attr ibv_dev_attr; + struct ibv_port_attr ibv_port_attr; + union ibv_gid ibv_gid; + + // Get the interface ID + found = 0; + uint64_t iid = this->get_interface_id(); + + // Find the right device + /* Query all devices */ + _dev_list = ibv_get_device_list(&ndev); + check_null(_dev_list, + "ibv_get_device_list"); + + /* Interogate */ + for(d=0; dfd, F_GETFL); + ::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK); + + // Setup the completion queues + _cq = (struct ibv_cq**) ::malloc(BF_IBVERBS_NQP * sizeof(struct ibv_cq*)); + check_null(_cq, + "cannot allocate completion queues"); + + for(i=0; ilkey; + } + } + + // Link the work requests to receive queue + for(i=0; iget_port()); + flow.spec_tcp_udp.mask.dst_port = 0xffff; + + // Filter on the destination MAC address + flow.attr.size += sizeof(struct ibv_flow_spec_eth); + flow.attr.num_of_specs++; + this->get_mac((uint8_t*) &(flow.spec_eth.val.dst_mac)); + ::memset(flow.spec_eth.mask.dst_mac, 0xff, 6); + + // Create the flows + for(i=0; iwr.wr_id / BF_IBVERBS_NPKTBUF; + return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); +} + +struct bf_ibv_recv_pkt* IBVerbsReceiver::receive(int timeout_ms) { + int i; + int num_wce; + uint64_t wr_id; + struct pollfd pfd; + struct ibv_qp_attr qp_attr; + struct ibv_cq *ev_cq; + intptr_t ev_cq_ctx; + struct ibv_wc wc[BF_IBVERBS_WCBATCH]; + struct bf_ibv_recv_pkt * recv_head = NULL; + struct ibv_recv_wr * recv_tail = NULL; + + // Ensure the queue pairs are in a state suitable for receiving + for(i=0; istate) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _port_num; + if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + break; + case IBV_QPS_RTR: + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + // Setup for poll + pfd.fd = _cc->fd; + pfd.events = POLLIN; + pfd.revents = 0; + + // poll completion channel's fd with given timeout + if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { + // Timeout or error + return NULL; + } + + // Get the completion event + if( ibv_get_cq_event(_cc, &ev_cq, (void **)&ev_cq_ctx) ) { + return NULL; + } + + // Ack the event + ibv_ack_cq_events(ev_cq, 1); + + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + if( ibv_req_notify_cq(ev_cq, 0) ) { + return NULL; + } + + // Empty the CQ: poll all of the completions from the CQ (if any exist) + do { + num_wce = ibv_poll_cq(ev_cq, BF_IBVERBS_WCBATCH, wc); + if( num_wce < 0 ) { + return NULL; + } + + // Loop through all work completions + for(i=0; iwr; + } else { + recv_tail->next = &(_pkt_buf[wr_id].wr); + recv_tail = recv_tail->next; + } + } // for each work completion + } while(num_wce); + + // Ensure list is NULL terminated (if we have a list) + if(recv_tail) { + recv_tail->next = NULL; + } + + return recv_head; +} + diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp new file mode 100644 index 000000000..865e755be --- /dev/null +++ b/src/ib_verbs.hpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2020, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifndef BF_IBVERBS_NQP +#define BF_IBVERBS_NQP 1 +#endif + +#ifndef BF_IBVERBS_NPKTBUF +#define BF_IBVERBS_NPKTBUF 32768 +#endif + +#ifndef BF_IBVERBS_WCBATCH +#define BF_IBVERBS_WCBATCH 16 +#endif + +#define IBV_UDP_PAYLOAD_OFFSET 42 + +struct bf_ibv_recv_pkt { + struct ibv_recv_wr wr; + uint32_t length; +}; + +// Structure for defining various types of flow rules +struct bf_ibv_flow { + struct ibv_flow_attr attr; + struct ibv_flow_spec_eth spec_eth; + struct ibv_flow_spec_ipv4 spec_ipv4; + struct ibv_flow_spec_tcp_udp spec_tcp_udp; +} __attribute__((packed)); + +class IBVerbsReceiver { + int _fd; + size_t _pkt_size_max; + + struct ibv_device** _dev_list = NULL; + struct ibv_context* _ctx = NULL; + struct ibv_device_attr _dev_attr; + uint8_t _port_num; + struct ibv_pd* _pd = NULL; + struct ibv_comp_channel* _cc = NULL; + struct ibv_cq** _cq = NULL; + struct ibv_qp** _qp = NULL; + struct ibv_sge* _sge = NULL; + struct ibv_flow** _flows = NULL; + + struct bf_ibv_recv_pkt* _pkt_buf = NULL; + struct bf_ibv_recv_pkt* _pkt; + struct bf_ibv_recv_pkt* _chain; + + uint8_t* _mr_buf = NULL; + size_t _mr_size = 0; + struct ibv_mr* _mr = NULL; + + int32_t _nqp = BF_IBVERBS_NQP; + int32_t _npkt = BF_IBVERBS_NPKTBUF; + int32_t _nflows = 1; + + uint64_t get_interface_id() { + uint64_t id; + uint8_t buf[8] = {0}; + struct ifreq ethreq; + ::ioctl(_fd, SIOCGIFHWADDR, ðreq); + + ::memcpy(buf, (unsigned char*) ethreq.ifr_hwaddr.sa_data, 3); + buf[0] ^= 2; // Toggle G/L bit per modified EUI-64 spec + buf[3] = 0xff; + buf[4] = 0xfe; + ::memcpy(buf+5, (unsigned char*) ethreq.ifr_hwaddr.sa_data+3, 3); + ::memcpy(&id, buf, 8); + return id; + } + void get_mac(uint8_t* mac) { + struct ifreq ethreq; + ::ioctl(_fd, SIOCGIFHWADDR, ðreq); + + ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); + } + uint16_t get_port() { + struct sockaddr_in sin; + socklen_t len = sizeof(sin); + ::getsockname(_fd, (struct sockaddr *)&sin, &len); + return ntohs(sin.sin_port); + } + void create_context(); + void destroy_context(); + void create_buffers(); + void destroy_buffers(); + void create_queues(); + void destroy_queues(); + void link_work_requests(); + void create_flows(); + void destroy_flows(); + int release(bf_ibv_recv_pkt*); + struct bf_ibv_recv_pkt* receive(int timeout_ms=1); + inline void check_error(int retval, std::string what) { + if( retval < 0 ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw IBVerbsReceiver::Error(ss.str()); + } + } + inline void check_null(void* ptr, std::string what) { + if( ptr == NULL ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw IBVerbsReceiver::Error(ss.str()); + } + } +public: + class Error : public std::runtime_error { + typedef std::runtime_error super_t; + protected: + virtual const char* what() const throw() { + return super_t::what(); + } + public: + Error(const std::string& what_arg) + : super_t(what_arg) {} + }; + + IBVerbsReceiver(int fd, size_t pkt_size_max) + : _fd(fd), _pkt_size_max(pkt_size_max) { + create_context(); + create_buffers(); + create_queues(); + link_work_requests(); + create_flows(); + } + ~IBVerbsReceiver() { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + } + inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { + // If we don't have a work-request queue on the go, + // get some new packets. + if ( _pkt ) { + _pkt = (struct bf_ibv_recv_pkt *)_pkt->wr.next; + if ( !_pkt ) { + release(_chain); + _chain = NULL; + } + } + while( !_chain ) { + _chain = receive(1); + _pkt = _chain; + } + // IBV returns Eth/UDP/IP headers. Strip them off here. + *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; + return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; + } + inline operator bool() const { return true; } +}; + diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index bce215344..0fc0e833e 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -176,10 +176,17 @@ class DiskPacketReader : public PacketCaptureMethod { // TODO: The VMA API is returning unaligned buffers, which prevents use of SSE #ifndef BF_VMA_ENABLED #define BF_VMA_ENABLED 0 -//#define BF_VMA_ENABLED 1 #endif -#if BF_VMA_ENABLED +// NOTE: IBVERBS overrides VMA +#ifndef BF_IBVERBS_ENABLED +#define BF_IBVERBS_ENABLED 0 +#endif + +#if BF_IBVERBS_ENABLED +#include "ib_verbs.hpp" + +#elif BF_VMA_ENABLED #include class VMAReceiver { int _fd; @@ -224,18 +231,28 @@ class VMAReceiver { #endif // BF_VMA_ENABLED class UDPPacketReceiver : public PacketCaptureMethod { -#if BF_VMA_ENABLED +#if BF_IBVERBS_ENABLED + IBVerbsReceiver _ibv; +#elif BF_VMA_ENABLED VMAReceiver _vma; #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP) -#if BF_VMA_ENABLED +#if BF_IBVERBS_ENABLED + , _ibv(fd, pkt_size_max) +#elif BF_VMA_ENABLED , _vma(fd) #endif {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { -#if BF_VMA_ENABLED + +#if BF_IBVERBS_ENABLED + if( _ibv ) { + *pkt_ptr = 0; + return _ibv.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); + } else { +#elif BF_VMA_ENABLED if( _vma ) { *pkt_ptr = 0; return _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); @@ -243,7 +260,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { #endif *pkt_ptr = &_buf[0]; return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0); -#if BF_VMA_ENABLED +#if BF_IBVERBS_ENABLED || BF_VMA_ENABLED } #endif } diff --git a/user.mk b/user.mk index 09f7be577..e458ec332 100644 --- a/user.mk +++ b/user.mk @@ -28,3 +28,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #NUMA = 1 # Enable use of numa library for setting affinity of ring memory #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture +#IBVERBS = 1 # Enable use of IB verbs in udp_capture From 60573db9976cc7251d13d37c37993daaa44fe61e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 11 Jul 2020 13:46:35 -0600 Subject: [PATCH 088/424] IBVerbs -> Verbs --- src/Makefile | 6 ++-- src/ib_verbs.cpp | 68 +++++++++++++++++++++--------------------- src/ib_verbs.hpp | 26 ++++++++-------- src/packet_capture.hpp | 16 +++++----- user.mk | 2 +- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/Makefile b/src/Makefile index 071888f80..a41615e39 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o -ifdef IBVERBS +ifdef VERBS # These files require IB verbs to combine LIBBIFROST_OBJS += \ ib_verbs.o \ @@ -101,10 +101,10 @@ ifdef VMA CPPFLAGS += -DBF_VMA_ENABLED=1 endif -ifdef IBVERBS +ifdef VERBS # Requires Mellanox libvma to be installed LIB += -lvma - CPPFLAGS += -DBF_IBVERBS_ENABLED=1 + CPPFLAGS += -DBF_VERBS_ENABLED=1 endif ifdef ALIGNMENT diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 03e859250..70919b77b 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -28,7 +28,7 @@ #include "ib_verbs.hpp" -void IBVerbsReceiver::create_context() { +void VerbsReceiver::create_context() { int d, p, g; int ndev, found; struct ibv_context* ibv_ctx = NULL; @@ -93,11 +93,11 @@ void IBVerbsReceiver::create_context() { // Done if( !found ) { destroy_context(); - throw IBVerbsReceiver::Error("specified device not found"); + throw VerbsReceiver::Error("specified device not found"); } } -void IBVerbsReceiver::destroy_context() { +void VerbsReceiver::destroy_context() { int failures = 0; if( _ctx ) { if( ibv_close_device(_ctx) ) { @@ -110,19 +110,19 @@ void IBVerbsReceiver::destroy_context() { } } -void IBVerbsReceiver::create_buffers() { +void VerbsReceiver::create_buffers() { // Setup the protected domain _pd = ibv_alloc_pd(_ctx); // Create the buffers, the scatter/gather entries, and the memory region - _pkt_buf = (bf_ibv_recv_pkt*) ::malloc(BF_IBVERBS_NPKTBUF*BF_IBVERBS_NQP * sizeof(bf_ibv_recv_pkt)); + _pkt_buf = (bf_ibv_recv_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(bf_ibv_recv_pkt)); check_null(_pkt_buf, "cannot allocate receive packet buffer"); - _sge = (struct ibv_sge*) ::malloc(BF_IBVERBS_NPKTBUF*BF_IBVERBS_NQP * sizeof(struct ibv_sge)); + _sge = (struct ibv_sge*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct ibv_sge)); check_null(_sge, "cannot allocate scatter/gather entries"); - ::memset(_sge, 0, BF_IBVERBS_NPKTBUF*BF_IBVERBS_NQP * sizeof(struct ibv_sge)); - _mr_size = (size_t) BF_IBVERBS_NPKTBUF*BF_IBVERBS_NQP * _pkt_size_max; + ::memset(_sge, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct ibv_sge)); + _mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; _mr_buf = (uint8_t *) ::malloc(_mr_size); ::memset(_mr_buf, 0, _mr_size); check_null(_mr_buf, @@ -132,7 +132,7 @@ void IBVerbsReceiver::create_buffers() { "cannot register memory region"); } -void IBVerbsReceiver::destroy_buffers() { +void VerbsReceiver::destroy_buffers() { int failures = 0; if( _mr ) { if( ibv_dereg_mr(_mr) ) { @@ -159,7 +159,7 @@ void IBVerbsReceiver::destroy_buffers() { } } -void IBVerbsReceiver::create_queues() { +void VerbsReceiver::create_queues() { int i; // Setup the completion channel and make it non-blocking @@ -170,12 +170,12 @@ void IBVerbsReceiver::create_queues() { ::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK); // Setup the completion queues - _cq = (struct ibv_cq**) ::malloc(BF_IBVERBS_NQP * sizeof(struct ibv_cq*)); + _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); check_null(_cq, "cannot allocate completion queues"); - for(i=0; iwr.wr_id / BF_IBVERBS_NPKTBUF; + i = recv_pkt->wr.wr_id / BF_VERBS_NPKTBUF; return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); } -struct bf_ibv_recv_pkt* IBVerbsReceiver::receive(int timeout_ms) { +struct bf_ibv_recv_pkt* VerbsReceiver::receive(int timeout_ms) { int i; int num_wce; uint64_t wr_id; @@ -368,12 +368,12 @@ struct bf_ibv_recv_pkt* IBVerbsReceiver::receive(int timeout_ms) { struct ibv_qp_attr qp_attr; struct ibv_cq *ev_cq; intptr_t ev_cq_ctx; - struct ibv_wc wc[BF_IBVERBS_WCBATCH]; + struct ibv_wc wc[BF_VERBS_WCBATCH]; struct bf_ibv_recv_pkt * recv_head = NULL; struct ibv_recv_wr * recv_tail = NULL; // Ensure the queue pairs are in a state suitable for receiving - for(i=0; istate) { case IBV_QPS_RESET: // Unexpected, but maybe user reset it qp_attr.qp_state = IBV_QPS_INIT; @@ -422,7 +422,7 @@ struct bf_ibv_recv_pkt* IBVerbsReceiver::receive(int timeout_ms) { // Empty the CQ: poll all of the completions from the CQ (if any exist) do { - num_wce = ibv_poll_cq(ev_cq, BF_IBVERBS_WCBATCH, wc); + num_wce = ibv_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc); if( num_wce < 0 ) { return NULL; } diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 865e755be..045735866 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -42,16 +42,16 @@ #include -#ifndef BF_IBVERBS_NQP -#define BF_IBVERBS_NQP 1 +#ifndef BF_VERBS_NQP +#define BF_VERBS_NQP 1 #endif -#ifndef BF_IBVERBS_NPKTBUF -#define BF_IBVERBS_NPKTBUF 32768 +#ifndef BF_VERBS_NPKTBUF +#define BF_VERBS_NPKTBUF 32768 #endif -#ifndef BF_IBVERBS_WCBATCH -#define BF_IBVERBS_WCBATCH 16 +#ifndef BF_VERBS_WCBATCH +#define BF_VERBS_WCBATCH 16 #endif #define IBV_UDP_PAYLOAD_OFFSET 42 @@ -69,7 +69,7 @@ struct bf_ibv_flow { struct ibv_flow_spec_tcp_udp spec_tcp_udp; } __attribute__((packed)); -class IBVerbsReceiver { +class VerbsReceiver { int _fd; size_t _pkt_size_max; @@ -92,8 +92,8 @@ class IBVerbsReceiver { size_t _mr_size = 0; struct ibv_mr* _mr = NULL; - int32_t _nqp = BF_IBVERBS_NQP; - int32_t _npkt = BF_IBVERBS_NPKTBUF; + int32_t _nqp = BF_VERBS_NQP; + int32_t _npkt = BF_VERBS_NPKTBUF; int32_t _nflows = 1; uint64_t get_interface_id() { @@ -143,7 +143,7 @@ class IBVerbsReceiver { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw IBVerbsReceiver::Error(ss.str()); + throw VerbsReceiver::Error(ss.str()); } } inline void check_null(void* ptr, std::string what) { @@ -156,7 +156,7 @@ class IBVerbsReceiver { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw IBVerbsReceiver::Error(ss.str()); + throw VerbsReceiver::Error(ss.str()); } } public: @@ -171,7 +171,7 @@ class IBVerbsReceiver { : super_t(what_arg) {} }; - IBVerbsReceiver(int fd, size_t pkt_size_max) + VerbsReceiver(int fd, size_t pkt_size_max) : _fd(fd), _pkt_size_max(pkt_size_max) { create_context(); create_buffers(); @@ -179,7 +179,7 @@ class IBVerbsReceiver { link_work_requests(); create_flows(); } - ~IBVerbsReceiver() { + ~VerbsReceiver() { destroy_flows(); destroy_queues(); destroy_buffers(); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 0fc0e833e..c795aeb43 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -178,12 +178,12 @@ class DiskPacketReader : public PacketCaptureMethod { #define BF_VMA_ENABLED 0 #endif -// NOTE: IBVERBS overrides VMA -#ifndef BF_IBVERBS_ENABLED -#define BF_IBVERBS_ENABLED 0 +// NOTE: VERBS overrides VMA +#ifndef BF_VERBS_ENABLED +#define BF_VERBS_ENABLED 0 #endif -#if BF_IBVERBS_ENABLED +#if BF_VERBS_ENABLED #include "ib_verbs.hpp" #elif BF_VMA_ENABLED @@ -231,7 +231,7 @@ class VMAReceiver { #endif // BF_VMA_ENABLED class UDPPacketReceiver : public PacketCaptureMethod { -#if BF_IBVERBS_ENABLED +#if BF_VERBS_ENABLED IBVerbsReceiver _ibv; #elif BF_VMA_ENABLED VMAReceiver _vma; @@ -239,7 +239,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP) -#if BF_IBVERBS_ENABLED +#if BF_VERBS_ENABLED , _ibv(fd, pkt_size_max) #elif BF_VMA_ENABLED , _vma(fd) @@ -247,7 +247,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { -#if BF_IBVERBS_ENABLED +#if BF_VERBS_ENABLED if( _ibv ) { *pkt_ptr = 0; return _ibv.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); @@ -260,7 +260,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { #endif *pkt_ptr = &_buf[0]; return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0); -#if BF_IBVERBS_ENABLED || BF_VMA_ENABLED +#if BF_VERBS_ENABLED || BF_VMA_ENABLED } #endif } diff --git a/user.mk b/user.mk index e458ec332..7dde3d0d6 100644 --- a/user.mk +++ b/user.mk @@ -28,4 +28,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #NUMA = 1 # Enable use of numa library for setting affinity of ring memory #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture -#IBVERBS = 1 # Enable use of IB verbs in udp_capture +#VERBS = 1 # Enable use of IB verbs in udp_capture From 4ffaadfd3bff48a9d076ccf349b4a11629a50b03 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 11 Jul 2020 14:28:45 -0600 Subject: [PATCH 089/424] Made ib_verbs more like a hybrid of Socket and the VMA API. Added a new UDPVerbsReceiver class to packet_capture.hpp. --- src/Makefile | 3 ++- src/bifrost/io.h | 3 ++- src/ib_verbs.cpp | 24 ++++++++++---------- src/ib_verbs.hpp | 16 ++++++------- src/packet_capture.hpp | 51 ++++++++++++++++++++++++------------------ 5 files changed, 53 insertions(+), 44 deletions(-) diff --git a/src/Makefile b/src/Makefile index a41615e39..38f5443fd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,7 +23,8 @@ LIBBIFROST_OBJS = \ ifdef VERBS # These files require IB verbs to combine LIBBIFROST_OBJS += \ - ib_verbs.o \ + ib_verbs.o +endif ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ diff --git a/src/bifrost/io.h b/src/bifrost/io.h index 086dc8de7..a5ef3616e 100644 --- a/src/bifrost/io.h +++ b/src/bifrost/io.h @@ -39,7 +39,8 @@ typedef enum BFiomethod_ { BF_IO_GENERIC = 0, BF_IO_DISK = 1, BF_IO_UDP = 2, - BF_IO_SNIFFER = 3 + BF_IO_SNIFFER = 3, + BF_IO_VERBS = 4 } BFiomethod; typedef enum BFiowhence_ { diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 70919b77b..9dc7d3f0b 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -28,7 +28,7 @@ #include "ib_verbs.hpp" -void VerbsReceiver::create_context() { +void Verbs::create_context() { int d, p, g; int ndev, found; struct ibv_context* ibv_ctx = NULL; @@ -93,11 +93,11 @@ void VerbsReceiver::create_context() { // Done if( !found ) { destroy_context(); - throw VerbsReceiver::Error("specified device not found"); + throw Verbs::Error("specified device not found"); } } -void VerbsReceiver::destroy_context() { +void Verbs::destroy_context() { int failures = 0; if( _ctx ) { if( ibv_close_device(_ctx) ) { @@ -110,7 +110,7 @@ void VerbsReceiver::destroy_context() { } } -void VerbsReceiver::create_buffers() { +void Verbs::create_buffers() { // Setup the protected domain _pd = ibv_alloc_pd(_ctx); @@ -132,7 +132,7 @@ void VerbsReceiver::create_buffers() { "cannot register memory region"); } -void VerbsReceiver::destroy_buffers() { +void Verbs::destroy_buffers() { int failures = 0; if( _mr ) { if( ibv_dereg_mr(_mr) ) { @@ -159,7 +159,7 @@ void VerbsReceiver::destroy_buffers() { } } -void VerbsReceiver::create_queues() { +void Verbs::create_queues() { int i; // Setup the completion channel and make it non-blocking @@ -219,7 +219,7 @@ void VerbsReceiver::create_queues() { } -void VerbsReceiver::destroy_queues() { +void Verbs::destroy_queues() { int failures = 0; if( _qp ) { @@ -247,7 +247,7 @@ void VerbsReceiver::destroy_queues() { } } -void VerbsReceiver::link_work_requests() { +void Verbs::link_work_requests() { // Make sure we are ready to go check_null(_pkt_buf, "packet buffer has not been created"); @@ -289,7 +289,7 @@ void VerbsReceiver::link_work_requests() { } } -void VerbsReceiver::create_flows() { +void Verbs::create_flows() { // Setup the flows _flows = (struct ibv_flow**) ::malloc(_nflows*BF_VERBS_NQP * sizeof(struct ibv_flow*)); check_null(_flows, @@ -333,7 +333,7 @@ void VerbsReceiver::create_flows() { } } -void VerbsReceiver::destroy_flows() { +void Verbs::destroy_flows() { int failures = 0; if( _flows ) { @@ -347,7 +347,7 @@ void VerbsReceiver::destroy_flows() { } // See comments in header file for details about this function. -int VerbsReceiver::release(struct bf_ibv_recv_pkt* recv_pkt) { +int Verbs::release(struct bf_ibv_recv_pkt* recv_pkt) { int i; struct ibv_recv_wr* recv_wr_bad; @@ -360,7 +360,7 @@ int VerbsReceiver::release(struct bf_ibv_recv_pkt* recv_pkt) { return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); } -struct bf_ibv_recv_pkt* VerbsReceiver::receive(int timeout_ms) { +struct bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { int i; int num_wce; uint64_t wr_id; diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 045735866..471d16c60 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -54,7 +54,7 @@ #define BF_VERBS_WCBATCH 16 #endif -#define IBV_UDP_PAYLOAD_OFFSET 42 +#define BF_VERBS_PAYLOAD_OFFSET 42 struct bf_ibv_recv_pkt { struct ibv_recv_wr wr; @@ -69,7 +69,7 @@ struct bf_ibv_flow { struct ibv_flow_spec_tcp_udp spec_tcp_udp; } __attribute__((packed)); -class VerbsReceiver { +class Verbs { int _fd; size_t _pkt_size_max; @@ -143,7 +143,7 @@ class VerbsReceiver { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw VerbsReceiver::Error(ss.str()); + throw Verbs::Error(ss.str()); } } inline void check_null(void* ptr, std::string what) { @@ -156,7 +156,7 @@ class VerbsReceiver { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw VerbsReceiver::Error(ss.str()); + throw Verbs::Error(ss.str()); } } public: @@ -171,7 +171,7 @@ class VerbsReceiver { : super_t(what_arg) {} }; - VerbsReceiver(int fd, size_t pkt_size_max) + Verbs(int fd, size_t pkt_size_max) : _fd(fd), _pkt_size_max(pkt_size_max) { create_context(); create_buffers(); @@ -179,7 +179,7 @@ class VerbsReceiver { link_work_requests(); create_flows(); } - ~VerbsReceiver() { + ~Verbs() { destroy_flows(); destroy_queues(); destroy_buffers(); @@ -200,8 +200,8 @@ class VerbsReceiver { _pkt = _chain; } // IBV returns Eth/UDP/IP headers. Strip them off here. - *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; - return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; + *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; + return _pkt->length - BF_VERBS_PAYLOAD_OFFSET; } inline operator bool() const { return true; } }; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c795aeb43..9c6e631b3 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -178,15 +178,7 @@ class DiskPacketReader : public PacketCaptureMethod { #define BF_VMA_ENABLED 0 #endif -// NOTE: VERBS overrides VMA -#ifndef BF_VERBS_ENABLED -#define BF_VERBS_ENABLED 0 -#endif - -#if BF_VERBS_ENABLED -#include "ib_verbs.hpp" - -#elif BF_VMA_ENABLED +#if BF_VMA_ENABLED #include class VMAReceiver { int _fd; @@ -231,28 +223,19 @@ class VMAReceiver { #endif // BF_VMA_ENABLED class UDPPacketReceiver : public PacketCaptureMethod { -#if BF_VERBS_ENABLED - IBVerbsReceiver _ibv; -#elif BF_VMA_ENABLED +#if BF_VMA_ENABLED VMAReceiver _vma; #endif public: UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP) -#if BF_VERBS_ENABLED - , _ibv(fd, pkt_size_max) -#elif BF_VMA_ENABLED +#if BF_VMA_ENABLED , _vma(fd) #endif {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { -#if BF_VERBS_ENABLED - if( _ibv ) { - *pkt_ptr = 0; - return _ibv.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); - } else { -#elif BF_VMA_ENABLED +#if BF_VMA_ENABLED if( _vma ) { *pkt_ptr = 0; return _vma.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); @@ -260,7 +243,7 @@ class UDPPacketReceiver : public PacketCaptureMethod { #endif *pkt_ptr = &_buf[0]; return ::recvfrom(_fd, &_buf[0], _buf.size(), flags, 0, 0); -#if BF_VERBS_ENABLED || BF_VMA_ENABLED +#if BF_VMA_ENABLED } #endif } @@ -296,6 +279,26 @@ class UDPPacketSniffer : public PacketCaptureMethod { inline const char* get_name() { return "udp_sniffer"; } }; +#ifndef BF_VERBS_ENABLED +#define BF_VERBS_ENABLED 0 +#endif + +#if BF_VERBS_ENABLED +#include "ib_verbs.hpp" + +class UDPVerbsReceiver : public PacketCaptureMethod { + Verbs _ibv; +public: + UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max) {} + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + *pkt_ptr = 0; + return _ibv.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); + } + inline const char* get_name() { return "udp_verbs_capture"; } +}; +#endif // BF_VERBS_ENABLED + struct PacketStats { size_t ninvalid; size_t ninvalid_bytes; @@ -1099,6 +1102,10 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new UDPPacketReceiver(fd, max_payload_size); } else if( backend == BF_IO_SNIFFER ) { method = new UDPPacketSniffer(fd, max_payload_size); +#if BF_VERBS_ENABLED + } else if( backend == BF_IO_VERBS ) { + method = new UDPVerbsReceiver(fd, max_payload_size); +#endif } else { return BF_STATUS_UNSUPPORTED; } From 46b38badbba99e3c492b7bf1c5795a96dcf23809 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 11 Jul 2020 14:36:15 -0600 Subject: [PATCH 090/424] Exposed the new UDPVerbsCapture interface through Python. --- python/bifrost/packet_capture.py | 16 ++++++++++++++++ src/bifrost/packet_capture.h | 11 +++++++++++ src/packet_capture.cpp | 24 ++++++++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index f5fc446ca..53ac79764 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -102,6 +102,22 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) +class UDPVerbsCapture(_CaptureBase): + def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, sequence_callback, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpVerbsCaptureCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) + class DiskReader(_CaptureBase): def __init__(self, fmt, fh, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core=None): diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index b32af9bdb..5e4d11235 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -113,6 +113,17 @@ BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, BFsize slot_ntime, BFpacketcapture_callback sequence_callback, int core); +BFstatus bfUdpVerbsCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core); BFstatus bfPacketCaptureDestroy(BFpacketcapture obj); BFstatus bfPacketCaptureRecv(BFpacketcapture obj, BFpacketcapture_status* result); diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index ca594764f..a03b107b4 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -340,6 +340,30 @@ BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, BF_IO_SNIFFER); } +BFstatus bfUdpVerbsCaptureCreate(BFpacketcapture* obj, + const char* format, + int fd, + BFring ring, + BFsize nsrc, + BFsize src0, + BFsize max_payload_size, + BFsize buffer_ntime, + BFsize slot_ntime, + BFpacketcapture_callback sequence_callback, + int core) { + return BFpacketcapture_create(obj, + format, + fd, + ring, + nsrc, + src0, + buffer_ntime, + slot_ntime, + sequence_callback, + core, + BF_IO_VERBS); +} + BFstatus bfPacketCaptureDestroy(BFpacketcapture obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; From fe8b27b46b73e77233070e0a6cddde1560faf999 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 11 Jul 2020 15:06:46 -0600 Subject: [PATCH 091/424] Cleanup. --- src/ib_verbs.cpp | 3 ++- src/ib_verbs.hpp | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 9dc7d3f0b..b461c4b1a 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -118,15 +118,16 @@ void Verbs::create_buffers() { _pkt_buf = (bf_ibv_recv_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(bf_ibv_recv_pkt)); check_null(_pkt_buf, "cannot allocate receive packet buffer"); + ::memset(_pkt_buf, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(bf_ibv_recv_pkt)); _sge = (struct ibv_sge*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct ibv_sge)); check_null(_sge, "cannot allocate scatter/gather entries"); ::memset(_sge, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct ibv_sge)); _mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; _mr_buf = (uint8_t *) ::malloc(_mr_size); - ::memset(_mr_buf, 0, _mr_size); check_null(_mr_buf, "cannot allocate memory region buffer"); + ::memset(_mr_buf, 0, _mr_size); _mr = ibv_reg_mr(_pd, _mr_buf, _mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_mr, "cannot register memory region"); diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 471d16c60..1cc1b7e75 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -85,8 +85,8 @@ class Verbs { struct ibv_flow** _flows = NULL; struct bf_ibv_recv_pkt* _pkt_buf = NULL; - struct bf_ibv_recv_pkt* _pkt; - struct bf_ibv_recv_pkt* _chain; + struct bf_ibv_recv_pkt* _pkt = NULL; + struct bf_ibv_recv_pkt* _chain = NULL; uint8_t* _mr_buf = NULL; size_t _mr_size = 0; @@ -203,6 +203,5 @@ class Verbs { *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; return _pkt->length - BF_VERBS_PAYLOAD_OFFSET; } - inline operator bool() const { return true; } }; From 960137468a5879f4147ab84d8c27219be4871482 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 14 Jul 2020 13:23:25 -0600 Subject: [PATCH 092/424] Various cleanups and fixes. --- src/ib_verbs.cpp | 71 ++++++++++++++++++++++++++---------------------- src/ib_verbs.hpp | 3 +- 2 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index b461c4b1a..f08e62461 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -50,20 +50,20 @@ void Verbs::create_context() { for(d=0; dfd, F_GETFL); - ::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK); + check_error(::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK), + "set completion channel to non-blocking"); // Setup the completion queues _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); check_null(_cq, - "cannot allocate completion queues"); + "allocate completion queues"); for(i=0; i Date: Tue, 14 Jul 2020 14:06:13 -0600 Subject: [PATCH 093/424] Fixed a problem finding the ainterface associated with an address. --- src/ib_verbs.cpp | 24 ++++++++++----------- src/ib_verbs.hpp | 54 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index f08e62461..90a08b044 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -80,7 +80,7 @@ void Verbs::create_context() { if ( found ) { /* Save it to the class so that we can use it later */ - _ctx = ibv_ctx; + _ctx = ibv_ctx; ::memcpy(&_dev_attr, &ibv_dev_attr, sizeof(struct ibv_device_attr)); _port_num = p; break; @@ -169,7 +169,7 @@ void Verbs::create_queues() { "create completion channel"); int flags = ::fcntl(_cc->fd, F_GETFL); check_error(::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); + "set completion channel to non-blocking"); // Setup the completion queues _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); @@ -226,10 +226,10 @@ void Verbs::destroy_queues() { if( _qp ) { for(int i=0; iget_port()); + flow.spec_tcp_udp.val.dst_port = htons(this->get_port()); flow.spec_tcp_udp.mask.dst_port = 0xffff; // Filter on the destination MAC address flow.attr.size += sizeof(struct ibv_flow_spec_eth); flow.attr.num_of_specs++; - this->get_mac((uint8_t*) &(flow.spec_eth.val.dst_mac)); + this->get_mac_address((uint8_t*) &(flow.spec_eth.val.dst_mac)); ::memset(flow.spec_eth.mask.dst_mac, 0xff, 6); // Create the flows @@ -344,10 +344,10 @@ void Verbs::destroy_flows() { if( _flows ) { for(int i=0; i<_nflows; i++) { - if( _flows[i] ) { + if( _flows[i] ) { if( ibv_destroy_flow(_flows[i]) ) { failures += 1; - } + } } } free(_flows); diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 7997e8a5a..8f8a7bc84 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -96,32 +96,56 @@ class Verbs { int32_t _npkt = BF_VERBS_NPKTBUF; int32_t _nflows = 1; - uint64_t get_interface_id() { - uint64_t id; - uint8_t buf[8] = {0}; - struct ifreq ethreq; - ::ioctl(_fd, SIOCGIFHWADDR, ðreq); + void get_interface_name(char* name) { + struct sockaddr_in sin; + char ip[INET_ADDRSTRLEN]; + socklen_t len = sizeof(sin); + check_error(::getsockname(_fd, (struct sockaddr *)&sin, &len), + "query socket name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); - ::memcpy(buf, (unsigned char*) ethreq.ifr_hwaddr.sa_data, 3); - buf[0] ^= 2; // Toggle G/L bit per modified EUI-64 spec - buf[3] = 0xff; - buf[4] = 0xfe; - ::memcpy(buf+5, (unsigned char*) ethreq.ifr_hwaddr.sa_data+3, 3); - ::memcpy(&id, buf, 8); - return id; + // TODO: Is there a better way to find this? + char cmd[256] = {'\0'}; + char line[256] = {'\0'}; + sprintf(cmd, "ip route get to %s | grep dev | awk '{print $4}'", ip); + FILE* fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + strncpy(name, &(line[0]), IFNAMSIZ); + } + pclose(fp); } - void get_mac(uint8_t* mac) { + void get_mac_address(uint8_t* mac) { struct ifreq ethreq; - ::ioctl(_fd, SIOCGIFHWADDR, ðreq); + this->get_interface_name(&(ethreq.ifr_name[0])); + check_error(::ioctl(_fd, SIOCGIFHWADDR, ðreq), + "query interface hardware address"); ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); } uint16_t get_port() { struct sockaddr_in sin; socklen_t len = sizeof(sin); - ::getsockname(_fd, (struct sockaddr *)&sin, &len); + check_error(::getsockname(_fd, (struct sockaddr *)&sin, &len), + "query socket name"); return ntohs(sin.sin_port); } + uint64_t get_interface_id() { + uint64_t id; + uint8_t mac[6] = {0}; + uint8_t buf[8] = {0}; + this->get_mac_address(&(mac[0])); + + ::memcpy(buf, (unsigned char*) &(mac[0]), 3); + buf[0] ^= 2; // Toggle G/L bit per modified EUI-64 spec + buf[3] = 0xff; + buf[4] = 0xfe; + ::memcpy(buf+5, (unsigned char*) &(mac[3]), 3); + ::memcpy(&id, buf, 8); + return id; + } void create_context(); void destroy_context(); void create_buffers(); From 5f6b1d5b43011fac73e24b2bb2f69c779142194f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 14 Jul 2020 14:48:30 -0600 Subject: [PATCH 094/424] Even more cleanup. --- src/ib_verbs.cpp | 26 ++++++++++++++++++++++---- src/ib_verbs.hpp | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 90a08b044..ddc6c8132 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -26,8 +26,19 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include #include "ib_verbs.hpp" +#define BF_JAYCE_DEBUG 1 + +#if BF_JAYCE_DEBUG +#define BF_PRINTD(stmt) \ + std::cout << stmt << std::endl +#else // not BF_JAYCE_DEBUG +#define BF_PRINTD(stmt) +#endif + void Verbs::create_context() { int d, p, g; int ndev, found; @@ -36,9 +47,16 @@ void Verbs::create_context() { struct ibv_port_attr ibv_port_attr; union ibv_gid ibv_gid; - // Get the interface ID + // Get the interface MAC address and GID found = 0; - uint64_t iid = this->get_interface_id(); + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + uint64_t gid = this->get_interface_gid(); + + BF_PRINTD("MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec); + BF_PRINTD("GID: " << std::hex << int((gid >> 24) & 0xFFFF) << ":" << int((gid >> 16) & 0xFFFF) + << ":" << int((gid >> 8) & 0xFFFF) << ":" << int( gid & 0xFFFF) << std::dec); // Find the right device /* Query all devices */ @@ -54,7 +72,7 @@ void Verbs::create_context() { check_error(ibv_query_device(ibv_ctx, &ibv_dev_attr), "query device"); - + /* Loop through the ports on the device */ for(p=1; p<=ibv_dev_attr.phys_port_cnt; p++) { check_error(ibv_query_port(ibv_ctx, p, &ibv_port_attr), @@ -67,7 +85,7 @@ void Verbs::create_context() { /* Did we find a match? */ if( (ibv_gid.global.subnet_prefix == 0x80feUL) \ - && (ibv_gid.global.interface_id == iid) ) { + && (ibv_gid.global.interface_id == gid) ) { found = 1; break; } diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 8f8a7bc84..ac96b8dfa 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -132,7 +132,7 @@ class Verbs { "query socket name"); return ntohs(sin.sin_port); } - uint64_t get_interface_id() { + uint64_t get_interface_gid() { uint64_t id; uint8_t mac[6] = {0}; uint8_t buf[8] = {0}; From 1c121440757ac54b19ed865ba43becc288ef495d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 14 Jul 2020 16:08:00 -0600 Subject: [PATCH 095/424] Made get_interface_name() more robust. --- src/ib_verbs.hpp | 93 ++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index ac96b8dfa..ea598a9e3 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -97,8 +97,8 @@ class Verbs { int32_t _nflows = 1; void get_interface_name(char* name) { - struct sockaddr_in sin; - char ip[INET_ADDRSTRLEN]; + struct sockaddr_in sin; + char ip[INET_ADDRSTRLEN]; socklen_t len = sizeof(sin); check_error(::getsockname(_fd, (struct sockaddr *)&sin, &len), "query socket name"); @@ -107,15 +107,32 @@ class Verbs { // TODO: Is there a better way to find this? char cmd[256] = {'\0'}; char line[256] = {'\0'}; - sprintf(cmd, "ip route get to %s | grep dev | awk '{print $4}'", ip); - FILE* fp = popen(cmd, "r"); - if( fgets(line, sizeof(line), fp) != NULL) { - if( line[strlen(line)-1] == '\n' ) { - line[strlen(line)-1] = '\0'; - } - strncpy(name, &(line[0]), IFNAMSIZ); - } - pclose(fp); + int is_lo = 0; + sprintf(cmd, "ip route get to %s | grep dev | awk '{print $4}'", ip); + FILE* fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + if( strncmp(&(line[0]), "lo", 2) == 0 ) { + is_lo = 1; + } + strncpy(name, &(line[0]), IFNAMSIZ); + } + pclose(fp); + + if( is_lo ) { + // TODO: Is there a way to avoid having to do this? + sprintf(cmd, "ip route show | grep %s | grep -v default | awk '{print $3}'", ip); + fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + strncpy(name, &(line[0]), IFNAMSIZ); + } + pclose(fp); + } } void get_mac_address(uint8_t* mac) { struct ifreq ethreq; @@ -158,42 +175,42 @@ class Verbs { int release(bf_ibv_recv_pkt*); struct bf_ibv_recv_pkt* receive(int timeout_ms=1); inline void check_error(int retval, std::string what) { - if( retval < 0 ) { - destroy_flows(); + if( retval < 0 ) { + destroy_flows(); destroy_queues(); destroy_buffers(); destroy_context(); - std::stringstream ss; - ss << "Failed to " << what << ": (" << errno << ") " - << strerror(errno); - throw Verbs::Error(ss.str()); - } - } + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw Verbs::Error(ss.str()); + } + } inline void check_null(void* ptr, std::string what) { - if( ptr == NULL ) { - destroy_flows(); + if( ptr == NULL ) { + destroy_flows(); destroy_queues(); destroy_buffers(); destroy_context(); - std::stringstream ss; - ss << "Failed to " << what; - throw Verbs::Error(ss.str()); - } - } + std::stringstream ss; + ss << "Failed to " << what; + throw Verbs::Error(ss.str()); + } + } public: class Error : public std::runtime_error { - typedef std::runtime_error super_t; - protected: - virtual const char* what() const throw() { - return super_t::what(); - } - public: - Error(const std::string& what_arg) - : super_t(what_arg) {} - }; - + typedef std::runtime_error super_t; + protected: + virtual const char* what() const throw() { + return super_t::what(); + } + public: + Error(const std::string& what_arg) + : super_t(what_arg) {} + }; + Verbs(int fd, size_t pkt_size_max) : _fd(fd), _pkt_size_max(pkt_size_max) { create_context(); @@ -211,9 +228,9 @@ class Verbs { inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { // If we don't have a work-request queue on the go, // get some new packets. - if ( _pkt ) { + if( _pkt ) { _pkt = (struct bf_ibv_recv_pkt *)_pkt->wr.next; - if ( !_pkt ) { + if( !_pkt ) { release(_chain); _chain = NULL; } From f6622c1e0abd951a3a77778c0941bcdebb95703b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Jul 2020 12:33:27 -0600 Subject: [PATCH 096/424] Merged ib_verbs.cpp into ib_verbs.hpp so that it acts more like Socket.hpp. Added -libverbs to the Makefile. --- src/Makefile | 2 +- src/ib_verbs.cpp | 484 ----------------------------------------------- src/ib_verbs.hpp | 471 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 457 insertions(+), 500 deletions(-) delete mode 100644 src/ib_verbs.cpp diff --git a/src/Makefile b/src/Makefile index 38f5443fd..4544dab7a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -104,7 +104,7 @@ endif ifdef VERBS # Requires Mellanox libvma to be installed - LIB += -lvma + LIB += -lvma -libverbs CPPFLAGS += -DBF_VERBS_ENABLED=1 endif diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp deleted file mode 100644 index ddc6c8132..000000000 --- a/src/ib_verbs.cpp +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright (c) 2020, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include -#include "ib_verbs.hpp" - -#define BF_JAYCE_DEBUG 1 - -#if BF_JAYCE_DEBUG -#define BF_PRINTD(stmt) \ - std::cout << stmt << std::endl -#else // not BF_JAYCE_DEBUG -#define BF_PRINTD(stmt) -#endif - -void Verbs::create_context() { - int d, p, g; - int ndev, found; - struct ibv_context* ibv_ctx = NULL; - struct ibv_device_attr ibv_dev_attr; - struct ibv_port_attr ibv_port_attr; - union ibv_gid ibv_gid; - - // Get the interface MAC address and GID - found = 0; - uint8_t mac[6] = {0}; - this->get_mac_address(&(mac[0])); - uint64_t gid = this->get_interface_gid(); - - BF_PRINTD("MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec); - BF_PRINTD("GID: " << std::hex << int((gid >> 24) & 0xFFFF) << ":" << int((gid >> 16) & 0xFFFF) - << ":" << int((gid >> 8) & 0xFFFF) << ":" << int( gid & 0xFFFF) << std::dec); - - // Find the right device - /* Query all devices */ - _dev_list = ibv_get_device_list(&ndev); - check_null(_dev_list, - "ibv_get_device_list"); - - /* Interogate */ - for(d=0; dfd, F_GETFL); - check_error(::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); - - // Setup the completion queues - _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); - check_null(_cq, - "allocate completion queues"); - - for(i=0; ilkey; - } - } - - // Link the work requests to receive queue - for(i=0; iget_port()); - flow.spec_tcp_udp.mask.dst_port = 0xffff; - - // Filter on the destination MAC address - flow.attr.size += sizeof(struct ibv_flow_spec_eth); - flow.attr.num_of_specs++; - this->get_mac_address((uint8_t*) &(flow.spec_eth.val.dst_mac)); - ::memset(flow.spec_eth.mask.dst_mac, 0xff, 6); - - // Create the flows - for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; - return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); -} - -struct bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { - int i; - int num_wce; - uint64_t wr_id; - struct pollfd pfd; - struct ibv_qp_attr qp_attr; - struct ibv_cq *ev_cq; - intptr_t ev_cq_ctx; - struct ibv_wc wc[BF_VERBS_WCBATCH]; - struct bf_ibv_recv_pkt * recv_head = NULL; - struct ibv_recv_wr * recv_tail = NULL; - - // Ensure the queue pairs are in a state suitable for receiving - for(i=0; istate) { - case IBV_QPS_RESET: // Unexpected, but maybe user reset it - qp_attr.qp_state = IBV_QPS_INIT; - qp_attr.port_num = _port_num; - if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { - return NULL; - } - case IBV_QPS_INIT: - qp_attr.qp_state = IBV_QPS_RTR; - if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE) ) { - return NULL; - } - break; - case IBV_QPS_RTR: - case IBV_QPS_RTS: - break; - default: - return NULL; - } - } - - // Setup for poll - pfd.fd = _cc->fd; - pfd.events = POLLIN; - pfd.revents = 0; - - // poll completion channel's fd with given timeout - if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { - // Timeout or error - return NULL; - } - - // Get the completion event - if( ibv_get_cq_event(_cc, &ev_cq, (void **)&ev_cq_ctx) ) { - return NULL; - } - - // Ack the event - ibv_ack_cq_events(ev_cq, 1); - - // Request notification upon the next completion event - // Do NOT restrict to solicited-only completions - if( ibv_req_notify_cq(ev_cq, 0) ) { - return NULL; - } - - // Empty the CQ: poll all of the completions from the CQ (if any exist) - do { - num_wce = ibv_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc); - if( num_wce < 0 ) { - return NULL; - } - - // Loop through all work completions - for(i=0; iwr; - } else { - recv_tail->next = &(_pkt_buf[wr_id].wr); - recv_tail = recv_tail->next; - } - } // for each work completion - } while(num_wce); - - // Ensure list is NULL terminated (if we have a list) - if(recv_tail) { - recv_tail->next = NULL; - } - - return recv_head; -} - diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index ea598a9e3..cf0699962 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -47,7 +47,7 @@ #endif #ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 32768 +#define BF_VERBS_NPKTBUF 4096 #endif #ifndef BF_VERBS_WCBATCH @@ -58,22 +58,21 @@ struct bf_ibv_recv_pkt { struct ibv_recv_wr wr; - uint32_t length; + uint32_t length; }; // Structure for defining various types of flow rules struct bf_ibv_flow { - struct ibv_flow_attr attr; - struct ibv_flow_spec_eth spec_eth; - struct ibv_flow_spec_ipv4 spec_ipv4; - struct ibv_flow_spec_tcp_udp spec_tcp_udp; + struct ibv_flow_attr attr; + struct ibv_flow_spec_tcp_udp spec_tcp_udp; + struct ibv_flow_spec_ipv4 spec_ipv4; + struct ibv_flow_spec_eth spec_eth; } __attribute__((packed)); class Verbs { int _fd; size_t _pkt_size_max; - struct ibv_device** _dev_list = NULL; struct ibv_context* _ctx = NULL; struct ibv_device_attr _dev_attr; uint8_t _port_num; @@ -92,10 +91,6 @@ class Verbs { size_t _mr_size = 0; struct ibv_mr* _mr = NULL; - int32_t _nqp = BF_VERBS_NQP; - int32_t _npkt = BF_VERBS_NPKTBUF; - int32_t _nflows = 1; - void get_interface_name(char* name) { struct sockaddr_in sin; char ip[INET_ADDRSTRLEN]; @@ -195,7 +190,8 @@ class Verbs { destroy_context(); std::stringstream ss; - ss << "Failed to " << what; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); throw Verbs::Error(ss.str()); } } @@ -225,18 +221,18 @@ class Verbs { destroy_buffers(); destroy_context(); } - inline int recv_packet(uint8_t* buf, size_t bufsize, uint8_t** pkt_ptr, int flags=0) { + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { // If we don't have a work-request queue on the go, // get some new packets. if( _pkt ) { _pkt = (struct bf_ibv_recv_pkt *)_pkt->wr.next; if( !_pkt ) { - release(_chain); + this->release(_chain); _chain = NULL; } } while( !_chain ) { - _chain = receive(1); + _chain = this->receive(500); _pkt = _chain; } // IBV returns Eth/UDP/IP headers. Strip them off here. @@ -245,3 +241,448 @@ class Verbs { } }; +void Verbs::create_context() { + int d, p, g; + int ndev, found; + struct ibv_device** ibv_dev_list = NULL; + struct ibv_context* ibv_ctx = NULL; + struct ibv_device_attr ibv_dev_attr; + struct ibv_port_attr ibv_port_attr; + union ibv_gid ibv_gid; + + // Get the interface MAC address and GID + found = 0; + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + uint64_t gid = this->get_interface_gid(); + + std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) + << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; + + // Find the right device + /* Query all devices */ + ibv_dev_list = ibv_get_device_list(&ndev); + check_null(ibv_dev_list, + "ibv_get_device_list"); + + /* Interogate */ + for(d=0; dfd, F_GETFL); + check_error(::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK), + "set completion channel to non-blocking"); + + // Setup the completion queues + _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); + check_null(_cq, + "allocate completion queues"); + ::memset(_cq, 0, BF_VERBS_NQP * sizeof(struct ibv_cq*)); + for(i=0; ilkey; + } + } + + // Link the work requests to receive queue + for(i=0; iget_port()); + flow.spec_tcp_udp.mask.dst_port = 0xffff; + + // Filter on nothing in the IPv4 header + + // Filter on the destination MAC address + this->get_mac_address(&(flow.spec_eth.val.dst_mac[0])); + ::memset(&(flow.spec_eth.mask.dst_mac[0]), 0xff, 6); + + // Create the flows + _flows = (struct ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_flow*)); + check_null(_flows, + "allocate flows"); + ::memset(_flows, 0, BF_VERBS_NQP * sizeof(struct ibv_flow*)); + for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; + return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); +} + +struct bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { + int i; + int num_wce; + uint64_t wr_id; + struct pollfd pfd; + struct ibv_qp_attr qp_attr; + struct ibv_cq *ev_cq; + intptr_t ev_cq_ctx; + struct ibv_wc wc[BF_VERBS_WCBATCH]; + struct bf_ibv_recv_pkt * recv_head = NULL; + struct ibv_recv_wr * recv_tail = NULL; + + // Ensure the queue pairs are in a state suitable for receiving + for(i=0; istate) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _port_num; + if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + break; + case IBV_QPS_RTR: + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + // Setup for poll + pfd.fd = _cc->fd; + pfd.events = POLLIN; + pfd.revents = 0; + + // poll completion channel's fd with given timeout + if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { + // Timeout or error + return NULL; + } + + // Get the completion event + if( ibv_get_cq_event(_cc, &ev_cq, (void **)&ev_cq_ctx) ) { + return NULL; + } + + // Ack the event + ibv_ack_cq_events(ev_cq, 1); + + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + if( ibv_req_notify_cq(ev_cq, 0) ) { + return NULL; + } + + // Empty the CQ: poll all of the completions from the CQ (if any exist) + do { + num_wce = ibv_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc); + if( num_wce < 0 ) { + return NULL; + } + + // Loop through all work completions + for(i=0; iwr; + } else { + recv_tail->next = &(_pkt_buf[wr_id].wr); + recv_tail = recv_tail->next; + } + } // for each work completion + } while(num_wce); + + // Ensure list is NULL terminated (if we have a list) + if(recv_tail) { + recv_tail->next = NULL; + } + + return recv_head; +} From c54fa9005441177a5d0fb8acf89b5df3e1f9aa35 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Jul 2020 12:34:07 -0600 Subject: [PATCH 097/424] Forgot to hit save on that one. --- src/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4544dab7a..7e3f5776b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,11 +20,6 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o -ifdef VERBS - # These files require IB verbs to combine - LIBBIFROST_OBJS += \ - ib_verbs.o -endif ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ From 91be4d203d38a11d2305e1cc02f99d4dd135e099 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Jul 2020 12:40:25 -0600 Subject: [PATCH 098/424] Debugging cleanup. --- src/ib_verbs.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index cf0699962..daf1bed0d 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -338,7 +338,6 @@ void Verbs::create_buffers() { _pkt_buf = (struct bf_ibv_recv_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_recv_pkt)); check_null(_pkt_buf, "allocate receive packet buffer"); - std::cout << "_pkt_buf: " << _pkt_buf << std::endl; ::memset(_pkt_buf, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(bf_ibv_recv_pkt)); _sge = (struct ibv_sge*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct ibv_sge)); check_null(_sge, @@ -413,9 +412,9 @@ void Verbs::create_queues() { ::memset(&qp_init, 0, sizeof(struct ibv_qp_init_attr)); qp_init.qp_context = NULL; qp_init.srq = NULL; - qp_init.cap.max_send_wr = 1; + qp_init.cap.max_send_wr = 0; qp_init.cap.max_recv_wr = BF_VERBS_NPKTBUF; - qp_init.cap.max_send_sge = 1; + qp_init.cap.max_send_sge = 0; qp_init.cap.max_recv_sge = 1; qp_init.cap.max_inline_data = 0; qp_init.qp_type = IBV_QPT_RAW_PACKET; @@ -553,12 +552,9 @@ void Verbs::create_flows() { "allocate flows"); ::memset(_flows, 0, BF_VERBS_NQP * sizeof(struct ibv_flow*)); for(i=0; i Date: Tue, 21 Jul 2020 15:40:27 -0600 Subject: [PATCH 099/424] Follow redirects to get to bf_test_files.tar.gz. --- test/download_test_data.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/download_test_data.sh b/test/download_test_data.sh index 93d419018..031c748c7 100755 --- a/test/download_test_data.sh +++ b/test/download_test_data.sh @@ -1,5 +1,5 @@ #!/bin/bash -curl -O http://mcranmer.com/data/bf_test_files.tar.gz +curl -L -O http://mcranmer.com/data/bf_test_files.tar.gz tar xzf bf_test_files.tar.gz mv for_test_suite data rm bf_test_files.tar.gz From 775a2d0f2f946f94d92964ae0423a5e03d3f258a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 22 Jul 2020 09:28:51 -0600 Subject: [PATCH 100/424] Now we are getting somewhere. --- src/Makefile | 5 + src/ib_verbs.cpp | 565 +++++++++++++++++++++++++++++++++++++++++ src/ib_verbs.hpp | 547 ++++----------------------------------- src/packet_capture.hpp | 2 +- user.mk | 2 +- 5 files changed, 626 insertions(+), 495 deletions(-) create mode 100644 src/ib_verbs.cpp diff --git a/src/Makefile b/src/Makefile index 7e3f5776b..23cce5406 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,6 +20,11 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o +ifdef VERBS: + # These files require IB verbs to compile + LIBBIFROST_OBJS += \ + ib_verbs.o +endif ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp new file mode 100644 index 000000000..5600ae098 --- /dev/null +++ b/src/ib_verbs.cpp @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2020, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "ib_verbs.hpp" + +void Verbs::create_context() { + int d, p, g; + int ndev, found; + ibv_device** ibv_dev_list = NULL; + ibv_context* ibv_ctx = NULL; + ibv_device_attr ibv_dev_attr; + ibv_port_attr ibv_port_attr; + union ibv_gid ibv_gid; + + // Get the interface MAC address and GID + found = 0; + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + uint64_t gid = this->get_interface_gid(); + + std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) + << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; + + // Find the right device + /* Query all devices */ + ibv_dev_list = ibv_get_device_list(&ndev); + check_null(ibv_dev_list, + "ibv_get_device_list"); + + /* Interogate */ + for(d=0; dfd, F_GETFL); + check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), + "set completion channel to non-blocking"); + + // Setup the completion queues + _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); + check_null(_verbs.cq, + "allocate completion queues"); + ::memset(_verbs.cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); + ibv_exp_cq_init_attr cq_attr; + ::memset(&cq_attr, 0, sizeof(cq_attr)); + cq_attr.comp_mask = IBV_EXP_CQ_INIT_ATTR_FLAGS; + cq_attr.flags = IBV_EXP_CQ_TIMESTAMP; + for(i=0; ilkey; + } + } + + // Link the work requests to receive queue + for(i=0; iget_port()); + flow.udp.mask.dst_port = 0xffff; + + // Filter on IP address in the IPv4 header + uint32_t ip; + char ip_str[INET_ADDRSTRLEN]; + this->get_ip_address(&(ip_str[0])); + inet_pton(AF_INET, &(ip_str[0]), &ip); + std::cout << "IP is: " << ip << " (" << ip_str << ")" << std::endl; + ::memcpy(&(flow.ipv4.val.dst_ip), &ip, 4); + ::memset(&(flow.ipv4.mask.dst_ip), 0xff, 4); + + // Filter on the destination MAC address (actual or multicast) + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { + ETHER_MAP_IP_MULTICAST(&ip, mac); + std::cout << "Multicast MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + } + ::memcpy(&flow.eth.val.dst_mac, &mac, 6); + ::memset(&flow.eth.mask.dst_mac, 0xff, 6); + + /* + printf("size: %i\n", flow.attr.size); + printf(" attr: %i vs %lu\n", flow.attr.size, sizeof(ibv_flow_attr)); + printf(" eth: %i vs %lu\n", flow.eth.size, sizeof(ibv_flow_spec_eth)); + printf(" ipv4: %i vs %lu\n", flow.ipv4.size, sizeof(ibv_flow_spec_ipv4)); + printf(" udp: %i vs %lu\n", flow.udp.size, sizeof(ibv_flow_spec_tcp_udp)); + printf("specs: %i\n", flow.attr.num_of_specs); + + printf("type: %i (%i)\n", flow.udp.type, IBV_FLOW_SPEC_UDP); + printf("dst_port: %u\n", flow.udp.val.dst_port); + printf("dst_port: %u\n", flow.udp.mask.dst_port); + printf("src_port: %u\n", flow.udp.val.src_port); + printf("src_port: %u\n", flow.udp.mask.src_port); + + printf("dst_ip: %u\n", flow.ipv4.val.dst_ip); + printf("dst_ip: %u\n", flow.ipv4.mask.dst_ip); + printf("src_ip: %u\n", flow.ipv4.val.src_ip); + printf("src_ip: %u\n", flow.ipv4.mask.src_ip); + + ::memcpy(&(mac[0]), &(flow.eth.val.dst_mac[0]), 6); + printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.mask.dst_mac[0]), 6); + printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.val.src_mac[0]), 6); + printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.mask.src_mac[0]), 6); + printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("ether_type: %u\n", flow.eth.val.ether_type); + printf("ether_type: %u\n", flow.eth.mask.ether_type); + printf("vlan_tag: %u\n", flow.eth.val.vlan_tag); + printf("vlan_tag: %u\n", flow.eth.mask.vlan_tag); + */ + + // Create the flows + _verbs.flows = (ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(ibv_flow*)); + check_null(_verbs.flows, + "allocate flows"); + ::memset(_verbs.flows, 0, BF_VERBS_NQP * sizeof(ibv_flow*)); + for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; + return ibv_post_recv(_verbs.qp[i], &recv_pkt->wr, &recv_wr_bad); +} + +bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { + int i; + int num_wce; + uint64_t wr_id; + pollfd pfd; + ibv_qp_attr qp_attr; + ibv_cq *ev_cq; + intptr_t ev_cq_ctx; + ibv_exp_wc wc[BF_VERBS_WCBATCH]; + bf_ibv_recv_pkt * recv_head = NULL; + ibv_recv_wr * recv_tail = NULL; + + // Ensure the queue pairs are in a state suitable for receiving + for(i=0; istate << std::endl; + switch(_verbs.qp[i]->state) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + break; + case IBV_QPS_RTR: + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + // Setup for poll + pfd.fd = _verbs.cc->fd; + pfd.events = POLLIN; + pfd.revents = 0; + + // poll completion channel's fd with given timeout + if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { + // Timeout or error + return NULL; + } + + // Get the completion event + if( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) ) { + return NULL; + } + + // Ack the event + ibv_ack_cq_events(ev_cq, 1); + + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + if( ibv_req_notify_cq(ev_cq, 0) ) { + return NULL; + } + + // Empty the CQ: poll all of the completions from the CQ (if any exist) + do { + num_wce = ibv_exp_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc, sizeof(struct ibv_exp_wc)); + if( num_wce < 0 ) { + return NULL; + } + + // Loop through all work completions + for(i=0; iwr; + } else { + recv_tail->next = &(_verbs.pkt_buf[wr_id].wr); + recv_tail = recv_tail->next; + } + } // for each work completion + } while(num_wce); + + // Ensure list is NULL terminated (if we have a list) + if(recv_tail) { + recv_tail->next = NULL; + } + + return recv_head; +} + +int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { + // If we don't have a work-request queue on the go, + // get some new packets. + + /* + std::cout << "Here with qp: " << &(_verbs.qp) << std::endl; + std::cout << " _pkt: " << (_verbs.pkt != NULL) << std::endl; + */ + + if( _verbs.pkt != NULL) { + //std::cout << "inside" << std::endl; + _verbs.pkt = (bf_ibv_recv_pkt *) _verbs.pkt->wr.next; + //std::cout << " next: " << (_verbs.pkt != NULL) << std::endl; + if( _verbs.pkt == NULL ) { + this->release(_verbs.pkt_batch); + _verbs.pkt_batch = NULL; + } + } + while( _verbs.pkt_batch == NULL ) { + _verbs.pkt_batch = this->receive(1); + _verbs.pkt = _verbs.pkt_batch; + } + // IBV returns Eth/UDP/IP headers. Strip them off here. + *pkt_ptr = (uint8_t *)_verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; + //std::cout << "size: " << _verbs.pkt->length << " & " << _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET << std::endl; + return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; +} diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index daf1bed0d..a0a82505d 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -39,15 +39,18 @@ #include #include #include +#include +extern "C" { #include +} #ifndef BF_VERBS_NQP #define BF_VERBS_NQP 1 #endif #ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 4096 +#define BF_VERBS_NPKTBUF 8192 #endif #ifndef BF_VERBS_WCBATCH @@ -56,46 +59,53 @@ #define BF_VERBS_PAYLOAD_OFFSET 42 -struct bf_ibv_recv_pkt { - struct ibv_recv_wr wr; - uint32_t length; +extern "C" { + +struct bf_ibv_recv_pkt{ + ibv_recv_wr wr; + uint32_t length; + uint64_t timestamp; }; -// Structure for defining various types of flow rules struct bf_ibv_flow { - struct ibv_flow_attr attr; - struct ibv_flow_spec_tcp_udp spec_tcp_udp; - struct ibv_flow_spec_ipv4 spec_ipv4; - struct ibv_flow_spec_eth spec_eth; + ibv_flow_attr attr; + ibv_flow_spec_eth eth; + ibv_flow_spec_ipv4 ipv4; + ibv_flow_spec_tcp_udp udp; } __attribute__((packed)); -class Verbs { - int _fd; - size_t _pkt_size_max; +struct bf_ibv { + ibv_context* ctx; + //ibv_device_attr dev_attr; + uint8_t port_num; + ibv_pd* pd; + ibv_comp_channel* cc; + ibv_cq** cq; + ibv_qp** qp; + ibv_sge* sge; + ibv_flow** flows; - struct ibv_context* _ctx = NULL; - struct ibv_device_attr _dev_attr; - uint8_t _port_num; - struct ibv_pd* _pd = NULL; - struct ibv_comp_channel* _cc = NULL; - struct ibv_cq** _cq = NULL; - struct ibv_qp** _qp = NULL; - struct ibv_sge* _sge = NULL; - struct ibv_flow** _flows = NULL; + uint8_t* mr_buf; + size_t mr_size; + ibv_mr* mr; - struct bf_ibv_recv_pkt* _pkt_buf = NULL; - struct bf_ibv_recv_pkt* _pkt = NULL; - struct bf_ibv_recv_pkt* _chain = NULL; - - uint8_t* _mr_buf = NULL; - size_t _mr_size = 0; - struct ibv_mr* _mr = NULL; + bf_ibv_recv_pkt* pkt_buf; + bf_ibv_recv_pkt* pkt; + bf_ibv_recv_pkt* pkt_batch; +} __attribute((aligned(8))); + +} // extern "C" + +class Verbs { + int _fd; + size_t _pkt_size_max; + bf_ibv _verbs; void get_interface_name(char* name) { - struct sockaddr_in sin; + sockaddr_in sin; char ip[INET_ADDRSTRLEN]; socklen_t len = sizeof(sin); - check_error(::getsockname(_fd, (struct sockaddr *)&sin, &len), + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), "query socket name"); inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); @@ -130,17 +140,24 @@ class Verbs { } } void get_mac_address(uint8_t* mac) { - struct ifreq ethreq; + ifreq ethreq; this->get_interface_name(&(ethreq.ifr_name[0])); check_error(::ioctl(_fd, SIOCGIFHWADDR, ðreq), "query interface hardware address"); ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); } + void get_ip_address(char* ip) { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + } uint16_t get_port() { - struct sockaddr_in sin; + sockaddr_in sin; socklen_t len = sizeof(sin); - check_error(::getsockname(_fd, (struct sockaddr *)&sin, &len), + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), "query socket name"); return ntohs(sin.sin_port); } @@ -168,7 +185,7 @@ class Verbs { void create_flows(); void destroy_flows(); int release(bf_ibv_recv_pkt*); - struct bf_ibv_recv_pkt* receive(int timeout_ms=1); + bf_ibv_recv_pkt* receive(int timeout_ms=1); inline void check_error(int retval, std::string what) { if( retval < 0 ) { destroy_flows(); @@ -209,6 +226,8 @@ class Verbs { Verbs(int fd, size_t pkt_size_max) : _fd(fd), _pkt_size_max(pkt_size_max) { + ::memset(&_verbs, 0, sizeof(_verbs)); + create_context(); create_buffers(); create_queues(); @@ -221,464 +240,6 @@ class Verbs { destroy_buffers(); destroy_context(); } - inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { - // If we don't have a work-request queue on the go, - // get some new packets. - if( _pkt ) { - _pkt = (struct bf_ibv_recv_pkt *)_pkt->wr.next; - if( !_pkt ) { - this->release(_chain); - _chain = NULL; - } - } - while( !_chain ) { - _chain = this->receive(500); - _pkt = _chain; - } - // IBV returns Eth/UDP/IP headers. Strip them off here. - *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; - return _pkt->length - BF_VERBS_PAYLOAD_OFFSET; - } + int recv_packet(uint8_t** pkt_ptr, int flags=0); }; -void Verbs::create_context() { - int d, p, g; - int ndev, found; - struct ibv_device** ibv_dev_list = NULL; - struct ibv_context* ibv_ctx = NULL; - struct ibv_device_attr ibv_dev_attr; - struct ibv_port_attr ibv_port_attr; - union ibv_gid ibv_gid; - - // Get the interface MAC address and GID - found = 0; - uint8_t mac[6] = {0}; - this->get_mac_address(&(mac[0])); - uint64_t gid = this->get_interface_gid(); - - std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; - std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) - << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; - - // Find the right device - /* Query all devices */ - ibv_dev_list = ibv_get_device_list(&ndev); - check_null(ibv_dev_list, - "ibv_get_device_list"); - - /* Interogate */ - for(d=0; dfd, F_GETFL); - check_error(::fcntl(_cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); - - // Setup the completion queues - _cq = (struct ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_cq*)); - check_null(_cq, - "allocate completion queues"); - ::memset(_cq, 0, BF_VERBS_NQP * sizeof(struct ibv_cq*)); - for(i=0; ilkey; - } - } - - // Link the work requests to receive queue - for(i=0; iget_port()); - flow.spec_tcp_udp.mask.dst_port = 0xffff; - - // Filter on nothing in the IPv4 header - - // Filter on the destination MAC address - this->get_mac_address(&(flow.spec_eth.val.dst_mac[0])); - ::memset(&(flow.spec_eth.mask.dst_mac[0]), 0xff, 6); - - // Create the flows - _flows = (struct ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(struct ibv_flow*)); - check_null(_flows, - "allocate flows"); - ::memset(_flows, 0, BF_VERBS_NQP * sizeof(struct ibv_flow*)); - for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; - return ibv_post_recv(_qp[i], &recv_pkt->wr, &recv_wr_bad); -} - -struct bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { - int i; - int num_wce; - uint64_t wr_id; - struct pollfd pfd; - struct ibv_qp_attr qp_attr; - struct ibv_cq *ev_cq; - intptr_t ev_cq_ctx; - struct ibv_wc wc[BF_VERBS_WCBATCH]; - struct bf_ibv_recv_pkt * recv_head = NULL; - struct ibv_recv_wr * recv_tail = NULL; - - // Ensure the queue pairs are in a state suitable for receiving - for(i=0; istate) { - case IBV_QPS_RESET: // Unexpected, but maybe user reset it - qp_attr.qp_state = IBV_QPS_INIT; - qp_attr.port_num = _port_num; - if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { - return NULL; - } - case IBV_QPS_INIT: - qp_attr.qp_state = IBV_QPS_RTR; - if( ibv_modify_qp(_qp[i], &qp_attr, IBV_QP_STATE) ) { - return NULL; - } - break; - case IBV_QPS_RTR: - case IBV_QPS_RTS: - break; - default: - return NULL; - } - } - - // Setup for poll - pfd.fd = _cc->fd; - pfd.events = POLLIN; - pfd.revents = 0; - - // poll completion channel's fd with given timeout - if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { - // Timeout or error - return NULL; - } - - // Get the completion event - if( ibv_get_cq_event(_cc, &ev_cq, (void **)&ev_cq_ctx) ) { - return NULL; - } - - // Ack the event - ibv_ack_cq_events(ev_cq, 1); - - // Request notification upon the next completion event - // Do NOT restrict to solicited-only completions - if( ibv_req_notify_cq(ev_cq, 0) ) { - return NULL; - } - - // Empty the CQ: poll all of the completions from the CQ (if any exist) - do { - num_wce = ibv_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc); - if( num_wce < 0 ) { - return NULL; - } - - // Loop through all work completions - for(i=0; iwr; - } else { - recv_tail->next = &(_pkt_buf[wr_id].wr); - recv_tail = recv_tail->next; - } - } // for each work completion - } while(num_wce); - - // Ensure list is NULL terminated (if we have a list) - if(recv_tail) { - recv_tail->next = NULL; - } - - return recv_head; -} diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 9c6e631b3..b167f583c 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -293,7 +293,7 @@ class UDPVerbsReceiver : public PacketCaptureMethod { : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max) {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = 0; - return _ibv.recv_packet(&_buf[0], _buf.size(), pkt_ptr, flags); + return _ibv.recv_packet(pkt_ptr, flags); } inline const char* get_name() { return "udp_verbs_capture"; } }; diff --git a/user.mk b/user.mk index 7dde3d0d6..cda86c16f 100644 --- a/user.mk +++ b/user.mk @@ -28,4 +28,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #NUMA = 1 # Enable use of numa library for setting affinity of ring memory #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture -#VERBS = 1 # Enable use of IB verbs in udp_capture +#VERBS = 1 # Enable use of IB verbs with udp_verbs_capture From aacc2313e29decaea028670f86c12d27155c4be2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 22 Jul 2020 09:34:17 -0600 Subject: [PATCH 101/424] Cleaned up some of the debugging messages. --- src/ib_verbs.cpp | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 5600ae098..7d8e5cee9 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -44,10 +44,12 @@ void Verbs::create_context() { this->get_mac_address(&(mac[0])); uint64_t gid = this->get_interface_gid(); + /* std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; + */ // Find the right device /* Query all devices */ @@ -107,8 +109,6 @@ void Verbs::create_context() { destroy_context(); throw Verbs::Error("specified device not found"); } - - std::cout << "Here? " << 9000 << " & " << _pkt_size_max << std::endl; } void Verbs::destroy_context() { @@ -351,8 +351,10 @@ void Verbs::create_flows() { this->get_mac_address(&(mac[0])); if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { ETHER_MAP_IP_MULTICAST(&ip, mac); + /* std::cout << "Multicast MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + */ } ::memcpy(&flow.eth.val.dst_mac, &mac, 6); ::memset(&flow.eth.mask.dst_mac, 0xff, 6); @@ -446,7 +448,6 @@ bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { // Ensure the queue pairs are in a state suitable for receiving for(i=0; istate << std::endl; switch(_verbs.qp[i]->state) { case IBV_QPS_RESET: // Unexpected, but maybe user reset it qp_attr.qp_state = IBV_QPS_INIT; @@ -505,12 +506,6 @@ bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { wr_id = wc[i].wr_id; // Set length to 0 for unsuccessful work requests if( wc[i].status != IBV_WC_SUCCESS ) { - /* - fprintf(stderr, - "wr %lu (%#016lx) got completion status 0x%x (%s) vendor error 0x%x (QP %d)\n", - wr_id, wr_id, wc[i].status, ibv_wc_status_str(wc[i].status), - wc[i].vendor_err, (int)ev_cq_ctx); - */ _verbs.pkt_buf[wr_id].length = 0; } else { // Copy byte_len from completion to length of pkt srtuct @@ -540,15 +535,8 @@ int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { // If we don't have a work-request queue on the go, // get some new packets. - /* - std::cout << "Here with qp: " << &(_verbs.qp) << std::endl; - std::cout << " _pkt: " << (_verbs.pkt != NULL) << std::endl; - */ - if( _verbs.pkt != NULL) { - //std::cout << "inside" << std::endl; _verbs.pkt = (bf_ibv_recv_pkt *) _verbs.pkt->wr.next; - //std::cout << " next: " << (_verbs.pkt != NULL) << std::endl; if( _verbs.pkt == NULL ) { this->release(_verbs.pkt_batch); _verbs.pkt_batch = NULL; @@ -560,6 +548,5 @@ int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { } // IBV returns Eth/UDP/IP headers. Strip them off here. *pkt_ptr = (uint8_t *)_verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; - //std::cout << "size: " << _verbs.pkt->length << " & " << _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET << std::endl; return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; } From e3fbcb9670b2f3ce63a286df3d0bad16f136c09e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 22 Jul 2020 14:48:56 -0600 Subject: [PATCH 102/424] This works but is slightly hacky. --- src/ib_verbs.cpp | 11 +++++------ src/ib_verbs.hpp | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 7d8e5cee9..7bb362bbd 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -120,7 +120,7 @@ void Verbs::destroy_context() { } } -void Verbs::create_buffers() { +void Verbs::create_buffers(size_t pkt_size_max) { // Setup the protected domain _verbs.pd = ibv_alloc_pd(_verbs.ctx); @@ -133,9 +133,8 @@ void Verbs::create_buffers() { check_null(_verbs.sge, "allocate scatter/gather entries"); ::memset(_verbs.sge, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(ibv_sge)); - _verbs.mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * 9000; + _verbs.mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * pkt_size_max; _verbs.mr_buf = (uint8_t *) ::malloc(_verbs.mr_size); - std::cout << "mr_size: " << _verbs.mr_size << " & " << 9000 << std::endl; check_null(_verbs.mr_buf, "allocate memory region buffer"); ::memset(_verbs.mr_buf, 0, _verbs.mr_size); @@ -270,7 +269,7 @@ void Verbs::destroy_queues() { } } -void Verbs::link_work_requests() { +void Verbs::link_work_requests(size_t pkt_size_max) { // Make sure we are ready to go check_null(_verbs.pkt_buf, "find existing packet buffer"); @@ -284,8 +283,8 @@ void Verbs::link_work_requests() { for(i=0; i Date: Thu, 23 Jul 2020 13:30:23 +0000 Subject: [PATCH 103/424] Split up beamforming GEM and dynamic spectra / transpose / integrate Allow an option to beamform and integrate in one hit by passing ntime_blocks>0 when initializing the library. Otherwise don't transpose or integrate the data. This change allows multiple downstream processes to use raw beamformer data for their own, different purposes -- (eg) one generating integrated dynamic spectra, and one generating VLBI voltage beams --- src/beamform.cpp | 12 ++++++++++ src/bifrost/beamform.h | 5 +++++ src/cublas_beamform.cu | 50 ++++++++++++++++++++++++++++++++++++----- src/cublas_beamform.cuh | 1 + 4 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/beamform.cpp b/src/beamform.cpp index 190a6232e..eb6c563e4 100644 --- a/src/beamform.cpp +++ b/src/beamform.cpp @@ -59,4 +59,16 @@ BFstatus bfBeamformRun(BFarray *in, BFarray *out, BFarray *weights) { return BF_STATUS_SUCCESS; } +BFstatus bfBeamformIntegrate(BFarray *in, BFarray *out) { + if (in->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + if (out->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + cublas_beamform_integrate((float *)in->data, (float *)out->data); + return BF_STATUS_SUCCESS; +} } // C diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 8fa43a66f..1da1937a9 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -15,3 +15,8 @@ BFstatus bfBeamformRun( BFarray *out, BFarray *weights ); + +BFstatus bfBeamformIntegrate( + BFarray *in, + BFarray *out +); diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu index a98ae32ff..94f095850 100644 --- a/src/cublas_beamform.cu +++ b/src/cublas_beamform.cu @@ -143,7 +143,9 @@ static struct beamform_context context; void cublas_beamform_destroy(){ cudaFree(context.in32_d); - cudaFree(context.out_d); + if (context.ntimeblocks > 0) { + cudaFree(context.out_d); + } } void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks) { @@ -164,10 +166,14 @@ void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int n // Internally allocate intermediate buffers gpuErrchk( cudaMalloc(&context.in32_d, ninputs * nchans * ntimes * 2 * sizeof(float)) ); - gpuErrchk( cudaMalloc(&context.out_d, ntimes * nchans * nbeams * 2 * sizeof(float)) ); + // If the context is initialized with ntimeblocks=0, then we do no summing so don't + // need the intermediate buffer + if (ntimeblocks > 0) { + gpuErrchk( cudaMalloc(&context.out_d, ntimes * nchans * nbeams * 2 * sizeof(float)) ); + } } -void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d) { +void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { // Transpose input data and promote to float. // CUBLAS doesn't support float coeffs with int8 data dim3 transBlockGrid(context.ntimes, context.nchans); @@ -181,6 +187,17 @@ void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d) { ); cudaStreamSynchronize(context.stream); + // If we are integrating beam powers, put the + // GEM output in the context-defined intermediate + // buffer. If not, then write beamformer output + // to the address given by the user. + float *gem_out_d; + if (context.ntimeblocks > 0) { + gem_out_d = context.out_d; + } else { + gem_out_d = out_d; + } + // Beamform using GEMM float alpha = 1.0; float beta = 0.0; @@ -190,6 +207,7 @@ void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d) { // beta = 0.0 // A matrix: beamforming coeffs (NBEAMS * NANTS) // B matrix: data matrix (NANTS * NTIMES) + gpuBLASchk(cublasGemmStridedBatchedEx( context.handle, CUBLAS_OP_N, // transpose A? @@ -210,7 +228,7 @@ void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d) { context.ninputs*context.ntimes,// strideB : stride size &beta, // beta // Results - context.out_d, // C + gem_out_d, // C CUDA_C_32F, // Ctype context.nbeams, // Ldc context.nbeams*context.ntimes,// Stride C @@ -220,14 +238,34 @@ void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d) { )); cudaStreamSynchronize(context.stream); + // Optionally: + if (context.ntimeblocks > 0) { + // Create XX, YY, XY beam powers. + // Sum over `ntimes_sum` samples + int ntimes_sum = context.ntimes / context.ntimeblocks; + dim3 sumBlockGrid(context.nchans, context.nbeams/2); + dim3 sumThreadGrid(context.ntimes / ntimes_sum); + trans_output_and_sum<<>>( + gem_out_d, + out_d, + context.nchans, + context.nbeams/2, + context.ntimes, + ntimes_sum + ); + cudaStreamSynchronize(context.stream); + } +} + +void cublas_beamform_integrate(float *in_d, float *out_d) { // Create XX, YY, XY beam powers. // Sum over `ntimes_sum` samples int ntimes_sum = context.ntimes / context.ntimeblocks; dim3 sumBlockGrid(context.nchans, context.nbeams/2); dim3 sumThreadGrid(context.ntimes / ntimes_sum); trans_output_and_sum<<>>( - context.out_d, - sum_out_d, + in_d, + out_d, context.nchans, context.nbeams/2, context.ntimes, diff --git a/src/cublas_beamform.cuh b/src/cublas_beamform.cuh index eca2d63f2..6a0d2b22a 100644 --- a/src/cublas_beamform.cuh +++ b/src/cublas_beamform.cuh @@ -30,6 +30,7 @@ __global__ void complex2pow(float *in, float *out, int N); void cublas_beamform_destroy(); void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d); +void cublas_beamform_integrate(float *in_d, float *sum_out_d); void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks); #endif From 9f077f2238adff7b56c7d8c0e5e3f72dd0ab607b Mon Sep 17 00:00:00 2001 From: JackH Date: Fri, 24 Jul 2020 18:51:22 +0000 Subject: [PATCH 104/424] Add missing ifdefs for IBV code --- src/packet_capture.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c61454098..69258e231 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1184,8 +1184,10 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new DiskPacketReader(fd, max_payload_size); } else if( backend == BF_IO_UDP ) { method = new UDPPacketReceiver(fd, max_payload_size); +#if BF_HPIBV_ENABLED } else if( backend == BF_IO_IBV_UDP ) { method = new IBVUDPPacketReceiver(fd, max_payload_size); +#endif } else if( backend == BF_IO_SNIFFER ) { method = new UDPPacketSniffer(fd, max_payload_size); } else { From 9ab1d1f9d54f5cada42dea68126e597b17955986 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 27 Jul 2020 09:21:39 -0600 Subject: [PATCH 105/424] Fixed like_bmon.py for udp_verbs_capture. --- tools/like_bmon.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/like_bmon.py b/tools/like_bmon.py index dfc087ad1..589541e68 100755 --- a/tools/like_bmon.py +++ b/tools/like_bmon.py @@ -158,7 +158,9 @@ def _getStatistics(blockList, prevList): # Loop over the blocks to find udp_capture and udp_transmit blocks output = {'updated': datetime.now()} for block in blockList: - if block.find('udp_capture') != -1 or block.find('udp_sniffer') != -1: + if block.find('udp_capture') != -1 \ + or block.find('udp_sniffer') != -1 \ + or block.find('udp_verbs_capture') != -1: ## udp_capture is RX good = True type = 'rx' From 938d3d91476f1cd0782165f21ee235a1efdd131e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 28 Jul 2020 12:02:49 -0600 Subject: [PATCH 106/424] Added back in an argument to control the max_payload size in BFpacketcapture_create(). --- src/packet_capture.cpp | 4 ++++ src/packet_capture.hpp | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index a03b107b4..f942d3002 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -285,6 +285,7 @@ BFstatus bfDiskReaderCreate(BFpacketcapture* obj, ring, nsrc, src0, + 9000, buffer_ntime, slot_ntime, sequence_callback, @@ -309,6 +310,7 @@ BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, ring, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, sequence_callback, @@ -333,6 +335,7 @@ BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, ring, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, sequence_callback, @@ -357,6 +360,7 @@ BFstatus bfUdpVerbsCaptureCreate(BFpacketcapture* obj, ring, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, sequence_callback, diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index b167f583c..165b717b5 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1045,6 +1045,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, BFring ring, BFsize nsrc, BFsize src0, + BFsize max_payload_size, BFsize buffer_ntime, BFsize slot_ntime, BFpacketcapture_callback sequence_callback, @@ -1052,7 +1053,6 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, BFiomethod backend) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - size_t max_payload_size = JUMBO_FRAME_SIZE; if( std::string(format).substr(0, 5) == std::string("chips") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time From d7e60cf31ff8936c88dbd036f2de9e49a224696e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 28 Jul 2020 12:11:21 -0600 Subject: [PATCH 107/424] Missing pragma. --- src/hw_locality.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hw_locality.hpp b/src/hw_locality.hpp index 1494bb1cf..e0245f666 100644 --- a/src/hw_locality.hpp +++ b/src/hw_locality.hpp @@ -26,6 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#pragma once + #include #if BF_HWLOC_ENABLED From 42f6272cb122f7f2e82835bbf8e48f16d3350334 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 28 Jul 2020 12:50:45 -0600 Subject: [PATCH 108/424] Do we need strict locality? --- src/ib_verbs.hpp | 8 +++++--- src/packet_capture.hpp | 6 +++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index e47305869..288f3bc80 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -28,6 +28,8 @@ #pragma once +#include "hw_locality.hpp" + #include #include #include @@ -96,7 +98,7 @@ struct bf_ibv { } // extern "C" -class Verbs { +class Verbs : public BoundThread { int _fd; size_t _pkt_size_max; bf_ibv _verbs; @@ -224,8 +226,8 @@ class Verbs { : super_t(what_arg) {} }; - Verbs(int fd, size_t pkt_size_max) - : _fd(fd), _pkt_size_max(pkt_size_max) { + Verbs(int fd, size_t pkt_size_max, int core) + : BoundThread(core), _fd(fd), _pkt_size_max(pkt_size_max) { ::memset(&_verbs, 0, sizeof(_verbs)); create_context(); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 165b717b5..d557c400b 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -289,8 +289,8 @@ class UDPPacketSniffer : public PacketCaptureMethod { class UDPVerbsReceiver : public PacketCaptureMethod { Verbs _ibv; public: - UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max) {} + UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE, int core=-1) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max, core) {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = 0; return _ibv.recv_packet(pkt_ptr, flags); @@ -1104,7 +1104,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new UDPPacketSniffer(fd, max_payload_size); #if BF_VERBS_ENABLED } else if( backend == BF_IO_VERBS ) { - method = new UDPVerbsReceiver(fd, max_payload_size); + method = new UDPVerbsReceiver(fd, max_payload_size, core); #endif } else { return BF_STATUS_UNSUPPORTED; From 1ae7c3b1254f7259ec1dbad39132d32a04bdacbe Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 28 Jul 2020 14:29:27 -0600 Subject: [PATCH 109/424] What about this mmap() thing? --- src/ib_verbs.cpp | 12 ++++++++---- src/ib_verbs.hpp | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 7bb362bbd..8716d0ac1 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -134,9 +134,11 @@ void Verbs::create_buffers(size_t pkt_size_max) { "allocate scatter/gather entries"); ::memset(_verbs.sge, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(ibv_sge)); _verbs.mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * pkt_size_max; - _verbs.mr_buf = (uint8_t *) ::malloc(_verbs.mr_size); - check_null(_verbs.mr_buf, - "allocate memory region buffer"); + _verbs.mr_buf = (uint8_t *) ::mmap(NULL, _verbs.mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); + check_error(_verbs.mr_buf == MAP_FAILED, + "allocate memory region buffer"); + check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), + "lock memory region buffer"); ::memset(_verbs.mr_buf, 0, _verbs.mr_size); _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, @@ -152,7 +154,9 @@ void Verbs::destroy_buffers() { } if( _verbs.mr_buf ) { - free(_verbs.mr_buf); + if( ::munmap(_verbs.mr_buf, _verbs.mr_size) ) { + failures += 1; + } } if( _verbs.sge ) { diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 288f3bc80..b2d29a6ad 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -42,6 +42,7 @@ #include #include #include +#include extern "C" { #include From 3d553c80117f53a3fe83867e093360de4d67fc86 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 28 Jul 2020 14:35:15 -0600 Subject: [PATCH 110/424] Not needed. --- src/ib_verbs.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 8716d0ac1..dedf60ae0 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -139,7 +139,6 @@ void Verbs::create_buffers(size_t pkt_size_max) { "allocate memory region buffer"); check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), "lock memory region buffer"); - ::memset(_verbs.mr_buf, 0, _verbs.mr_size); _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, "register memory region"); From d0a907aac0efe0ca506646294af52214d5977a4a Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 13:37:56 +0000 Subject: [PATCH 111/424] Remove remnants of JH's hashpipe IBV code --- src/Makefile | 6 +--- src/bf_ibverbs.cpp | 60 ---------------------------------------- src/bifrost/bf_ibverbs.h | 17 ------------ 3 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 src/bf_ibverbs.cpp delete mode 100644 src/bifrost/bf_ibverbs.h diff --git a/src/Makefile b/src/Makefile index 9dc5101b8..b5e6057b8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o -ifdef VERBS: +ifdef VERBS # These files require IB verbs to compile LIBBIFROST_OBJS += \ ib_verbs.o @@ -49,10 +49,6 @@ ifdef XGPU bf_xgpu.o endif endif -ifdef IBV - LIBBIFROST_OBJS += \ - bf_ibverbs.o -endif JIT_SOURCES ?= \ Complex.hpp.jit \ diff --git a/src/bf_ibverbs.cpp b/src/bf_ibverbs.cpp deleted file mode 100644 index 38fa2e6a0..000000000 --- a/src/bf_ibverbs.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include "hashpipe_ibverbs.h" -#include - -#define IBV_UDP_PAYLOAD_OFFSET 42 - -extern "C" { -struct hashpipe_ibv_context _hibv_ctx = {0}; -struct hashpipe_ibv_recv_pkt* _hibv_rpkt; // Current packet chain -struct hashpipe_ibv_recv_pkt* _pkt; // Current packet - -BFstatus ibv_init(size_t pkt_size_max) { - fprintf(stderr, "Configuring IBV socket\n"); - int port = 10000; - char ifname[IFNAMSIZ] = "ens1f1"; - strncpy(_hibv_ctx.interface_name, ifname, IFNAMSIZ); - _hibv_ctx.interface_name[IFNAMSIZ-1] = '\0'; // Ensure NUL termination - _hibv_ctx.send_pkt_num = 1; - _hibv_ctx.recv_pkt_num = 32768; - _hibv_ctx.pkt_size_max = pkt_size_max; - fprintf(stderr, "IBV: pkt_size_max: %d\n", _hibv_ctx.pkt_size_max); - fprintf(stderr, "IBV: recv_pkt_num: %d\n", _hibv_ctx.recv_pkt_num); - _hibv_ctx.max_flows = 1; - int ret = hashpipe_ibv_init(&_hibv_ctx); - if( ret ) { - fprintf(stderr, "ERROR: haspipe_ibv_init returned %d\n", ret); - } - - // Subscribe to RX flow - ret = hashpipe_ibv_flow( - &_hibv_ctx, - 0, IBV_FLOW_SPEC_UDP, - _hibv_ctx.mac, NULL, 0, 0, 0, 0, 0, port); - if( ret ) { - fprintf(stderr, "ERROR: haspipe_ibv_flow returned %d\n", ret); - } - - return BF_STATUS_SUCCESS; -} - -int ibv_recv_packet(uint8_t** pkt_ptr, int flags) { - // If we don't have a work-request queue on the go, - // get some new packets. - if ( _pkt ) { - _pkt = (struct hashpipe_ibv_recv_pkt *)_pkt->wr.next; - if ( !_pkt ) { - hashpipe_ibv_release_pkts(&_hibv_ctx, _hibv_rpkt); - _hibv_rpkt = NULL; - } - } - while (!_hibv_rpkt) { - _hibv_rpkt = hashpipe_ibv_recv_pkts(&_hibv_ctx, 1); - _pkt = _hibv_rpkt; - } - // IBV returns Eth/UDP/IP headers. Strip them off here. - *pkt_ptr = (uint8_t *)_pkt->wr.sg_list->addr + IBV_UDP_PAYLOAD_OFFSET; - return _pkt->length - IBV_UDP_PAYLOAD_OFFSET; -} - -} diff --git a/src/bifrost/bf_ibverbs.h b/src/bifrost/bf_ibverbs.h deleted file mode 100644 index ce1206c74..000000000 --- a/src/bifrost/bf_ibverbs.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef BF_IBVERBS_H_INCLUDE_GUARD_ -#define BF_IBVERBS_H_INCLUDE_GUARD_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -BFstatus ibv_init(size_t pkt_size_max); -int ibv_recv_packet(uint8_t** pkt_ptr, int flags); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_IBVERBS_INCLUDE_GUARD_ From 76da1ebc61c6524b87dc979751f7d9be857dd176 Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 13:39:40 +0000 Subject: [PATCH 112/424] Remove remnants of JH's hashpipe IBV code --- src/packet_capture.cpp | 24 ------------------------ src/packet_capture.hpp | 23 ----------------------- 2 files changed, 47 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 9c24f8d87..f6d56b43a 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -328,30 +328,6 @@ BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, BF_IO_UDP); } -BFstatus bfIbvUdpCaptureCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core) { - return BFpacketcapture_create(obj, - format, - fd, - ring, - nsrc, - src0, - buffer_ntime, - slot_ntime, - sequence_callback, - core, - BF_IO_IBV_UDP); -} - BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, const char* format, int fd, diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 509b9f6c8..c8fc3f561 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -222,27 +222,6 @@ class VMAReceiver { }; #endif // BF_VMA_ENABLED -#ifndef BF_HPIBV_ENABLED -#define BF_HPIBV_ENABLED 0 -#endif - -#if BF_HPIBV_ENABLED -#include - -class IBVUDPPacketReceiver : public PacketCaptureMethod { -public: - IBVUDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_IBV_UDP) - { - ibv_init(pkt_size_max); - } - inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { - return ibv_recv_packet(pkt_ptr, flags); - } - inline const char* get_name() { return "udp_capture"; } -}; -#endif // BF_HPIBV_ENABLED - class UDPPacketReceiver : public PacketCaptureMethod { #if BF_VMA_ENABLED VMAReceiver _vma; @@ -1204,8 +1183,6 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new DiskPacketReader(fd, max_payload_size); } else if( backend == BF_IO_UDP ) { method = new UDPPacketReceiver(fd, max_payload_size); - } else if( backend == BF_IO_IBV_UDP ) { - method = new IBVUDPPacketReceiver(fd, max_payload_size); } else if( backend == BF_IO_SNIFFER ) { method = new UDPPacketSniffer(fd, max_payload_size); #if BF_VERBS_ENABLED From 951b7412c90dd758446bdd211814742a1fc6043b Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 13:39:59 +0000 Subject: [PATCH 113/424] Default to buffer 32k packets Reaches 27Gbps on LWA352 pipeline --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index b2d29a6ad..d00cbca08 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -53,7 +53,7 @@ extern "C" { #endif #ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 8192 +#define BF_VERBS_NPKTBUF 32768 #endif #ifndef BF_VERBS_WCBATCH From d8632960e2342a62d83960c8c5856ab23ebc91ff Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 09:59:18 -0400 Subject: [PATCH 114/424] Remove some unused code --- src/formats/snap2.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index ff401123b..fe0f2d7cd 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -143,7 +143,6 @@ class SNAP2Processor : virtual public PacketProcessor { itype const* __restrict__ in = (itype const*)pkt->payload_ptr; otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; - int words_per_chan_in = pkt->npol >> 5; // 32 pols per 256-bit word int words_per_chan_out = pkt->npol_tot >> 5; int pol_offset_out = pkt->pol0 >> 5; int pkt_chan = pkt->chan0; // The first channel in this packet @@ -156,7 +155,7 @@ class SNAP2Processor : virtual public PacketProcessor { __m256i *dest_p; __m256i vecbuf[2]; uint64_t *in64 = (uint64_t *)in; - int c, i; + int c; dest_p = (__m256i *)(out + (words_per_chan_out * (pkt_chan)) + pol_offset_out); for(c=0; cnchan; c++) { vecbuf[0] = _mm256_set_epi64x(in64[3], in64[2], in64[1], in64[0]); From 35e819d39d32688f212a73109373448adf372001 Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 09:59:47 -0400 Subject: [PATCH 115/424] Change how bifrost sequences are defined Sequence only changes if out-of-order packets indicate the upstream transmitters have reset --- src/packet_capture.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c61454098..a0e3e7957 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -657,6 +657,7 @@ class BFpacketcapture_chips_impl : public BFpacketcapture_impl { class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; + BFoffset _last_pkt_seq; BFpacketcapture_snap2_sequence_callback _sequence_callback; @@ -665,7 +666,8 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // always starts things ~3 seq's before the 1sec boundary anyway. //seq = round_up(pkt->seq, _slot_ntime); //*_seq = round_nearest(pkt->seq, _slot_ntime); - _seq = round_up(pkt->seq, _slot_ntime); + //_seq = round_up(pkt->seq, _slot_ntime); + _seq = pkt->seq; this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { @@ -679,8 +681,12 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // Has the configuration changed? I.e., different channels being sent. inline bool has_sequence_changed(const PacketDesc* pkt) { // TODO: Decide what a sequence actually is! - return (pkt->seq % 480 == 0); - //return false; + // Currently a new sequence starts whenever packets come out of order. + // This isn't great, but the packet RX code assumes packets are in order too. + bool is_new_seq; + is_new_seq = ((pkt->seq != _last_pkt_seq) && (pkt->seq != _last_pkt_seq)); + _last_pkt_seq = pkt->seq; + return is_new_seq; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); From f889f156092084b5c557510a3cb953ce3ffd95f6 Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 29 Jul 2020 10:05:05 -0400 Subject: [PATCH 116/424] Don't use VMA or HWLOC --- user.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user.mk b/user.mk index df51b226f..edea22fbd 100644 --- a/user.mk +++ b/user.mk @@ -32,7 +32,7 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #ANY_ARCH = 1 # Disable native architecture compilation #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) #NUMA = 1 # Enable use of numa library for setting affinity of ring memory -HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture -VMA = 1 # Enable use of Mellanox libvma in udp_capture +#HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture +#VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) VERBS = 1 # Enable use of IB verbs with udp_verbs_capture From d52ebb28477081587a1980a40ef1d0bab6ad6505 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 30 Jul 2020 17:23:53 +0000 Subject: [PATCH 117/424] VERMS doesn't need -lvma --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index b5e6057b8..ee2e9708b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -112,7 +112,7 @@ endif ifdef VERBS # Requires Mellanox libvma to be installed - LIB += -lvma -libverbs + LIB += -libverbs CPPFLAGS += -DBF_VERBS_ENABLED=1 endif From 6ee33a1256a7cb19ea2342d40df2f42b3e726f31 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 30 Jul 2020 17:24:22 +0000 Subject: [PATCH 118/424] Tweaks to sequence boundaries Round start of seq to a gulp size. Decide if a sequence has ended by checking if the first packet of the next sequence is the current time step + gulp size This enforces gulp_size = slot_size. But, it's not obvious slot size actually does anything other than set the time granularity at which a buffer may start --- src/packet_capture.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 22f74ba51..9bc978e9b 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -656,7 +656,7 @@ class BFpacketcapture_chips_impl : public BFpacketcapture_impl { class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; - BFoffset _last_pkt_seq; + BFoffset _last_seq; BFpacketcapture_snap2_sequence_callback _sequence_callback; @@ -665,8 +665,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // always starts things ~3 seq's before the 1sec boundary anyway. //seq = round_up(pkt->seq, _slot_ntime); //*_seq = round_nearest(pkt->seq, _slot_ntime); - //_seq = round_up(pkt->seq, _slot_ntime); - _seq = pkt->seq; + _seq = round_up(pkt->seq, _slot_ntime); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { @@ -680,11 +679,12 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // Has the configuration changed? I.e., different channels being sent. inline bool has_sequence_changed(const PacketDesc* pkt) { // TODO: Decide what a sequence actually is! - // Currently a new sequence starts whenever packets come out of order. - // This isn't great, but the packet RX code assumes packets are in order too. + // Currently a new sequence starts whenever a block finishes and the next + // packet isn't from the next block + // TODO. Is this actually reasonable? Does it recover from upstream resyncs? bool is_new_seq; - is_new_seq = ((pkt->seq != _last_pkt_seq) && (pkt->seq != _last_pkt_seq)); - _last_pkt_seq = pkt->seq; + is_new_seq = (pkt->seq != _last_seq + _slot_ntime); + _last_seq = pkt->seq; return is_new_seq; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { @@ -692,6 +692,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { _chan0 = pkt->chan0; _nchan = pkt->nchan; _payload_size = pkt->payload_size; + _last_seq = _seq; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, From 9206d8f682bb725a3cd6173be03259ffc5c720c9 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 30 Jul 2020 20:28:51 +0000 Subject: [PATCH 119/424] Make new sequence start when packet seq number resets --- src/packet_capture.cpp | 8 ++++++++ src/packet_capture.hpp | 16 ++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index f6d56b43a..7827fbc0c 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -91,6 +91,14 @@ int PacketCaptureThread::run(uint64_t seq_beg, BF_PRINTD("HERE" << " " << _pkt.seq << " < " << seq_beg); _have_pkt = false; if( less_than(_pkt.seq, seq_beg) ) { + // If lots [TODO: what is lots] of packets are late + // return. Otherwise a seq reset can lead to being stuck + // here endlessly counting late packets. + if( less_than(_pkt.seq + nseq_per_obuf, seq_beg) ) { + _have_pkt = true; + ret = CAPTURE_SUCCESS; + break; + } ++_stats.nlate; _stats.nlate_bytes += _pkt.payload_size; ++_src_stats[_pkt.src].nlate; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 9bc978e9b..7114482ee 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -661,11 +661,6 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { BFpacketcapture_snap2_sequence_callback _sequence_callback; void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { - // TODO: Might be safer to round to nearest here, but the current firmware - // always starts things ~3 seq's before the 1sec boundary anyway. - //seq = round_up(pkt->seq, _slot_ntime); - //*_seq = round_nearest(pkt->seq, _slot_ntime); - _seq = round_up(pkt->seq, _slot_ntime); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { @@ -682,17 +677,22 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // Currently a new sequence starts whenever a block finishes and the next // packet isn't from the next block // TODO. Is this actually reasonable? Does it recover from upstream resyncs? - bool is_new_seq; - is_new_seq = (pkt->seq != _last_seq + _slot_ntime); + bool is_new_seq = false; + if ( pkt->seq != _last_seq + _slot_ntime ) { + is_new_seq = true; + this->flush(); + } _last_seq = pkt->seq; return is_new_seq; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + _seq = round_up(pkt->seq, _slot_ntime); + fprintf(stderr, "New seq start is %d based on pkt->seq %d\n", _seq, (int)pkt->seq); + _last_seq = _seq; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); _chan0 = pkt->chan0; _nchan = pkt->nchan; _payload_size = pkt->payload_size; - _last_seq = _seq; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, From c10bb2b2b29e813f7a9e5148e3ba5531ad2f4fe1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 31 Jul 2020 13:46:03 -0600 Subject: [PATCH 120/424] Added a method to poll the socket timeout value. --- src/ib_verbs.cpp | 2 +- src/ib_verbs.hpp | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index dedf60ae0..19e2bc67b 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -545,7 +545,7 @@ int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { } } while( _verbs.pkt_batch == NULL ) { - _verbs.pkt_batch = this->receive(1); + _verbs.pkt_batch = this->receive(_timeout); _verbs.pkt = _verbs.pkt_batch; } // IBV returns Eth/UDP/IP headers. Strip them off here. diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index b2d29a6ad..7fa1f52c9 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -100,9 +100,10 @@ struct bf_ibv { } // extern "C" class Verbs : public BoundThread { - int _fd; - size_t _pkt_size_max; - bf_ibv _verbs; + int _fd; + size_t _pkt_size_max; + int _timeout; + bf_ibv _verbs; void get_interface_name(char* name) { sockaddr_in sin; @@ -164,6 +165,13 @@ class Verbs : public BoundThread { "query socket name"); return ntohs(sin.sin_port); } + int get_timeout_ms() { + timeval value; + socklen_t size = sizeof(value); + check_error(::getsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, &value, &size), + "query socket timeout"); + return int(value.tv_sec*1000) + int(value.tv_usec/1000); + } uint64_t get_interface_gid() { uint64_t id; uint8_t mac[6] = {0}; @@ -230,6 +238,7 @@ class Verbs : public BoundThread { Verbs(int fd, size_t pkt_size_max, int core) : BoundThread(core), _fd(fd), _pkt_size_max(pkt_size_max) { ::memset(&_verbs, 0, sizeof(_verbs)); + _timeout = get_timeout_ms(); create_context(); create_buffers(pkt_size_max); From e6fdff18b3bdf725e590b94a1a770f17b9048527 Mon Sep 17 00:00:00 2001 From: JackH Date: Sat, 1 Aug 2020 11:55:57 +0000 Subject: [PATCH 121/424] handle StopIteration exceptions Python 3.7 enables https://www.python.org/dev/peps/pep-0479/ StopIteration errors are, from Python 3.7, promoited to RuntimeErrors and must be explicitly handled by user code. See https://stackoverflow.com/questions/51700960/runtimeerror-generator-raised-stopiteration-every-time-i-try-to-run-app --- python/bifrost/ring.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/python/bifrost/ring.py b/python/bifrost/ring.py index ddf2c71e0..83ba84ec0 100644 --- a/python/bifrost/ring.py +++ b/python/bifrost/ring.py @@ -112,8 +112,11 @@ def open_earliest_sequence(self, guarantee=True): def read(self, whence='earliest', guarantee=True): with ReadSequence(self, which=whence, guarantee=guarantee) as cur_seq: while True: - yield cur_seq - cur_seq.increment() + try: + yield cur_seq + cur_seq.increment() + except StopIteration: + return #def _data(self): # data_ptr = _get(self.lib.bfRingLockedGetData, self.obj) # #data_ptr = c_void_p() @@ -273,9 +276,12 @@ def read(self, span_size, stride=None, begin=0): stride = span_size offset = begin while True: - with self.acquire(offset, span_size) as ispan: - yield ispan - offset += stride + try: + with self.acquire(offset, span_size) as ispan: + yield ispan + offset += stride + except StopIteration: + return class SpanBase(object): def __init__(self, ring, writeable): From f9530728b4b15ab24e6b135c072156ac962808d4 Mon Sep 17 00:00:00 2001 From: JackH Date: Sat, 1 Aug 2020 12:29:38 +0000 Subject: [PATCH 122/424] Remove debug print --- src/packet_capture.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 7114482ee..e8b397d40 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -687,7 +687,6 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { _seq = round_up(pkt->seq, _slot_ntime); - fprintf(stderr, "New seq start is %d based on pkt->seq %d\n", _seq, (int)pkt->seq); _last_seq = _seq; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); _chan0 = pkt->chan0; From fa671f43984ec660330ec6078a0460218a5a0a65 Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 10 Aug 2020 19:14:26 +0000 Subject: [PATCH 123/424] Tweak SNAP2 packet format to contain sync time And feed sync time into the pipeline time_tag --- src/formats/snap2.hpp | 10 +++------- src/packet_capture.hpp | 7 +++++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index fe0f2d7cd..9855b8c2e 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -33,8 +33,6 @@ #include // SSE #include -#define SNAP2_HEADER_MAGIC 0xaabbccdd - // TODO: parameterize somewhere. This isn't // related to the packet formatting #define PIPELINE_NPOL 704 @@ -44,9 +42,9 @@ // All entries are network (i.e. big) endian struct snap2_hdr_type { uint64_t seq; // Spectra counter == packet counter - uint32_t magic; // = 0xaabbccdd + uint32_t sync_time; // UNIX sync time uint16_t npol; // Number of pols in this packet - uint16_t npol_tot; // Number of pols total + uint16_t npol_tot; // Number of pols total uint16_t nchan; // Number of channels in this packet uint16_t nchan_tot; // Number of channels total (for this pipeline) uint32_t chan_block_id; // ID of this block of chans @@ -92,10 +90,8 @@ class SNAP2Decoder : virtual public PacketDecoder { const snap2_hdr_type* pkt_hdr = (snap2_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(snap2_hdr_type); int pld_size = pkt_size - sizeof(snap2_hdr_type); - if( be32toh(pkt_hdr->magic) != SNAP2_HEADER_MAGIC ) { - return false; - } pkt->seq = be64toh(pkt_hdr->seq); + pkt->time_tag = be32toh(pkt_hdr->sync_time); int npol_blocks = (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index e8b397d40..ef5e5d9b4 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -657,6 +657,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; BFoffset _last_seq; + BFoffset _last_time_tag; BFpacketcapture_snap2_sequence_callback _sequence_callback; @@ -678,7 +679,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // packet isn't from the next block // TODO. Is this actually reasonable? Does it recover from upstream resyncs? bool is_new_seq = false; - if ( pkt->seq != _last_seq + _slot_ntime ) { + if ( (_last_time_tag != pkt->time_tag) || (pkt->seq != _last_seq + _slot_ntime) ) { is_new_seq = true; this->flush(); } @@ -687,7 +688,9 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { _seq = round_up(pkt->seq, _slot_ntime); - _last_seq = _seq; + *time_tag = (BFoffset) pkt->time_tag; + _last_time_tag = pkt->time_tag; + _last_seq = _seq; *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); _chan0 = pkt->chan0; _nchan = pkt->nchan; From 8e92235fbe7d39bbe17095c175fc4634a9106292 Mon Sep 17 00:00:00 2001 From: JackH Date: Sun, 16 Aug 2020 12:40:19 +0000 Subject: [PATCH 124/424] Add option to sum over freq chans while subselecting baselines --- src/bf_xgpu.cpp | 8 ++++---- src/bifrost/bf_xgpu.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 25c3774eb..3fcbb8768 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -134,10 +134,10 @@ BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump) { * and gather them in a new buffer, in order chan x visibility x complexity [int32] * BFarray *in : Pointer to a BFarray with storage in device memory, where xGPU results reside * BFarray *in : Pointer to a BFarray with storage in device memory where collated visibilities should be written. - * int **vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. - * int nvis : The number of visibilities to colate (length of the vismap array) + * BFarray *vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. + * int nchan_sum: The number of frequency channels to sum over */ -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap) { +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_sum) { long long unsigned nvis = num_contiguous_elements(vismap); int xgpu_error; if (in->space != BF_SPACE_CUDA) { @@ -149,7 +149,7 @@ BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap) { if (vismap->space != BF_SPACE_CUDA) { return BF_STATUS_UNSUPPORTED_SPACE; } - xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, nvis); + xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, nvis, nchan_sum); if (xgpu_error != XGPU_OK) { fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); return BF_STATUS_INTERNAL_ERROR; diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index ede805053..7b4f45b1e 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -4,4 +4,4 @@ BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap); +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_sum); From 99c0b5b2be38c937ebd980d470a9f0ac95be32a8 Mon Sep 17 00:00:00 2001 From: JackH Date: Sun, 16 Aug 2020 17:09:04 +0000 Subject: [PATCH 125/424] Add methods for converting an input order to a visibility order --- src/bf_xgpu.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++ src/bifrost/bf_xgpu.h | 1 + 2 files changed, 74 insertions(+) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 3fcbb8768..35e68d429 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -158,4 +158,77 @@ BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_s } } +/* Computes the triangular index of an (i,j) pair as shown here... + * NB: Output is valid only if i >= j. + * + * i=0 1 2 3 4.. + * +--------------- + * j=0 | 00 01 03 06 10 + * 1 | 02 04 07 11 + * 2 | 05 08 12 + * 3 | 09 13 + * 4 | 14 + * : + */ +int tri_index(int i, int j){ + return (i * (i+1))/2 + j; + } + +/* Returns index into the GPU's register tile ordered output buffer for the + * real component of the cross product of inputs in0 and in1. Note that in0 + * and in1 are input indexes (i.e. 0 based) and often represent antenna and + * polarization by passing (2*ant_idx+pol_idx) as the input number (NB: ant_idx + * and pol_idx are also 0 based). Return value is valid if in1 >= in0. The + * corresponding imaginary component is located xgpu_info.matLength words after + * the real component. + */ +int regtile_index(int in0, int in1, int nstand) { + int a0, a1, p0, p1; + int num_words_per_cell=4; + int quadrant, quadrant_index, quadrant_size, cell_index, pol_offset, index; + a0 = in0 >> 1; + a1 = in1 >> 1; + p0 = in0 & 1; + p1 = in1 & 1; + + // Index within a quadrant + quadrant_index = tri_index(a1/2, a0/2); + // Quadrant for this input pair + quadrant = 2*(a0&1) + (a1&1); + // Size of quadrant + quadrant_size = (nstand/2 + 1) * nstand/4; + // Index of cell (in units of cells) + cell_index = quadrant*quadrant_size + quadrant_index; + // Pol offset + pol_offset = 2*p1 + p0; + // Word index (in units of words (i.e. floats) of real component + index = (cell_index * num_words_per_cell) + pol_offset; + return index; + } + +BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj, int nstand, int npol) { + int *ip_map = (int *)antpol_to_input->data; // indexed by stand, pol + int *bl_map = (int *)antpol_to_bl->data; // indexed by stand0, stand1, pol0, pol1 + int *conj_map = (int *)is_conj->data; // indexed by stand0, stand1, pol0, pol1 + int s0, s1, p0, p1, i0, i1; + for (s0=0; s0= i0) { + bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i0, i1, nstand); + conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 0; + } else { + bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i1, i0, nstand); + conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 1; + } + } + } + } + } + return BF_STATUS_SUCCESS; +} + } // C diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 7b4f45b1e..6e806c0df 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -5,3 +5,4 @@ BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_sum); +BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj, int nstand, int npol); From 63f84d9a1ca3c8dbeb37beda5eb0894c950a8deb Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 17 Aug 2020 11:26:01 +0000 Subject: [PATCH 126/424] Remove IBV option from UDPCapture constructor This is no longer necessary now there is a dedicated UDPVerbsCapture class --- python/bifrost/packet_capture.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 33c61abab..c72f000ae 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -82,7 +82,7 @@ def end(self): class UDPCapture(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None, - ibverbs=False, interface='', port=-1): + interface='', port=-1): try: fmt = fmt.encode() except AttributeError: @@ -90,19 +90,11 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, pass if core is None: core = -1 - if not ibverbs: - BifrostObject.__init__( - self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, - max_payload_size, buffer_ntime, slot_ntime, - sequence_callback.obj, core) - else: - print("Using IBVerbs") - BifrostObject.__init__( - self, _bf.bfIbvUdpCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, - max_payload_size, buffer_ntime, slot_ntime, - sequence_callback.obj, core) + BifrostObject.__init__( + self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) class UDPSniffer(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, From 3cb5105ec70baae091db52e6765d58bf057369e9 Mon Sep 17 00:00:00 2001 From: JackH Date: Mon, 17 Aug 2020 18:01:19 +0000 Subject: [PATCH 127/424] Add function to reorder DP4A xGPU output into visibility matrix --- src/bf_xgpu.cpp | 41 ++++++++++++++++++++++++++++++++++++++++- src/bifrost/bf_xgpu.h | 3 ++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 35e68d429..34809ec64 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -206,11 +206,16 @@ int regtile_index(int in0, int in1, int nstand) { return index; } -BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj, int nstand, int npol) { +BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj) { int *ip_map = (int *)antpol_to_input->data; // indexed by stand, pol int *bl_map = (int *)antpol_to_bl->data; // indexed by stand0, stand1, pol0, pol1 int *conj_map = (int *)is_conj->data; // indexed by stand0, stand1, pol0, pol1 int s0, s1, p0, p1, i0, i1; + int nstand, npol; + XGPUInfo xgpu_info; + xgpuInfo(&xgpu_info); + nstand = xgpu_info.nstation; + npol = xgpu_info.npol; for (s0=0; s0data; + int *input_r = (int *)xgpu_output->data; + int *input_i = input_r + xgpu_info.matLength; + int *bl = (int *)baselines->data; + int *conj = (int *)is_conjugated->data; + int n_bl = num_contiguous_elements(baselines); + int xgpu_n_input = xgpu_info.nstation * xgpu_info.npol; + int n_chan = xgpu_info.nfrequency; + int i, c; + // number of entries per channel + size_t regtile_chan_len = 4 * 4 * xgpu_n_input/4 * (xgpu_n_input/4+1) / 2; + fprintf(stderr, "nbaselines: %d; nchans:%d\n", n_bl, n_chan); + for (i=0; i Date: Mon, 17 Aug 2020 18:48:38 +0000 Subject: [PATCH 128/424] Remove debugging prints --- src/bf_xgpu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 34809ec64..0c55a0b9a 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -256,7 +256,6 @@ BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baseli int i, c; // number of entries per channel size_t regtile_chan_len = 4 * 4 * xgpu_n_input/4 * (xgpu_n_input/4+1) / 2; - fprintf(stderr, "nbaselines: %d; nchans:%d\n", n_bl, n_chan); for (i=0; i Date: Fri, 4 Sep 2020 11:23:48 +0000 Subject: [PATCH 129/424] Fix conjugations Fix bugs and set conjugation convention such that given a visibility matrix in order: [stand0, stand1, pol0, pol1] The conjugation of the data is (stand0, pol0) * conj(stand1, pol1) --- src/bf_xgpu.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 0c55a0b9a..13a014c5f 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -222,12 +222,14 @@ BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray for (p1=0; p1= i0) { + // Set the conj map such that bl_map[stand0, stand1, pol0, pol1] has conjugation convention + // stand0,pol0 * conj(stand1,pol1) + if (i1 > i0) { bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i0, i1, nstand); - conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 0; + conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 1; } else { bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i1, i0, nstand); - conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 1; + conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 0; } } } @@ -240,6 +242,7 @@ BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray * Reorder a DP4A xGPU spec output into something more sane, throwing * away unwanted baselines and re-concatenating real and imag parts in * a reasonable way. + * Also remove conjugation weirdness so baselines a,b has conjugation a*conj(b) */ BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated) { XGPUInfo xgpu_info; @@ -259,10 +262,10 @@ BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baseli for (i=0; i Date: Thu, 10 Sep 2020 17:30:33 +0000 Subject: [PATCH 130/424] Fix source ID computation --- src/formats/snap2.hpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 9855b8c2e..23de0c387 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -96,13 +96,13 @@ class SNAP2Decoder : virtual public PacketDecoder { int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); pkt->nsrc = npol_blocks * nchan_blocks;// _nsrc; - pkt->src = (npol_blocks * be16toh(pkt_hdr->chan_block_id)) + (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); pkt->nchan = be16toh(pkt_hdr->nchan); pkt->chan0 = be32toh(pkt_hdr->chan_block_id) * be16toh(pkt_hdr->nchan); pkt->nchan_tot = be16toh(pkt_hdr->nchan_tot); pkt->npol = be16toh(pkt_hdr->npol); pkt->npol_tot = be16toh(pkt_hdr->npol_tot); pkt->pol0 = be32toh(pkt_hdr->pol0); + pkt->src = (pkt->pol0 / pkt->npol) + be32toh(pkt_hdr->chan_block_id) * npol_blocks; pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; return this->valid_packet(pkt); @@ -153,6 +153,9 @@ class SNAP2Processor : virtual public PacketProcessor { uint64_t *in64 = (uint64_t *)in; int c; dest_p = (__m256i *)(out + (words_per_chan_out * (pkt_chan)) + pol_offset_out); + //if((pol_offset_out == 0) && (pkt_chan==0) && ((pkt->seq % 120)==0) ){ + // fprintf(stderr, "nsrc: %d seq: %d, dest_p: %p obuf idx %d, obuf offset %lu, nseq_per_obuf %d, seq0 %d, nbuf: %d\n", pkt->nsrc, pkt->seq, dest_p, obuf_idx, obuf_offset, nseq_per_obuf, seq0, nbuf); + //} for(c=0; cnchan; c++) { vecbuf[0] = _mm256_set_epi64x(in64[3], in64[2], in64[1], in64[0]); vecbuf[1] = _mm256_set_epi64x(in64[7], in64[6], in64[5], in64[4]); @@ -168,14 +171,16 @@ class SNAP2Processor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - typedef aligned256_type otype; - otype* __restrict__ aligned_data = (otype*)data; - for( int t=0; t Date: Wed, 7 Oct 2020 12:14:36 +0000 Subject: [PATCH 131/424] Py3-ize pipeline2dot --- tools/pipeline2dot.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/pipeline2dot.py b/tools/pipeline2dot.py index dd21a592d..c899af23c 100755 --- a/tools/pipeline2dot.py +++ b/tools/pipeline2dot.py @@ -63,7 +63,7 @@ def get_process_details(pid): data = {'user':'', 'cpu':0.0, 'mem':0.0, 'etime':'00:00', 'threads':0} try: - output = subprocess.check_output('ps o user,pcpu,pmem,etime,nlwp %i' % pid, shell=True) + output = subprocess.check_output('ps o user,pcpu,pmem,etime,nlwp %i' % pid, shell=True).decode() output = output.split('\n')[1] fields = output.split(None, 4) data['user'] = fields[0] @@ -348,4 +348,3 @@ def main(args): help='exclude associated blocks') args = parser.parse_args() main(args) - \ No newline at end of file From 5cc85c55cd5d1ee389cbd33040fcde428f4a3615 Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 7 Oct 2020 14:24:42 +0000 Subject: [PATCH 132/424] Add option to conjugate baselines while subselecting --- src/bf_xgpu.cpp | 10 ++++++++-- src/bifrost/bf_xgpu.h | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 13a014c5f..91d55c843 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -137,7 +137,7 @@ BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump) { * BFarray *vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. * int nchan_sum: The number of frequency channels to sum over */ -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_sum) { +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum) { long long unsigned nvis = num_contiguous_elements(vismap); int xgpu_error; if (in->space != BF_SPACE_CUDA) { @@ -149,7 +149,13 @@ BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_s if (vismap->space != BF_SPACE_CUDA) { return BF_STATUS_UNSUPPORTED_SPACE; } - xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, nvis, nchan_sum); + if (conj->space != BF_SPACE_CUDA) { + return BF_STATUS_UNSUPPORTED_SPACE; + } + if (num_contiguous_elements(conj) != nvis) { + return BF_STATUS_INVALID_SHAPE; + } + xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, (int *)conj->data, nvis, nchan_sum); if (xgpu_error != XGPU_OK) { fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); return BF_STATUS_INTERNAL_ERROR; diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 872777d41..e06b5be61 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -4,6 +4,6 @@ BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, int nchan_sum); +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum); BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj); BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated); From db72993f3abf62ad6facf6df1db4c2fa58e73631 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 20 Oct 2020 15:56:52 +0000 Subject: [PATCH 133/424] Beamformer fixes and comment updates - Add function to accumulate a single beam from a buffer of many - Make accumulation functions take acc_len as an arg rather than reading from context --- src/beamform.cpp | 17 +++++++-- src/bifrost/beamform.h | 52 ++++++++++++++++++++++++++- src/cublas_beamform.cu | 79 +++++++++++++++++++++++++++++++++-------- src/cublas_beamform.cuh | 3 +- 4 files changed, 133 insertions(+), 18 deletions(-) diff --git a/src/beamform.cpp b/src/beamform.cpp index eb6c563e4..16d874222 100644 --- a/src/beamform.cpp +++ b/src/beamform.cpp @@ -59,7 +59,7 @@ BFstatus bfBeamformRun(BFarray *in, BFarray *out, BFarray *weights) { return BF_STATUS_SUCCESS; } -BFstatus bfBeamformIntegrate(BFarray *in, BFarray *out) { +BFstatus bfBeamformIntegrate(BFarray *in, BFarray *out, int ntimes_sum) { if (in->space != BF_SPACE_CUDA) { fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); return BF_STATUS_INVALID_SPACE; @@ -68,7 +68,20 @@ BFstatus bfBeamformIntegrate(BFarray *in, BFarray *out) { fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); return BF_STATUS_INVALID_SPACE; } - cublas_beamform_integrate((float *)in->data, (float *)out->data); + cublas_beamform_integrate((float *)in->data, (float *)out->data, ntimes_sum); + return BF_STATUS_SUCCESS; +} + +BFstatus bfBeamformIntegrateSingleBeam(BFarray *in, BFarray *out, int ntimes_sum, int beam_index) { + if (in->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + if (out->space != BF_SPACE_CUDA) { + fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); + return BF_STATUS_INVALID_SPACE; + } + cublas_beamform_integrate_single_beam((float *)in->data, (float *)out->data, ntimes_sum, beam_index); return BF_STATUS_SUCCESS; } } // C diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 1da1937a9..890b727da 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -1,6 +1,16 @@ #include #include +/* + * gpudev: GPU device ID to use + * ninputs: Number of inputs (single-polarization) to the beamformer + * nchans: Number of frequency channels + * ntimes: Number of time samples per beamforming call + * nbeams: Number of beams to generate. If using ntime_blocks > 0, beams=N will deliver + * ntime_blocks: Number of time blocks to output. Eg. if ntimes=1000 and ntime_blocks=10, the beamformer + will integrate over 100 samples per call. Set to 0 for no accumulation, in which case + raw beam voltages are output. + */ BFstatus bfBeamformInitialize( int gpudev, int ninputs, @@ -10,13 +20,53 @@ BFstatus bfBeamformInitialize( int ntime_blocks ); +/* + * in: Pointer to ntime x nchan x ninputs x 4+4 bit data block + * out: Pointer to output data. + * If ntime_blocks > 0: + * For the purposes of generating dynamic spectra, beam 2n and 2n+1 are considered + * to be two pols of the same pointing, and are cross-multipled and summed over + * ntimes/ntime_blocks to form the output array: + * nbeam/2 x ntime_blocks x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) + * Note that this means for N dual-pol beam pointings, the beamformer should be + * constructed with nbeams=2N. This isn't very efficient, but makes it easy to deal + * with arbitrary polarization orderings in the input buffer (suitable beamforming + * coefficients can make appropriate single-pol beam pairs). + * If ntime_blocks = 0: + * Data are returned as voltages, in order: + * ntimes x nchan x nbeam x complex64 beamformer block + * + * weights -- pointer to nbeams x nchans x ninputs x complex64 weights + */ BFstatus bfBeamformRun( BFarray *in, BFarray *out, BFarray *weights ); +/* + * Take the output of bfBeamformRun with ntime_blocks = 0, and perform transposing and integration + * of data, to deliver a time integrated dual-pol dynamic spectra of the form: + * nbeam/2 x ntime/ntimes_sum x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) + * I.e., the format which would be returned by bfBeamformRun is ntime_blocks > 0 + */ BFstatus bfBeamformIntegrate( BFarray *in, - BFarray *out + BFarray *out, + int ntimes_sum, +); + +/* + * Take the output of bfBeamformRun with ntime_blocks = 0, and + * deliver a time integrated dual-pol dynamic spectra for a single beam of the form: + * ntime/ntimes_sum x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) + * + * ntime_sum: the number of times to integrate + * beam_index: The beam to select (if beam_index=N, beams N and N+1 will be used as a polarization pair) + */ +BFstatus bfBeamformIntegrateSingleBeam( + BFarray *in, + BFarray *out, + int ntimes_sum, + int beam_index ); diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu index 94f095850..4be7aedb6 100644 --- a/src/cublas_beamform.cu +++ b/src/cublas_beamform.cu @@ -54,16 +54,16 @@ __global__ void trans_output_and_sum(float *in, int chan = blockIdx.x; int beam = blockIdx.y; int time = threadIdx.x; - long long int old_index = chan*n_beam*n_time*2 + beam*n_time*2 + time*n_time_sum; // start index for n_time/n_time_sum samples + long long int old_index = chan*n_beam*n_time*2 + beam*n_time*2 + time*n_time_sum*2; // start index for n_time/n_time_sum samples long long int new_index = beam*(n_time / n_time_sum)*n_chan + time*n_chan + chan; float xx=0., yy=0., xy_r=0., xy_i=0.; float x_r, x_i, y_r, y_i; int t; for (t=0; t 0 int ninputs; // Number of inputs (ants * pols) int npols; // Number of polarizations per antenna int nchans; // Number of channels input @@ -167,7 +203,7 @@ void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int n // Internally allocate intermediate buffers gpuErrchk( cudaMalloc(&context.in32_d, ninputs * nchans * ntimes * 2 * sizeof(float)) ); // If the context is initialized with ntimeblocks=0, then we do no summing so don't - // need the intermediate buffer + // need the intermediate buffer allocated internally. if (ntimeblocks > 0) { gpuErrchk( cudaMalloc(&context.out_d, ntimes * nchans * nbeams * 2 * sizeof(float)) ); } @@ -188,7 +224,7 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { cudaStreamSynchronize(context.stream); // If we are integrating beam powers, put the - // GEM output in the context-defined intermediate + // GEM output in the internal intermediate // buffer. If not, then write beamformer output // to the address given by the user. float *gem_out_d; @@ -242,6 +278,7 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { if (context.ntimeblocks > 0) { // Create XX, YY, XY beam powers. // Sum over `ntimes_sum` samples + // Write to the user-provided output buffer int ntimes_sum = context.ntimes / context.ntimeblocks; dim3 sumBlockGrid(context.nchans, context.nbeams/2); dim3 sumThreadGrid(context.ntimes / ntimes_sum); @@ -257,13 +294,12 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { } } -void cublas_beamform_integrate(float *in_d, float *out_d) { +void cublas_beamform_integrate(float *in_d, float *out_d, int ntimes_sum) { // Create XX, YY, XY beam powers. // Sum over `ntimes_sum` samples - int ntimes_sum = context.ntimes / context.ntimeblocks; dim3 sumBlockGrid(context.nchans, context.nbeams/2); dim3 sumThreadGrid(context.ntimes / ntimes_sum); - trans_output_and_sum<<>>( + trans_output_and_sum<<>>( in_d, out_d, context.nchans, @@ -271,5 +307,20 @@ void cublas_beamform_integrate(float *in_d, float *out_d) { context.ntimes, ntimes_sum ); - cudaStreamSynchronize(context.stream); +} + +void cublas_beamform_integrate_single_beam(float *in_d, float *out_d, int ntimes_sum, int beam_index) { + // Create XX, YY, XY beam powers. + // Sum over `ntimes_sum` samples + dim3 sumBlockGrid(context.nchans); + dim3 sumThreadGrid(context.ntimes / ntimes_sum); + trans_output_and_sum_single_beam<<>>( + in_d, + out_d, + context.nchans, + context.nbeams/2, + context.ntimes, + ntimes_sum, + beam_index + ); } diff --git a/src/cublas_beamform.cuh b/src/cublas_beamform.cuh index 6a0d2b22a..1e9df948f 100644 --- a/src/cublas_beamform.cuh +++ b/src/cublas_beamform.cuh @@ -30,7 +30,8 @@ __global__ void complex2pow(float *in, float *out, int N); void cublas_beamform_destroy(); void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d); -void cublas_beamform_integrate(float *in_d, float *sum_out_d); +void cublas_beamform_integrate(float *in_d, float *sum_out_d, int ntimes_sum); +void cublas_beamform_integrate_single_beam(float *in_d, float *sum_out_d, int ntimes_sum, int beam_index); void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks); #endif From 246af1c0c9a44701678e9227eda881e6f0769111 Mon Sep 17 00:00:00 2001 From: JackH Date: Wed, 28 Oct 2020 12:09:18 +0000 Subject: [PATCH 134/424] Add LWA352 voltage packet output --- src/formats/formats.hpp | 1 + src/formats/lwa352_vbeam.hpp | 57 ++++++++++++++++++++++++++++++++++++ src/packet_writer.hpp | 19 ++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 src/formats/lwa352_vbeam.hpp diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 6e2f4c527..79dd5fd4e 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -36,3 +36,4 @@ #include "tbf.hpp" #include "ibeam.hpp" #include "snap2.hpp" +#include "lwa352_vbeam.hpp" diff --git a/src/formats/lwa352_vbeam.hpp b/src/formats/lwa352_vbeam.hpp new file mode 100644 index 000000000..8cccef753 --- /dev/null +++ b/src/formats/lwa352_vbeam.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +#pragma pack(1) +struct lwa352_vbeam_hdr_type { + uint64_t sync_word; + uint64_t sync_time; + uint64_t time_tag; + double bw_hz; + double sfreq; + uint32_t nchan; + uint32_t chan0; + uint32_t npol; +}; + +class LWA352VBeamHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(lwa352_vbeam_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, + char* hdr) { + lwa352_vbeam_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(lwa352_vbeam_hdr_type)); + + header->sync_word = 0xAABBCCDD00000000L; + header->time_tag = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index dbdc70e84..527505680 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -320,6 +320,18 @@ class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { } }; +class BFpacketwriter_lwa352_vbeam_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_lwa352_vbeam_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new LWA352VBeamHeaderFiller(); + _type_log.update("type : %s\n", "tbf"); + } +}; + BFstatus BFpacketwriter_create(BFpacketwriter* obj, const char* format, int fd, @@ -351,6 +363,10 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, nsamples = 4096; } else if( format == std::string("tbf") ) { nsamples = 6144; + } else if( std::string(format).substr(0, 13) == std::string("lwa352_vbeam_") ) { + // e.g. "lwa352_vbeam_184" is a 184-channel voltage beam" + int nchan = std::atoi((std::string(format).substr(13, std::string(format).length())).c_str()); + nsamples = 2*nchan; // 2 polarizations. Natively 32-bit floating complex (see implementation class) } PacketWriterMethod* method; @@ -390,6 +406,9 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( format == std::string("tbf") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), *obj = 0); + } else if( std::string(format).substr(0, 13) == std::string("lwa352_vbeam_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_lwa352_vbeam_impl(writer, nsamples), + *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } From 9c693fd2d60f0f119bd0249602ead5c0bbaa20f3 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 17 Nov 2020 18:55:00 +0000 Subject: [PATCH 135/424] Syntax error in BfBeamformIntegrate declaration --- src/bifrost/beamform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 890b727da..296336008 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -53,7 +53,7 @@ BFstatus bfBeamformRun( BFstatus bfBeamformIntegrate( BFarray *in, BFarray *out, - int ntimes_sum, + int ntimes_sum ); /* From d10f38aac7a65f3260c102868e060c69e36f3151 Mon Sep 17 00:00:00 2001 From: JackH Date: Tue, 15 Dec 2020 20:20:50 +0000 Subject: [PATCH 136/424] Header docstring --- src/bifrost/beamform.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 296336008..7a5e4d297 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -6,7 +6,8 @@ * ninputs: Number of inputs (single-polarization) to the beamformer * nchans: Number of frequency channels * ntimes: Number of time samples per beamforming call - * nbeams: Number of beams to generate. If using ntime_blocks > 0, beams=N will deliver + * nbeams: Number of beams to generate. If using ntime_blocks > 0, beams=N will deliver N/2 beams. + * (See bfBeamformRun) * ntime_blocks: Number of time blocks to output. Eg. if ntimes=1000 and ntime_blocks=10, the beamformer will integrate over 100 samples per call. Set to 0 for no accumulation, in which case raw beam voltages are output. From aa166129c877cbe17c6c3a8b6ab57797acf7300e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 21 Dec 2020 12:06:33 -0700 Subject: [PATCH 137/424] Added a new 'pbeam' format for the power beams at OVRO-LWA. --- src/bifrost/packet_capture.h | 6 +- src/formats/formats.hpp | 3 +- src/formats/pbeam.hpp | 155 +++++++++++++++++++++++++++++++++++ src/packet_capture.hpp | 115 ++++++++++++++++++++++---- src/packet_writer.hpp | 17 ++-- 5 files changed, 270 insertions(+), 26 deletions(-) create mode 100644 src/formats/pbeam.hpp diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index b32af9bdb..b1002cb3e 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,6 +41,8 @@ typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); +typedef int (*BFpacketcapture_pbeam_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_vdif_sequence_callback)(BFoffset, BFoffset, int, int, int, @@ -58,6 +60,8 @@ BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, BFpacketcapture_ibeam_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetPBeam(BFpacketcapture_callback obj, + BFpacketcapture_pbeam_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, BFpacketcapture_cor_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetVDIF(BFpacketcapture_callback obj, diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 311319169..28d24e221 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,3 +35,4 @@ #include "tbn.hpp" #include "tbf.hpp" #include "ibeam.hpp" +#include "pbeam.hpp" diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp new file mode 100644 index 000000000..653f0b3aa --- /dev/null +++ b/src/formats/pbeam.hpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2020, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +//#include // SSE + +#pragma pack(1) +struct pbeam_hdr_type { + uint8_t server; // Note: 1-based + uint8_t beam; // Note: 1-based + uint8_t gbe; // (AKA tuning) + uint8_t nchan; // 109 + uint8_t nbeam; // 2 + uint8_t nserver; // 6 + // Note: Big endian + uint16_t chan0; // First chan in packet + uint64_t seq; // Note: 1-based +}; + +class PBeamDecoder: virtual public PacketDecoder { + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->seq >= 0 && + pkt->src >= 0 && pkt->src < _nsrc && + pkt->chan0 >= 0); + } +public: + PBeamDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(pbeam_hdr_type) ) { + return false; + } + const pbeam_hdr_type* pkt_hdr = (pbeam_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(pbeam_hdr_type); + int pld_size = pkt_size - sizeof(pbeam_hdr_type); + pkt->seq = be64toh(pkt_hdr->seq) - 1; + //pkt->nsrc = pkt_hdr->nserver; + pkt->nsrc = _nsrc; + pkt->src = (pkt_hdr->beam - _src0) * pkt->hdr_nserver + (pkt_hdr->server - 1); + pkt->beam = pkt_hdr->beam; + pkt->nchan = pkt_hdr->nchan; + pkt->chan0 = ntohs(pkt_hdr->chan0) - pkt->nchan * pkt->src; + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + +class PBeamProcessor : virtual public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + // **CHANGED RECENTLY + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef unaligned128_type itype; // f32 * 1 beam * 4 pol (XX, YY, R(XY), I(XY)) + typedef aligned128_type otype; + + obuf_offset *= BF_UNPACK_FACTOR; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + // Convenience + int beam_server = pkt->src; + int nchan = pkt->nchan; + + int chan, beam; + for(chan=0; chan +class PBeamHeaderFiller : virtual public PacketHeaderFiller { + uint8_t _nbeam = B; + +public: + inline int get_size() { return sizeof(pbeam_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, + char* hdr) { + pbeam_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(pbeam_hdr_type)); + + int nserver = hdr_base->nsrc / _nbeam; + + header->server = (hdr_base->src % nserver) + 1; // Modulo? + header->beam = (hdr_base->src / nserver) + 1; + header->gbe = hdr_base->tuning; + header->nchan = hdr_base->nchan; + header->nbeam = _nbeam; + header->nserver = nserver; + header->chan0 = htons(hdr_base->chan0); + header->seq = htobe64(hdr_base->seq); + } +}; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index bce215344..ec4821395 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -290,8 +290,8 @@ struct PacketStats { class PacketCaptureThread : public BoundThread { private: - PacketCaptureMethod* _method; - PacketStats _stats; + PacketCaptureMethod* _method; + PacketStats _stats; std::vector _src_stats; bool _have_pkt; PacketDesc _pkt; @@ -351,14 +351,16 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { class BFpacketcapture_callback_impl { BFpacketcapture_chips_sequence_callback _chips_callback; BFpacketcapture_ibeam_sequence_callback _ibeam_callback; + BFpacketcapture_pbeam_sequence_callback _pbeam_callback; BFpacketcapture_cor_sequence_callback _cor_callback; BFpacketcapture_vdif_sequence_callback _vdif_callback; BFpacketcapture_tbn_sequence_callback _tbn_callback; BFpacketcapture_drx_sequence_callback _drx_callback; public: BFpacketcapture_callback_impl() - : _chips_callback(NULL), _ibeam_callback(NULL), _cor_callback(NULL), - _vdif_callback(NULL), _tbn_callback(NULL), _drx_callback(NULL) {} + : _chips_callback(NULL), _ibeam_callback(NULL), _pbeam_callback(NULL), + _cor_callback(NULL), _vdif_callback(NULL), _tbn_callback(NULL), + _drx_callback(NULL) {} inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } @@ -371,6 +373,12 @@ class BFpacketcapture_callback_impl { inline BFpacketcapture_ibeam_sequence_callback get_ibeam() { return _ibeam_callback; } + inline void set_pbeam(BFpacketcapture_pbeam_sequence_callback callback) { + _pbeam_callback = callback; + } + inline BFpacketcapture_ibeam_sequence_callback get_pbeam() { + return _pbeam_callback; + } inline void set_cor(BFpacketcapture_cor_sequence_callback callback) { _cor_callback = callback; } @@ -420,7 +428,7 @@ class BFpacketcapture_impl { bool _active; private: - std::chrono::high_resolution_clock::time_point _t0; + std::chrono::high_resolution_clock::time_point _t0; std::chrono::high_resolution_clock::time_point _t1; std::chrono::high_resolution_clock::time_point _t2; std::chrono::duration _process_time; @@ -700,6 +708,81 @@ class BFpacketcapture_ibeam_impl : public BFpacketcapture_impl { } }; +class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_pbeam_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _nbeam = pkt->beam; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan*_nsrc/_nbeam, + _nbeam, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "nbeam : " << _nbeam << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFpacketcapture_pbeam_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_pbeam()) { + _decoder = new PBeamDecoder(nsrc, src0); + _processor = new PBeamProcessor(); + _type_log.update("type : %s\n", "pbeam"); + } +}; + class BFpacketcapture_cor_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; @@ -1039,23 +1122,18 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); max_payload_size = sizeof(chips_hdr_type) + 32*nchan; } - } else if( std::string(format).substr(0, 6) == std::string("ibeam2") ) { + } else if( std::string(format).substr(0, 5) == std::string("ibeam") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time + int nbeam = std::atoi((std::string(format).substr(5, 1).c_str()); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - max_payload_size = sizeof(ibeam_hdr_type) + 64*2*2*nchan; + max_payload_size = sizeof(ibeam_hdr_type) + 64*2*nbeam*nchan; } - } else if( std::string(format).substr(0, 6) == std::string("ibeam3") ) { + } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - max_payload_size = sizeof(ibeam_hdr_type) + 64*2*3*nchan; - } - } else if( std::string(format).substr(0, 6) == std::string("ibeam4") ) { - if( backend == BF_IO_DISK ) { - // Need to know how much to read at a time - int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - max_payload_size = sizeof(ibeam_hdr_type) + 64*2*4*nchan; + max_payload_size = sizeof(pbeam_hdr_type) + 32*4*nchan; } } else if(std::string(format).substr(0, 3) == std::string("cor") ) { if( backend == BF_IO_DISK ) { @@ -1107,6 +1185,11 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_pbeam_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else if( std::string(format).substr(0, 3) == std::string("cor") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_cor_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index dbdc70e84..accf1be1f 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -333,15 +333,13 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; - } else if( std::string(format).substr(0, 7) == std::string("ibeam2_") ) { - int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - nsamples = 2*2*nchan; - } else if( std::string(format).substr(0, 7) == std::string("ibeam3_") ) { + } else if( std::string(format).substr(0, 5) == std::string("ibeam") ) { + int nbeam = std::stoi(std::string(format).stdstr(5, 1)); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - nsamples = 2*3*nchan; - } else if( std::string(format).substr(0, 7) == std::string("ibeam4_") ) { + nsamples = 2*nbeam*nchan; + } else if( std::string(format).substr(0, 7) == std::string("pbeam") ) { int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - nsamples = 2*4*nchan; + nsamples = 4*nchan; } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); nsamples = 4*nchan; @@ -378,6 +376,9 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 7) == std::string("ibeam4_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<4>(writer, nsamples), *obj = 0); + } else if( std::string(format).substr(0, 7) == std::string("pbeam1_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_pbeam_impl<1>(writer, nsamples), + *obj = 0); } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_cor_impl(writer, nsamples), *obj = 0); From 432e1fcc04209f21de56de08aa57c8976984373b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 21 Dec 2020 12:13:57 -0700 Subject: [PATCH 138/424] Added 'pbeam' to the Python API. --- python/bifrost/packet_capture.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index f5fc446ca..67bc942a3 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -44,6 +44,10 @@ def set_ibeam(self, fnc): self._ref_cache['ibeam'] = _bf.BFpacketcapture_ibeam_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetIBeam( self.obj, self._ref_cache['ibeam'])) + def set_pbeam(self, fnc): + self._ref_cache['pbeam'] = _bf.BFpacketcapture_pbeam_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetPBeam( + self.obj, self._ref_cache['pbeam'])) def set_cor(self, fnc): self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( From 0a6fc1530862a9e711449983b73d1efcbf997f32 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 21 Dec 2020 12:44:50 -0700 Subject: [PATCH 139/424] Cleanup --- src/packet_capture.hpp | 23 +++++++++-------------- src/packet_writer.hpp | 22 ++++++++++++---------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index ec4821395..c12c2b149 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1170,21 +1170,16 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); - } else if( std::string(format).substr(0, 6) == std::string("ibeam2") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<2>(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( std::string(format).substr(0, 6) == std::string("ibeam3") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<3>(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), - *obj = 0); - } else if( std::string(format).substr(0, 6) == std::string("ibeam4") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl<4>(capture, ring, nsrc, src0, - buffer_ntime, slot_ntime, - sequence_callback), +#define MATCH_IBEAM_MODE(NBEAM) \ + } else if( std::string(format).substr(0, 6) == std::string("ibeam"#NBEAM) ) { \ + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_ibeam_impl(capture, ring, nsrc, src0, \ + buffer_ntime, slot_ntime, \ + sequence_callback), \ *obj = 0); + MATCH_IBEAM_MODE(2) + MATCH_IBEAM_MODE(3) + MATCH_IBEAM_MODE(4) +#undef MATCH_IBEAM_MODE } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_pbeam_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index accf1be1f..38a7a0e28 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -367,18 +367,20 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_chips_impl(writer, nsamples), *obj = 0); - } else if( std::string(format).substr(0, 7) == std::string("ibeam2_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<2>(writer, nsamples), +#define MATCH_IBEAM_MODE(NBEAM) \ + } else if( std::string(format).substr(0, 7) == std::string("ibeam"#NBEAM"_") ) { \ + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl(writer, nsamples), \ *obj = 0); - } else if( std::string(format).substr(0, 7) == std::string("ibeam3_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<3>(writer, nsamples), - *obj = 0); - } else if( std::string(format).substr(0, 7) == std::string("ibeam4_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl<4>(writer, nsamples), - *obj = 0); - } else if( std::string(format).substr(0, 7) == std::string("pbeam1_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_pbeam_impl<1>(writer, nsamples), + MATCH_IBEAM_MODE(2) + MATCH_IBEAM_MODE(3) + MATCH_IBEAM_MODE(4) +#undef MATCH_IBEAM_MODE +#define MATCH_PBEAM_MODE(NBEAM) \ + } else if( std::string(format).substr(0, 7) == std::string("pbeam"#NBEAM"_") ) { \ + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_pbeam_impl(writer, nsamples), \ *obj = 0); + MATCH_PBEAM_MODE(1) +#undef MATCH_PBEAM_MODE } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_cor_impl(writer, nsamples), *obj = 0); From ec96b11f90f6407d22f74e8f8665e4c60e90b040 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 21 Dec 2020 13:46:20 -0700 Subject: [PATCH 140/424] Ugh --- src/formats/pbeam.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index 653f0b3aa..1daf7dd7f 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -65,8 +65,8 @@ class PBeamDecoder: virtual public PacketDecoder { pkt->seq = be64toh(pkt_hdr->seq) - 1; //pkt->nsrc = pkt_hdr->nserver; pkt->nsrc = _nsrc; - pkt->src = (pkt_hdr->beam - _src0) * pkt->hdr_nserver + (pkt_hdr->server - 1); - pkt->beam = pkt_hdr->beam; + pkt->src = (pkt_hdr->beam - _src0) * pkt_hdr->nserver + (pkt_hdr->server - 1); + pkt->beam = pkt_hdr->nbeam; pkt->nchan = pkt_hdr->nchan; pkt->chan0 = ntohs(pkt_hdr->chan0) - pkt->nchan * pkt->src; pkt->payload_size = pld_size; @@ -108,10 +108,9 @@ class PBeamProcessor : virtual public PacketProcessor { int beam_server = pkt->src; int nchan = pkt->nchan; - int chan, beam; + int chan; for(chan=0; chan Date: Mon, 21 Dec 2020 14:28:49 -0700 Subject: [PATCH 141/424] Ugh, part 2 --- src/packet_capture.hpp | 3 ++- src/packet_writer.hpp | 16 +++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c12c2b149..0c69851e2 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -709,6 +709,7 @@ class BFpacketcapture_ibeam_impl : public BFpacketcapture_impl { }; class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { + uint8_t _nbeam; ProcLog _type_log; ProcLog _chan_log; @@ -1125,7 +1126,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, } else if( std::string(format).substr(0, 5) == std::string("ibeam") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time - int nbeam = std::atoi((std::string(format).substr(5, 1).c_str()); + int nbeam = std::atoi((std::string(format).substr(5, 1).c_str())); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); max_payload_size = sizeof(ibeam_hdr_type) + 64*2*nbeam*nchan; } diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 38a7a0e28..f1851f491 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -272,6 +272,20 @@ class BFpacketwriter_ibeam_impl : public BFpacketwriter_impl { } }; +template +class BFpacketwriter_pbeam_impl : public BFpacketwriter_impl { + uint8_t _nbeam = B; + ProcLog _type_log; +public: + inline BFpacketwriter_pbeam_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_F32), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new PBeamHeaderFiller(); + _type_log.update("type : %s%i\n", "pbeam", _nbeam); + } +}; + class BFpacketwriter_cor_impl : public BFpacketwriter_impl { ProcLog _type_log; public: @@ -334,7 +348,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; } else if( std::string(format).substr(0, 5) == std::string("ibeam") ) { - int nbeam = std::stoi(std::string(format).stdstr(5, 1)); + int nbeam = std::stoi(std::string(format).substr(5, 1)); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); nsamples = 2*nbeam*nchan; } else if( std::string(format).substr(0, 7) == std::string("pbeam") ) { From 2816cdcb4a7d9cff759d2567f3767779e063e82b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 15:59:25 -0700 Subject: [PATCH 142/424] Added a missing io.h include. --- src/bifrost/packet_capture.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index b1002cb3e..41ac196d9 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -33,6 +33,7 @@ extern "C" { #endif +#inclue #include // Callback setup From a900f6fe8cdb53eaa23364dc8dddc26f577343b3 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 16:00:33 -0700 Subject: [PATCH 143/424] Typo. --- src/bifrost/packet_capture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 41ac196d9..f317398fc 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,7 @@ extern "C" { #endif -#inclue +#include #include // Callback setup From 8b0795cfa3a0b5aa5111e48fa3fac9e5989aa186 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 16:13:35 -0700 Subject: [PATCH 144/424] 'pbeam' is only five characters long. --- src/packet_writer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index f1851f491..88d878c87 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -351,7 +351,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, int nbeam = std::stoi(std::string(format).substr(5, 1)); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); nsamples = 2*nbeam*nchan; - } else if( std::string(format).substr(0, 7) == std::string("pbeam") ) { + } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); nsamples = 4*nchan; } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { From 3a4ad55410d5fed5ab79eed54ee6dd9ea2795bdb Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 16:46:45 -0700 Subject: [PATCH 145/424] Added missing callback setter. --- src/packet_capture.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index ca594764f..77793c1c5 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -139,6 +139,13 @@ BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetPBeam(BFpacketcapture_callback obj, + BFpacketcapture_pbeam_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_pbeam(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfPacketCaptureCallbackSetCOR(BFpacketcapture_callback obj, BFpacketcapture_cor_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); From cee6436d3869cb4dccf4705292a48c7c0e551bff Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 16:59:33 -0700 Subject: [PATCH 146/424] Typing problem. --- src/packet_capture.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 0c69851e2..30cc9adf0 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -376,7 +376,7 @@ class BFpacketcapture_callback_impl { inline void set_pbeam(BFpacketcapture_pbeam_sequence_callback callback) { _pbeam_callback = callback; } - inline BFpacketcapture_ibeam_sequence_callback get_pbeam() { + inline BFpacketcapture_pbeam_sequence_callback get_pbeam() { return _pbeam_callback; } inline void set_cor(BFpacketcapture_cor_sequence_callback callback) { From cbb51c004ae221bd156fd14e4351989afdffc97f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 17:43:43 -0700 Subject: [PATCH 147/424] Changed the callback signature for PBeam to match COR/TBN/DRX. --- src/bifrost/packet_capture.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index f317398fc..8310c2485 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -42,8 +42,8 @@ typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); -typedef int (*BFpacketcapture_pbeam_sequence_callback)(BFoffset, int, int, int, - BFoffset*, void const**, size_t*); +typedef int (*BFpacketcapture_pbeam_sequence_callback)(BFoffset, BFoffset, int, int, + int, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_vdif_sequence_callback)(BFoffset, BFoffset, int, int, int, From 446146d1d836c08faf7fe92940684463881e0924 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 28 Jan 2021 17:44:22 -0700 Subject: [PATCH 148/424] Changed the PBeam callback signature and fixed a few bits vs. bytes errors. --- src/packet_capture.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 30cc9adf0..0075fec7c 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -744,10 +744,10 @@ class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, + *time_tag, _chan0, _nchan*_nsrc/_nbeam, _nbeam, - time_tag, hdr, hdr_size); if( status != 0 ) { @@ -1121,20 +1121,20 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); - max_payload_size = sizeof(chips_hdr_type) + 32*nchan; + max_payload_size = sizeof(chips_hdr_type) + (4*nchan); } } else if( std::string(format).substr(0, 5) == std::string("ibeam") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nbeam = std::atoi((std::string(format).substr(5, 1).c_str())); int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - max_payload_size = sizeof(ibeam_hdr_type) + 64*2*nbeam*nchan; + max_payload_size = sizeof(ibeam_hdr_type) + (8*2*nbeam*nchan); } } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time - int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); - max_payload_size = sizeof(pbeam_hdr_type) + 32*4*nchan; + int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); + max_payload_size = sizeof(pbeam_hdr_type) + (4*4*nchan); } } else if(std::string(format).substr(0, 3) == std::string("cor") ) { if( backend == BF_IO_DISK ) { From 6232dd4f0d772d528bbaa256e7fd8770fde97e7f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 29 Jan 2021 09:28:31 -0700 Subject: [PATCH 149/424] Added a 'navg' field to the PBeam header and updated the callback to include this new field as an argument. --- src/bifrost/packet_capture.h | 2 +- src/formats/pbeam.hpp | 5 ++++- src/packet_capture.hpp | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 8310c2485..8a7f7692b 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -42,7 +42,7 @@ typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); -typedef int (*BFpacketcapture_pbeam_sequence_callback)(BFoffset, BFoffset, int, int, +typedef int (*BFpacketcapture_pbeam_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); typedef int (*BFpacketcapture_cor_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index 1daf7dd7f..29f1b268b 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -41,6 +41,7 @@ struct pbeam_hdr_type { uint8_t nbeam; // 2 uint8_t nserver; // 6 // Note: Big endian + uint16_t navg; // Number of raw spectra averaged uint16_t chan0; // First chan in packet uint64_t seq; // Note: 1-based }; @@ -62,7 +63,8 @@ class PBeamDecoder: virtual public PacketDecoder { const pbeam_hdr_type* pkt_hdr = (pbeam_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(pbeam_hdr_type); int pld_size = pkt_size - sizeof(pbeam_hdr_type); - pkt->seq = be64toh(pkt_hdr->seq) - 1; + pkt->decimation = be16toh(pkt_hdr->navg); + pkt->seq = (be64toh(pkt_hdr->seq) - 1) / pkt->decimation; //pkt->nsrc = pkt_hdr->nserver; pkt->nsrc = _nsrc; pkt->src = (pkt_hdr->beam - _src0) * pkt_hdr->nserver + (pkt_hdr->server - 1); @@ -148,6 +150,7 @@ class PBeamHeaderFiller : virtual public PacketHeaderFiller { header->nchan = hdr_base->nchan; header->nbeam = _nbeam; header->nserver = nserver; + header->navg = htons(hdr_base->decimation); header->chan0 = htons(hdr_base->chan0); header->seq = htobe64(hdr_base->seq); } diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 0075fec7c..535688369 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -710,6 +710,7 @@ class BFpacketcapture_ibeam_impl : public BFpacketcapture_impl { class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { uint8_t _nbeam; + uint8_t _navg; ProcLog _type_log; ProcLog _chan_log; @@ -733,18 +734,21 @@ class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { } inline bool has_sequence_changed(const PacketDesc* pkt) { return (pkt->chan0 != _chan0) \ - || (pkt->nchan != _nchan); + || (pkt->nchan != _nchan) \ + || (pkt->decimation != _navg); } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); _chan0 = pkt->chan0; _nchan = pkt->nchan; _nbeam = pkt->beam; + _navg = pkt->decimation; _payload_size = pkt->payload_size; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, *time_tag, + _navg, _chan0, _nchan*_nsrc/_nbeam, _nbeam, @@ -764,6 +768,7 @@ class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { _chan_log.update() << "chan0 : " << _chan0 << "\n" << "nchan : " << _nchan << "\n" << "nbeam : " << _nbeam << "\n" + << "navg : " << _navg << "\n" << "payload_size : " << _payload_size << "\n"; } public: From 4b26a558d34a4c363895b1273025ccf683bb3973 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 29 Jan 2021 13:06:28 -0700 Subject: [PATCH 150/424] Allow nsrc to be passed in as a tuple. --- python/bifrost/packet_capture.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 67bc942a3..b0a800dc5 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -30,6 +30,8 @@ from bifrost.libbifrost import _bf, _check, _get, BifrostObject import ctypes +from functools import reduce + class PacketCaptureCallback(BifrostObject): _ref_cache = {} @@ -66,6 +68,13 @@ def set_drx(self, fnc): self.obj, self._ref_cache['drx'])) class _CaptureBase(BifrostObject): + @staticmethod + def _flatten_value(value): + try: + value = reduce(lambda x,y: x*y, value, 1 if value else 0) + except TypeError: + pass + return value def __enter__(self): return self def __exit__(self, type, value, tb): @@ -87,6 +96,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, except AttributeError: # Python2 catch pass + nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( @@ -98,6 +108,12 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, class UDPSniffer(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass + nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( @@ -109,6 +125,12 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, class DiskReader(_CaptureBase): def __init__(self, fmt, fh, ring, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass + nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( From 387f45cb94bd9b748063820e43f08b2cffc5340d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 29 Jan 2021 13:26:08 -0700 Subject: [PATCH 151/424] Use time_tag to keep up with time and change the sequence finding method. --- src/formats/pbeam.hpp | 5 +++-- src/packet_capture.hpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index 29f1b268b..0a9b54114 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -63,8 +63,9 @@ class PBeamDecoder: virtual public PacketDecoder { const pbeam_hdr_type* pkt_hdr = (pbeam_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(pbeam_hdr_type); int pld_size = pkt_size - sizeof(pbeam_hdr_type); - pkt->decimation = be16toh(pkt_hdr->navg); - pkt->seq = (be64toh(pkt_hdr->seq) - 1) / pkt->decimation; + pkt->decimation = be16toh(pkt_hdr->navg); + pkt->time_tag = be64toh(pkt_hdr->seq); + pkt->seq = (pkt->time_tag - 1) / pkt->decimation; //pkt->nsrc = pkt_hdr->nserver; pkt->nsrc = _nsrc; pkt->src = (pkt_hdr->beam - _src0) * pkt_hdr->nserver + (pkt_hdr->server - 1); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 535688369..c144eebb2 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -720,8 +720,7 @@ class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { // TODO: Might be safer to round to nearest here, but the current firmware // always starts things ~3 seq's before the 1sec boundary anyway. //seq = round_up(pkt->seq, _slot_ntime); - //*_seq = round_nearest(pkt->seq, _slot_ntime); - _seq = round_up(pkt->seq, _slot_ntime); + _seq = round_nearest(pkt->seq, _slot_ntime); this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { @@ -739,6 +738,7 @@ class BFpacketcapture_pbeam_impl : public BFpacketcapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; _chan0 = pkt->chan0; _nchan = pkt->nchan; _nbeam = pkt->beam; From 7a7a6fe0f6e492988843971d1b9e6d1a4e3316f0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Feb 2021 10:22:21 -0700 Subject: [PATCH 152/424] Added some tests for the PBeam format. --- test/test_disk_io.py | 124 +++++++++++++++++++++++++++++++++++++++-- test/test_udp_io.py | 128 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 243 insertions(+), 9 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index bc8d4ba07..e4836736d 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -115,18 +115,61 @@ def main(self): del capture +class PBeamReader(object): + def __init__(self, sock, ring, nchan, nsrc=1): + self.sock = sock + self.ring = ring + self.nchan = nchan + self.nsrc = nsrc + def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq0': chan0*(196e6/8192), + 'bw': nchan*(196e6/8192), + 'navg': navg, + 'nbeam': nbeam, + 'npol': 4, + 'complex': False, + 'nbit': 32} + #print("******** HDR:", hdr) + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_pbeam(self.callback) + with DiskReader("pbeam_%i" % self.nchan, self.sock, self.ring, self.nsrc, 1, 240, 240, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + class AccumulateOp(object): - def __init__(self, ring, output, size): + def __init__(self, ring, output, size, dtype=np.uint8): self.ring = ring self.output = output - self.size = size + self.size = size*(dtype().nbytes) + self.dtype = dtype + + self.ring.resize(self.size*10) def main(self): for iseq in self.ring.read(guarantee=True): iseq_spans = iseq.read(self.size) while not self.ring.writing_ended(): for ispan in iseq_spans: - idata = ispan.data_view(np.uint8) + idata = ispan.data_view(self.dtype) self.output.append(idata) @@ -353,6 +396,79 @@ def test_read_drx_single(self): del oop fh.close() + def _get_pbeam_data(self): + # Setup the packet HeaderInfo + desc = HeaderInfo() + desc.set_tuning(2) + desc.set_chan0(1034) + desc.set_nchan(128) + desc.set_decimation(24) + + # Reorder as packets, beam, chan/pol + data = self.s0.reshape(128*4,1,-1) + data = data.transpose(2,1,0) + data = data.real.copy() + + # Update the number of data sources and return + desc.set_nsrc(data.shape[1]) + return desc, data + def test_write_pbeam(self): + fh = self._open('test_pbeam.dat', 'wb') + oop = DiskWriter('pbeam1_128', fh) + + # Get PBeam data + desc, data = self._get_pbeam_data() + + # Go! + oop.send(desc, 0, 24, 0, 2, data) + fh.close() + + self.assertEqual(os.path.getsize('test_pbeam.dat'), \ + (18+128*4*4)*data.shape[0]*data.shape[1]) + def test_read_pbeam(self): + # Write + fh = self._open('test_pbeam.dat', 'wb') + oop = DiskWriter('pbeam1_128', fh) + + # Get PBeam data + desc, data = self._get_pbeam_data() + + # Go! + oop.send(desc, 1, 24, 0, 1, data) + fh.close() + + # Read + fh = self._open('test_pbeam.dat', 'rb') + ring = Ring(name="capture_pbeam") + iop = PBeamReader(fh, ring, 128, nsrc=1) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.float32) + final = final.reshape(-1,128*4,1) + final = final.transpose(0,2,1).copy() + ## Reduce to match the capture block size + data = data[:(final.shape[0]//240-1)*240,...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + fh.close() + def tearDown(self): for filename in self._cache: os.unlink(filename) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index be0ac63a5..78181eb86 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -117,18 +117,58 @@ def main(self): del capture +class PBeamReader(object): + def __init__(self, sock, ring, nsrc=1): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq0': chan0*(196e6/8192), + 'bw': nchan*(196e6/8192), + 'navg': navg, + 'nbeam': nbeam, + 'npol': 4, + 'complex': False, + 'nbit': 32} + print("******** HDR:", hdr) + hdr_str = json.dumps(hdr) + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_pbeam(self.callback) + with UDPCapture("pbeam", self.sock, self.ring, self.nsrc, 1, 9000, 240, 240, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + + class AccumulateOp(object): - def __init__(self, ring, output, size): + def __init__(self, ring, output, size, dtype=np.uint8): self.ring = ring self.output = output - self.size = size + self.size = size*(dtype().nbytes) + self.dtype = dtype def main(self): for iseq in self.ring.read(guarantee=True): iseq_spans = iseq.read(self.size) while not self.ring.writing_ended(): for ispan in iseq_spans: - idata = ispan.data_view(np.uint8) + idata = ispan.data_view(self.dtype) self.output.append(idata) @@ -206,6 +246,7 @@ def test_read_tbn(self): # Compare ## Reorder to match what we sent out final = np.array(final, dtype=np.uint8) + print('tbn_final:', final.shape) final = final.reshape(-1,512,32,2) final = final.transpose(0,2,1,3).copy() final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) @@ -360,6 +401,83 @@ def test_read_drx_single(self): isock.close() osock.close() + def _get_pbeam_data(self): + # Setup the packet HeaderInfo + desc = HeaderInfo() + desc.set_tuning(1) + desc.set_chan0(345) + desc.set_nchan(128) + desc.set_decimation(24) + + # Reorder as packets, beam, chan/pol + data = self.s0.reshape(128*4,1,-1) + data = data.transpose(2,1,0) + data = data.real.copy() + + # Update the number of data sources and return + desc.set_nsrc(data.shape[1]) + return desc, data + def test_write_pbeam(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('pbeam1_128', sock) + + # Get PBeam data + desc, data = self._get_pbeam_data() + + # Go! + op.send(desc, 0, 24, 0, 1, data) + sock.close() + def test_read_pbeam(self): + # Setup the ring + ring = Ring(name="capture_pbeam") + + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('pbeam1_128', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = PBeamReader(isock, ring, nsrc=1) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get PBeam data and send it off + desc, data = self._get_pbeam_data() + for p in range(data.shape[0]): + oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) + time.sleep(1e-3) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.float32) + print("final:", final.shape) + final = final.reshape(-1,128*4,1) + final = final.transpose(0,2,1).copy() + ## Reduce to match the capture block size + data = data[:(final.shape[0]//240-1)*240,...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + isock.close() + osock.close() + def test_write_multicast(self): addr = Address('224.0.0.101', 7147) sock = UDPSocket() @@ -419,4 +537,4 @@ def test_read_multicast(self): # Clean up del oop isock.close() - osock.close() \ No newline at end of file + osock.close() From fb7db55a119ba4e5e446977ff10b848412b04c69 Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 11 Feb 2021 13:11:54 +0000 Subject: [PATCH 153/424] Fix mismerge Put UDPVerbsCapture back in after mismerging it out --- python/bifrost/packet_capture.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index b25e8b1e4..7a4ad2594 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -107,6 +107,17 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, sequence_callback.obj, core) class UDPSniffer(_CaptureBase): + def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, + buffer_ntime, slot_ntime, sequence_callback, core=None): + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpSnifferCreate, _bf.bfPacketCaptureDestroy, + fmt, sock.fileno(), ring.obj, nsrc, src0, + max_payload_size, buffer_ntime, slot_ntime, + sequence_callback.obj, core) + +class UDPVerbsCapture(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None): try: From edfe3604a5a9b5903f128aac613d780045b1ea62 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 18 Feb 2021 16:39:35 -0700 Subject: [PATCH 154/424] Grow decimation to uint32_t to fully support navg in the COR format. --- src/formats/base.hpp | 2 +- src/formats/drx.hpp | 2 +- src/formats/pbeam.hpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 8bc05fedc..64583a83b 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -70,7 +70,7 @@ struct PacketDesc { int tuning1 = 0; uint8_t beam; uint16_t gain; - uint16_t decimation; + uint32_t decimation; uint8_t valid_mode; int payload_size; const uint8_t* payload_ptr; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 9b12e9750..45c61ab91 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -150,7 +150,7 @@ class DRXHeaderFiller : virtual public PacketHeaderFiller { header->sync_word = 0x5CDEC0DE; // ID is stored in the lowest 8 bits; bit 2 is reserved header->frame_count_word = htobe32((uint32_t) (hdr_base->src & 0xBF) << 24); - header->decimation = htobe16(hdr_base->decimation); + header->decimation = htobe16((uint16_t) hdr_base->decimation); header->time_offset = 0; header->time_tag = htobe64(hdr_base->seq); header->tuning_word = htobe32(hdr_base->tuning); diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index 0a9b54114..a4a69e904 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -151,8 +151,8 @@ class PBeamHeaderFiller : virtual public PacketHeaderFiller { header->nchan = hdr_base->nchan; header->nbeam = _nbeam; header->nserver = nserver; - header->navg = htons(hdr_base->decimation); - header->chan0 = htons(hdr_base->chan0); + header->navg = htons((uint16_t) hdr_base->decimation); + header->chan0 = htons((uint16_t) hdr_base->chan0); header->seq = htobe64(hdr_base->seq); } }; From 73417bebf4a14f414620503464c1e7253ca19247 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 20 Apr 2021 08:30:39 -0600 Subject: [PATCH 155/424] Enabled IBeam1. --- src/packet_capture.hpp | 1 + src/packet_writer.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index c144eebb2..9581008fd 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1182,6 +1182,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, \ sequence_callback), \ *obj = 0); + MATCH_IBEAM_MODE(1) MATCH_IBEAM_MODE(2) MATCH_IBEAM_MODE(3) MATCH_IBEAM_MODE(4) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 88d878c87..a25551eed 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -385,6 +385,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 7) == std::string("ibeam"#NBEAM"_") ) { \ BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_ibeam_impl(writer, nsamples), \ *obj = 0); + MATCH_IBEAM_MODE(1) MATCH_IBEAM_MODE(2) MATCH_IBEAM_MODE(3) MATCH_IBEAM_MODE(4) From 72791eeed0d50671b692c4126f02e9d8d8ba2ca0 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 11 May 2021 14:00:59 +0000 Subject: [PATCH 156/424] Re-enable NUMA memory --- user.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user.mk b/user.mk index edea22fbd..27d469d71 100644 --- a/user.mk +++ b/user.mk @@ -31,7 +31,7 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #NOCUDA = 1 # Disable CUDA support #ANY_ARCH = 1 # Disable native architecture compilation #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) -#NUMA = 1 # Enable use of numa library for setting affinity of ring memory +NUMA = 1 # Enable use of numa library for setting affinity of ring memory #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) From aa70eed212195d7f436e9484d5c2626c40cc04fe Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 11 May 2021 14:22:33 +0000 Subject: [PATCH 157/424] Add back in snap2 packet callback Got lost in the wash somewhere --- python/bifrost/packet_capture.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 7a4ad2594..df7024ce9 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -42,6 +42,10 @@ def set_chips(self, fnc): self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( self.obj, self._ref_cache['chips'])) + def set_snap2(self, fnc): + self._ref_cache['snap2'] = _bf.BFpacketcapture_snap2_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetSNAP2( + self.obj, self._ref_cache['snap2'])) def set_ibeam(self, fnc): self._ref_cache['ibeam'] = _bf.BFpacketcapture_ibeam_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetIBeam( From 08f8ed869a9f3785e33f5c6d2bb038cebfc4a7c3 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 11 May 2021 17:42:31 +0000 Subject: [PATCH 158/424] Merge fix again -- helps if ibverbs actually uses ibverbs(!) --- python/bifrost/packet_capture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index df7024ce9..77b22fcc1 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -133,7 +133,7 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, if core is None: core = -1 BifrostObject.__init__( - self, _bf.bfUdpSnifferCreate, _bf.bfPacketCaptureDestroy, + self, _bf.bfUdpVerbsCaptureCreate, _bf.bfPacketCaptureDestroy, fmt, sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) From 91e57fe4caa94266092a3cc2ed946f281e8c9a0e Mon Sep 17 00:00:00 2001 From: ubuntu Date: Fri, 14 May 2021 15:47:06 +0000 Subject: [PATCH 159/424] Add some debug prints --- src/formats/snap2.hpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 23de0c387..ea3d04e55 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -64,13 +64,13 @@ struct snap2_hdr_type { class SNAP2Decoder : virtual public PacketDecoder { protected: inline bool valid_packet(const PacketDesc* pkt) const { -#if BFSNAP2_DEBUG - cout << "seq: "<< pkt->seq << endl; - cout << "src: "<< pkt->src << endl; - cout << "nsrc: "<< pkt->nsrc << endl; - cout << "nchan: "<< pkt->nchan << endl; - cout << "chan0: "<< pkt->chan0 << endl; -#endif +//#if BF_SNAP2_DEBUG +// cout << "seq: "<< pkt->seq << endl; +// cout << "src: "<< pkt->src << endl; +// cout << "nsrc: "<< pkt->nsrc << endl; +// cout << "nchan: "<< pkt->nchan << endl; +// cout << "chan0: "<< pkt->chan0 << endl; +//#endif return ( pkt->seq >= 0 && pkt->src >= 0 @@ -92,6 +92,12 @@ class SNAP2Decoder : virtual public PacketDecoder { int pld_size = pkt_size - sizeof(snap2_hdr_type); pkt->seq = be64toh(pkt_hdr->seq); pkt->time_tag = be32toh(pkt_hdr->sync_time); +#if BF_SNAP2_DEBUG + fprintf(stderr, "seq: %lu\t", pkt->seq); + fprintf(stderr, "sync_time: %lu\t", pkt->time_tag); + fprintf(stderr, "nchan: %lu\t", be16toh(pkt_hdr->nchan)); + fprintf(stderr, "npol: %lu\t", be16toh(pkt_hdr->npol)); +#endif int npol_blocks = (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); @@ -105,6 +111,15 @@ class SNAP2Decoder : virtual public PacketDecoder { pkt->src = (pkt->pol0 / pkt->npol) + be32toh(pkt_hdr->chan_block_id) * npol_blocks; pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; +#if BF_SNAP2_DEBUG + fprintf(stderr, "nsrc: %lu\t", pkt->nsrc); + fprintf(stderr, "src: %lu\t", pkt->src); + fprintf(stderr, "chan0: %lu\t", pkt->chan0); + fprintf(stderr, "chan_block_id: %lu\t", be32toh(pkt_hdr->chan_block_id)); + fprintf(stderr, "nchan_tot: %lu\t", pkt->nchan_tot); + fprintf(stderr, "npol_tot: %lu\t", pkt->npol_tot); + fprintf(stderr, "pol0: %lu\n", pkt->pol0); +#endif return this->valid_packet(pkt); } }; From 4fb0d0b7ba1d3ae5bdd744215e752007d97486ed Mon Sep 17 00:00:00 2001 From: ubuntu Date: Fri, 14 May 2021 16:02:49 +0000 Subject: [PATCH 160/424] Enable HWLOC This makes a pretty big difference at high packet RX rates --- user.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user.mk b/user.mk index 27d469d71..b2d4dbdca 100644 --- a/user.mk +++ b/user.mk @@ -32,7 +32,7 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #ANY_ARCH = 1 # Disable native architecture compilation #CUDA_DEBUG = 1 # Enable CUDA debugging (nvcc -G) NUMA = 1 # Enable use of numa library for setting affinity of ring memory -#HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture +HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture XGPU = 1 # build xGPU integrations (requires the xGPU library) VERBS = 1 # Enable use of IB verbs with udp_verbs_capture From 7aa790e17bfcd74206330ae98d12152943662dfd Mon Sep 17 00:00:00 2001 From: ubuntu Date: Wed, 19 May 2021 15:22:08 +0000 Subject: [PATCH 161/424] Allow (hopefully) buffer size and slot size to be different for SNAP2 packets --- src/packet_capture.cpp | 3 ++- src/packet_capture.hpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 0e18dde4d..115d72505 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -94,7 +94,8 @@ int PacketCaptureThread::run(uint64_t seq_beg, // If lots [TODO: what is lots] of packets are late // return. Otherwise a seq reset can lead to being stuck // here endlessly counting late packets. - if( less_than(_pkt.seq + nseq_per_obuf, seq_beg) ) { + if( less_than(_pkt.seq + 1000*nseq_per_obuf, seq_beg) ) { + fprintf(stderr, "Breaking from packet receive because of so many late packets\n"); _have_pkt = true; ret = CAPTURE_SUCCESS; break; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index ace8d2522..0314b900d 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -686,7 +686,8 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // packet isn't from the next block // TODO. Is this actually reasonable? Does it recover from upstream resyncs? bool is_new_seq = false; - if ( (_last_time_tag != pkt->time_tag) || (pkt->seq != _last_seq + _slot_ntime) ) { + if ( (_last_time_tag != pkt->time_tag) || (pkt->seq != _last_seq + _nseq_per_buf) ) { + //fprintf(stderr, "packet seq was %lu. Expected %lu + %lu\r\n", pkt->seq, _last_seq, _nseq_per_buf); is_new_seq = true; this->flush(); } From aebba8211717d9c20f176e3addfad4fbaae17541 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 20 May 2021 14:05:19 +0000 Subject: [PATCH 162/424] Tweak sequence-has-changed condition Allow two slots of loss before considering the sequence new. --- src/packet_capture.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 0314b900d..678fa9397 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -687,9 +687,13 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { // TODO. Is this actually reasonable? Does it recover from upstream resyncs? bool is_new_seq = false; if ( (_last_time_tag != pkt->time_tag) || (pkt->seq != _last_seq + _nseq_per_buf) ) { - //fprintf(stderr, "packet seq was %lu. Expected %lu + %lu\r\n", pkt->seq, _last_seq, _nseq_per_buf); - is_new_seq = true; - this->flush(); + // We could have a packet sequence number which isn't what we expect + // but is only wrong because of missing packets. Set an upper bound on + // two slots of loss + if (pkt->seq > _last_seq + 2*_slot_ntime) { + is_new_seq = true; + this->flush(); + } } _last_seq = pkt->seq; return is_new_seq; From 39d133bdb22e054e2d1750835f124616e67b3480 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 8 Jun 2021 15:42:10 +0000 Subject: [PATCH 163/424] Remove pring when trying to blank packets --- src/formats/snap2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index ea3d04e55..8d5420830 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -186,7 +186,7 @@ class SNAP2Processor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - fprintf(stderr, "TRYING TO BLANK OUT A SOURCE WITH MISSING PACKETS. BUT BLANKING NOT IMPLEMENTED\n"); + //fprintf(stderr, "TRYING TO BLANK OUT A SOURCE WITH MISSING PACKETS. BUT BLANKING NOT IMPLEMENTED\n"); //typedef aligned256_type otype; //fprintf(stderr, "You really better not be here\n"); //otype* __restrict__ aligned_data = (otype*)data; From 2f4d6dc0a5023147743351e4a42df1042df1458f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 10 Jun 2021 08:41:10 -0600 Subject: [PATCH 164/424] Extra colon. --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 892d2d4dd..bd1c46f65 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o -ifdef VERBS: +ifdef VERBS # These files require IB verbs to compile LIBBIFROST_OBJS += \ ib_verbs.o From bcbd25169bd6d9ce9b78b746530cd29dc5a49a2e Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 22 Jun 2021 19:42:50 +0000 Subject: [PATCH 165/424] Remove _timeout use (which causes segfaults?) --- src/ib_verbs.cpp | 3 ++- src/ib_verbs.hpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp index 19e2bc67b..7742e706a 100644 --- a/src/ib_verbs.cpp +++ b/src/ib_verbs.cpp @@ -545,7 +545,8 @@ int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { } } while( _verbs.pkt_batch == NULL ) { - _verbs.pkt_batch = this->receive(_timeout); + //_verbs.pkt_batch = this->receive(_timeout); + _verbs.pkt_batch = this->receive(1); _verbs.pkt = _verbs.pkt_batch; } // IBV returns Eth/UDP/IP headers. Strip them off here. diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 3e52a343d..7468b834b 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -102,7 +102,7 @@ struct bf_ibv { class Verbs : public BoundThread { int _fd; size_t _pkt_size_max; - int _timeout; + //int _timeout; bf_ibv _verbs; void get_interface_name(char* name) { @@ -238,7 +238,7 @@ class Verbs : public BoundThread { Verbs(int fd, size_t pkt_size_max, int core) : BoundThread(core), _fd(fd), _pkt_size_max(pkt_size_max) { ::memset(&_verbs, 0, sizeof(_verbs)); - _timeout = get_timeout_ms(); + //_timeout = get_timeout_ms(); create_context(); create_buffers(pkt_size_max); From 16d7710997ae84cc701960bbfcb1f3740b1a6811 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Jun 2021 15:42:44 -0600 Subject: [PATCH 166/424] Adjust the alignment because otherwise it segfaults? --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 7fa1f52c9..f1afce752 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -103,6 +103,7 @@ class Verbs : public BoundThread { int _fd; size_t _pkt_size_max; int _timeout; + int _alignment_filler; // Why is this needed? bf_ibv _verbs; void get_interface_name(char* name) { @@ -254,4 +255,3 @@ class Verbs : public BoundThread { } int recv_packet(uint8_t** pkt_ptr, int flags=0); }; - From 877dc34bcf1728b75de41bd46d30796b14e0b7a0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 24 Jun 2021 09:28:28 -0600 Subject: [PATCH 167/424] Make the decimation field int32 in the HeaderInfo setter as well. --- src/bifrost/packet_writer.h | 4 ++-- src/packet_writer.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index b600dec65..837892706 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -49,8 +49,8 @@ BFstatus bfHeaderInfoSetTuning(BFheaderinfo obj, int tuning); BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, unsigned short int gain); -BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, - unsigned short int decimation); +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + unsigned int decimation); typedef struct BFpacketwriter_impl* BFpacketwriter; diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index a3d08998c..21bcbede5 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -124,8 +124,8 @@ BFstatus bfHeaderInfoSetGain(BFheaderinfo obj, return BF_STATUS_SUCCESS; } -BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, - unsigned short int decimation) { +BFstatus bfHeaderInfoSetDecimation(BFheaderinfo obj, + unsigned int decimation) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); obj->set_decimation(decimation); return BF_STATUS_SUCCESS; From a6ed0c84a4bfab3ad24c2e09272a92a76918e105 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 24 Jun 2021 13:41:29 -0600 Subject: [PATCH 168/424] Another one. --- src/packet_writer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index a25551eed..04e4e23a2 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -183,7 +183,7 @@ class BFheaderinfo_impl { inline void set_chan0(int chan0) { _desc.chan0 = chan0; } inline void set_tuning(int tuning) { _desc.tuning = tuning; } inline void set_gain(uint16_t gain) { _desc.gain = gain; } - inline void set_decimation(uint16_t decimation) { _desc.decimation = decimation; } + inline void set_decimation(uint32_t decimation) { _desc.decimation = decimation; } }; class BFpacketwriter_impl { From 933edc161fd14e536b8b9ed8ce35154062e0fe51 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 28 Jun 2021 10:38:41 -0600 Subject: [PATCH 169/424] Cleaned up the header packing. --- src/formats/chips.hpp | 3 +-- src/formats/cor.hpp | 3 +-- src/formats/drx.hpp | 3 +-- src/formats/ibeam.hpp | 3 +-- src/formats/pbeam.hpp | 3 +-- src/formats/tbf.hpp | 3 +-- src/formats/tbn.hpp | 3 +-- src/formats/vdif.hpp | 14 ++++++-------- 8 files changed, 13 insertions(+), 22 deletions(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index a4e96dfdb..982584e16 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -32,8 +32,7 @@ //#include // SSE -#pragma pack(1) -struct chips_hdr_type { +struct __attribute__((packed)) chips_hdr_type { uint8_t roach; // Note: 1-based uint8_t gbe; // (AKA tuning) uint8_t nchan; // 109 diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 4379e27af..705c6db7d 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -31,8 +31,7 @@ #include "base.hpp" #include -#pragma pack(1) -struct cor_hdr_type { +struct __attribute__((packed)) cor_hdr_type { uint32_t sync_word; uint32_t frame_count_word; uint32_t second_count; diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 45c61ab91..10058ccf9 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -32,8 +32,7 @@ #define DRX_FRAME_SIZE 4128 -#pragma pack(1) -struct drx_hdr_type { +struct __attribute__((packed)) drx_hdr_type { uint32_t sync_word; uint32_t frame_count_word; uint32_t seconds_count; diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp index a910527b6..df81a9244 100644 --- a/src/formats/ibeam.hpp +++ b/src/formats/ibeam.hpp @@ -32,8 +32,7 @@ //#include // SSE -#pragma pack(1) -struct ibeam_hdr_type { +struct __attribute__((packed)) ibeam_hdr_type { uint8_t server; // Note: 1-based uint8_t gbe; // (AKA tuning) uint8_t nchan; // 109 diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index a4a69e904..a7dc966a7 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -32,8 +32,7 @@ //#include // SSE -#pragma pack(1) -struct pbeam_hdr_type { +struct __attribute__((packed)) pbeam_hdr_type { uint8_t server; // Note: 1-based uint8_t beam; // Note: 1-based uint8_t gbe; // (AKA tuning) diff --git a/src/formats/tbf.hpp b/src/formats/tbf.hpp index 772d68def..289eda2b4 100644 --- a/src/formats/tbf.hpp +++ b/src/formats/tbf.hpp @@ -32,8 +32,7 @@ #define TBF_FRAME_SIZE 6168 -#pragma pack(1) -struct tbf_hdr_type { +struct __attribute__((packed)) tbf_hdr_type { uint32_t sync_word; uint32_t frame_count_word; uint32_t seconds_count; diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index 93efdb7ae..4679eb123 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -32,8 +32,7 @@ #define TBN_FRAME_SIZE 1048 -#pragma pack(1) -struct tbn_hdr_type { +struct __attribute__((packed)) tbn_hdr_type { uint32_t sync_word; uint32_t frame_count_word; uint32_t tuning_word; diff --git a/src/formats/vdif.hpp b/src/formats/vdif.hpp index 4b94f8998..ef0bd8f16 100644 --- a/src/formats/vdif.hpp +++ b/src/formats/vdif.hpp @@ -30,24 +30,23 @@ #include "base.hpp" -#pragma pack(1) -struct vdif_hdr_type { - struct word_1_ { +struct __attribute__((packed)) vdif_hdr_type { + struct __attribute__((packed)) word_1_ { uint32_t seconds_from_epoch:30; uint8_t is_legacy:1; uint8_t is_invalid:1; } word_1; - struct word_2_ { + struct __attribute__((packed)) word_2_ { uint32_t frame_in_second:24; uint16_t ref_epoch:6; uint8_t unassigned:2; } word_2; - struct word_3_ { + struct __attribute__((packed)) word_3_ { uint32_t frame_length:24; uint32_t log2_nchan:5; uint8_t version:3; } word_3; - struct word_4_ { + struct __attribute__((packed)) word_4_ { uint16_t station_id:16; uint16_t thread_id:10; uint8_t bits_per_sample_minus_one:5; @@ -55,8 +54,7 @@ struct vdif_hdr_type { } word_4; }; -#pragma pack(1) -struct vdif_ext_type { +struct __attribute__((packed)) vdif_ext_type { uint32_t extended_word_1; uint32_t extended_word_2; uint32_t extended_word_3; From 8c5c52d433c255829d8de69ed5378f41d9e0c727 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 29 Jun 2021 13:15:33 +0000 Subject: [PATCH 170/424] Hack to pass through chan0 to bifrost pipeline chan0 is used internally for the channel number within a single pipeline -- i.e., it is always 0 for the first channel in a given packet stream. Rather than messing with this, use the "tuning" packet header field to pass the actual channel number to the bifrost capture callback --- src/formats/snap2.hpp | 1 + src/packet_capture.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 8d5420830..a8fc7350f 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -101,6 +101,7 @@ class SNAP2Decoder : virtual public PacketDecoder { int npol_blocks = (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); + pkt->tuning = be32toh(pkt_hdr->chan0); // Abuse this so we can use chan0 to reference channel within pipeline pkt->nsrc = npol_blocks * nchan_blocks;// _nsrc; pkt->nchan = be16toh(pkt_hdr->nchan); pkt->chan0 = be32toh(pkt_hdr->chan_block_id) * be16toh(pkt_hdr->nchan); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index be06c7f4b..a554217cd 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -710,7 +710,7 @@ class BFpacketcapture_snap2_impl : public BFpacketcapture_impl { if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, - _chan0, + pkt->tuning, // Hacked to contain chan0 _nchan, _nsrc, time_tag, From 4529e9ba2553deb088783e43c4b37f92c9bd7e05 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Jun 2021 12:53:50 -0600 Subject: [PATCH 171/424] Added a LGTM config file. --- lgtm.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 lgtm.yml diff --git a/lgtm.yml b/lgtm.yml new file mode 100644 index 000000000..b8a3dccb4 --- /dev/null +++ b/lgtm.yml @@ -0,0 +1,10 @@ +extraction: + cpp: + prepare: + packages: + - exuberant-ctags + before_index: + - export NOCUDA=1 + index: + build_command: + - make -e libbifrost From 6b2154e5dcf3be1a86088b71e39a76fa5a7fb41c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jul 2021 17:01:04 -0600 Subject: [PATCH 172/424] Major re-write of Verbs support. --- src/Makefile | 5 - src/ib_verbs.cpp | 554 ----------------------------------------- src/ib_verbs.hpp | 551 +++++++++++++++++++++++++++++++++++++--- src/packet_capture.hpp | 6 +- 4 files changed, 523 insertions(+), 593 deletions(-) delete mode 100644 src/ib_verbs.cpp diff --git a/src/Makefile b/src/Makefile index bd1c46f65..b00ea3960 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,11 +20,6 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o -ifdef VERBS - # These files require IB verbs to compile - LIBBIFROST_OBJS += \ - ib_verbs.o -endif ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ diff --git a/src/ib_verbs.cpp b/src/ib_verbs.cpp deleted file mode 100644 index 19e2bc67b..000000000 --- a/src/ib_verbs.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* - * Copyright (c) 2020, The Bifrost Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of The Bifrost Authors nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include "ib_verbs.hpp" - -void Verbs::create_context() { - int d, p, g; - int ndev, found; - ibv_device** ibv_dev_list = NULL; - ibv_context* ibv_ctx = NULL; - ibv_device_attr ibv_dev_attr; - ibv_port_attr ibv_port_attr; - union ibv_gid ibv_gid; - - // Get the interface MAC address and GID - found = 0; - uint8_t mac[6] = {0}; - this->get_mac_address(&(mac[0])); - uint64_t gid = this->get_interface_gid(); - - /* - std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; - std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) - << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; - */ - - // Find the right device - /* Query all devices */ - ibv_dev_list = ibv_get_device_list(&ndev); - check_null(ibv_dev_list, - "ibv_get_device_list"); - - /* Interogate */ - for(d=0; dfd, F_GETFL); - check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); - - // Setup the completion queues - _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); - check_null(_verbs.cq, - "allocate completion queues"); - ::memset(_verbs.cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); - ibv_exp_cq_init_attr cq_attr; - ::memset(&cq_attr, 0, sizeof(cq_attr)); - cq_attr.comp_mask = IBV_EXP_CQ_INIT_ATTR_FLAGS; - cq_attr.flags = IBV_EXP_CQ_TIMESTAMP; - for(i=0; ilkey; - } - } - - // Link the work requests to receive queue - for(i=0; iget_port()); - flow.udp.mask.dst_port = 0xffff; - - // Filter on IP address in the IPv4 header - uint32_t ip; - char ip_str[INET_ADDRSTRLEN]; - this->get_ip_address(&(ip_str[0])); - inet_pton(AF_INET, &(ip_str[0]), &ip); - std::cout << "IP is: " << ip << " (" << ip_str << ")" << std::endl; - ::memcpy(&(flow.ipv4.val.dst_ip), &ip, 4); - ::memset(&(flow.ipv4.mask.dst_ip), 0xff, 4); - - // Filter on the destination MAC address (actual or multicast) - uint8_t mac[6] = {0}; - this->get_mac_address(&(mac[0])); - if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { - ETHER_MAP_IP_MULTICAST(&ip, mac); - /* - std::cout << "Multicast MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; - */ - } - ::memcpy(&flow.eth.val.dst_mac, &mac, 6); - ::memset(&flow.eth.mask.dst_mac, 0xff, 6); - - /* - printf("size: %i\n", flow.attr.size); - printf(" attr: %i vs %lu\n", flow.attr.size, sizeof(ibv_flow_attr)); - printf(" eth: %i vs %lu\n", flow.eth.size, sizeof(ibv_flow_spec_eth)); - printf(" ipv4: %i vs %lu\n", flow.ipv4.size, sizeof(ibv_flow_spec_ipv4)); - printf(" udp: %i vs %lu\n", flow.udp.size, sizeof(ibv_flow_spec_tcp_udp)); - printf("specs: %i\n", flow.attr.num_of_specs); - - printf("type: %i (%i)\n", flow.udp.type, IBV_FLOW_SPEC_UDP); - printf("dst_port: %u\n", flow.udp.val.dst_port); - printf("dst_port: %u\n", flow.udp.mask.dst_port); - printf("src_port: %u\n", flow.udp.val.src_port); - printf("src_port: %u\n", flow.udp.mask.src_port); - - printf("dst_ip: %u\n", flow.ipv4.val.dst_ip); - printf("dst_ip: %u\n", flow.ipv4.mask.dst_ip); - printf("src_ip: %u\n", flow.ipv4.val.src_ip); - printf("src_ip: %u\n", flow.ipv4.mask.src_ip); - - ::memcpy(&(mac[0]), &(flow.eth.val.dst_mac[0]), 6); - printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.mask.dst_mac[0]), 6); - printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.val.src_mac[0]), 6); - printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.mask.src_mac[0]), 6); - printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - printf("ether_type: %u\n", flow.eth.val.ether_type); - printf("ether_type: %u\n", flow.eth.mask.ether_type); - printf("vlan_tag: %u\n", flow.eth.val.vlan_tag); - printf("vlan_tag: %u\n", flow.eth.mask.vlan_tag); - */ - - // Create the flows - _verbs.flows = (ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(ibv_flow*)); - check_null(_verbs.flows, - "allocate flows"); - ::memset(_verbs.flows, 0, BF_VERBS_NQP * sizeof(ibv_flow*)); - for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; - return ibv_post_recv(_verbs.qp[i], &recv_pkt->wr, &recv_wr_bad); -} - -bf_ibv_recv_pkt* Verbs::receive(int timeout_ms) { - int i; - int num_wce; - uint64_t wr_id; - pollfd pfd; - ibv_qp_attr qp_attr; - ibv_cq *ev_cq; - intptr_t ev_cq_ctx; - ibv_exp_wc wc[BF_VERBS_WCBATCH]; - bf_ibv_recv_pkt * recv_head = NULL; - ibv_recv_wr * recv_tail = NULL; - - // Ensure the queue pairs are in a state suitable for receiving - for(i=0; istate) { - case IBV_QPS_RESET: // Unexpected, but maybe user reset it - qp_attr.qp_state = IBV_QPS_INIT; - qp_attr.port_num = _verbs.port_num; - if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { - return NULL; - } - case IBV_QPS_INIT: - qp_attr.qp_state = IBV_QPS_RTR; - if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { - return NULL; - } - break; - case IBV_QPS_RTR: - case IBV_QPS_RTS: - break; - default: - return NULL; - } - } - - // Setup for poll - pfd.fd = _verbs.cc->fd; - pfd.events = POLLIN; - pfd.revents = 0; - - // poll completion channel's fd with given timeout - if( ::poll(&pfd, 1, timeout_ms) <= 0 ) { - // Timeout or error - return NULL; - } - - // Get the completion event - if( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) ) { - return NULL; - } - - // Ack the event - ibv_ack_cq_events(ev_cq, 1); - - // Request notification upon the next completion event - // Do NOT restrict to solicited-only completions - if( ibv_req_notify_cq(ev_cq, 0) ) { - return NULL; - } - - // Empty the CQ: poll all of the completions from the CQ (if any exist) - do { - num_wce = ibv_exp_poll_cq(ev_cq, BF_VERBS_WCBATCH, wc, sizeof(struct ibv_exp_wc)); - if( num_wce < 0 ) { - return NULL; - } - - // Loop through all work completions - for(i=0; iwr; - } else { - recv_tail->next = &(_verbs.pkt_buf[wr_id].wr); - recv_tail = recv_tail->next; - } - } // for each work completion - } while(num_wce); - - // Ensure list is NULL terminated (if we have a list) - if(recv_tail) { - recv_tail->next = NULL; - } - - return recv_head; -} - -int Verbs::recv_packet(uint8_t** pkt_ptr, int flags) { - // If we don't have a work-request queue on the go, - // get some new packets. - - if( _verbs.pkt != NULL) { - _verbs.pkt = (bf_ibv_recv_pkt *) _verbs.pkt->wr.next; - if( _verbs.pkt == NULL ) { - this->release(_verbs.pkt_batch); - _verbs.pkt_batch = NULL; - } - } - while( _verbs.pkt_batch == NULL ) { - _verbs.pkt_batch = this->receive(_timeout); - _verbs.pkt = _verbs.pkt_batch; - } - // IBV returns Eth/UDP/IP headers. Strip them off here. - *pkt_ptr = (uint8_t *)_verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; - return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; -} diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index f1afce752..51da59c8c 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -28,11 +28,10 @@ #pragma once -#include "hw_locality.hpp" - #include #include #include +#include #include #include #include @@ -44,9 +43,7 @@ #include #include -extern "C" { #include -} #ifndef BF_VERBS_NQP #define BF_VERBS_NQP 1 @@ -62,12 +59,10 @@ extern "C" { #define BF_VERBS_PAYLOAD_OFFSET 42 -extern "C" { - struct bf_ibv_recv_pkt{ ibv_recv_wr wr; + ibv_sge sg; uint32_t length; - uint64_t timestamp; }; struct bf_ibv_flow { @@ -79,13 +74,11 @@ struct bf_ibv_flow { struct bf_ibv { ibv_context* ctx; - //ibv_device_attr dev_attr; uint8_t port_num; ibv_pd* pd; ibv_comp_channel* cc; ibv_cq** cq; ibv_qp** qp; - ibv_sge* sge; ibv_flow** flows; uint8_t* mr_buf; @@ -95,15 +88,12 @@ struct bf_ibv { bf_ibv_recv_pkt* pkt_buf; bf_ibv_recv_pkt* pkt; bf_ibv_recv_pkt* pkt_batch; -} __attribute((aligned(8))); - -} // extern "C" +}; -class Verbs : public BoundThread { +class Verbs { int _fd; size_t _pkt_size_max; int _timeout; - int _alignment_filler; // Why is this needed? bf_ibv _verbs; void get_interface_name(char* name) { @@ -187,17 +177,489 @@ class Verbs : public BoundThread { ::memcpy(&id, buf, 8); return id; } - void create_context(); - void destroy_context(); - void create_buffers(size_t pkt_size_max); - void destroy_buffers(); - void create_queues(); - void destroy_queues(); - void link_work_requests(size_t pkt_size_max); - void create_flows(); - void destroy_flows(); - int release(bf_ibv_recv_pkt*); - bf_ibv_recv_pkt* receive(int timeout_ms=1); + void create_context() { + int d, p, g; + int ndev, found; + ibv_device** ibv_dev_list = NULL; + ibv_context* ibv_ctx = NULL; + ibv_device_attr ibv_dev_attr; + ibv_port_attr ibv_port_attr; + union ibv_gid ibv_gid; + + // Get the interface MAC address and GID + found = 0; + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + uint64_t gid = this->get_interface_gid(); + + /* + std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) + << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; + */ + + // Find the right device + /* Query all devices */ + ibv_dev_list = ibv_get_device_list(&ndev); + check_null(ibv_dev_list, + "ibv_get_device_list"); + + /* Interogate */ + for(d=0; dfd, F_GETFL); + check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), + "set completion channel to non-blocking"); + flags = ::fcntl(_verbs.cc->fd, F_GETFD); + check_error(::fcntl(_verbs.cc->fd, F_SETFD, flags | O_CLOEXEC), + "set completion channel to non-blocking"); + ::madvise(_verbs.cc, sizeof(ibv_pd), MADV_DONTFORK); + + // Setup the completion queues + _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); + check_null(_verbs.cq, + "allocate completion queues"); + ::memset(_verbs.cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); + for(i=0; ilkey; + } + } + + // Link the work requests to receive queue + for(i=0; iget_port()); + flow.udp.mask.dst_port = 0xffff; + + // Filter on IP address in the IPv4 header + uint32_t ip; + char ip_str[INET_ADDRSTRLEN]; + this->get_ip_address(&(ip_str[0])); + inet_pton(AF_INET, &(ip_str[0]), &ip); + std::cout << "IP is: " << ip << " (" << ip_str << ")" << std::endl; + ::memcpy(&(flow.ipv4.val.dst_ip), &ip, 4); + ::memset(&(flow.ipv4.mask.dst_ip), 0xff, 4); + + // Filter on the destination MAC address (actual or multicast) + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { + ETHER_MAP_IP_MULTICAST(&ip, mac); + /* + std::cout << "Multicast MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) + << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; + */ + } + ::memcpy(&flow.eth.val.dst_mac, &mac, 6); + ::memset(&flow.eth.mask.dst_mac, 0xff, 6); + + /* + printf("size: %i\n", flow.attr.size); + printf(" attr: %i vs %lu\n", flow.attr.size, sizeof(ibv_flow_attr)); + printf(" eth: %i vs %lu\n", flow.eth.size, sizeof(ibv_flow_spec_eth)); + printf(" ipv4: %i vs %lu\n", flow.ipv4.size, sizeof(ibv_flow_spec_ipv4)); + printf(" udp: %i vs %lu\n", flow.udp.size, sizeof(ibv_flow_spec_tcp_udp)); + printf("specs: %i\n", flow.attr.num_of_specs); + + printf("type: %i (%i)\n", flow.udp.type, IBV_FLOW_SPEC_UDP); + printf("dst_port: %u\n", flow.udp.val.dst_port); + printf("dst_port: %u\n", flow.udp.mask.dst_port); + printf("src_port: %u\n", flow.udp.val.src_port); + printf("src_port: %u\n", flow.udp.mask.src_port); + + printf("dst_ip: %u\n", flow.ipv4.val.dst_ip); + printf("dst_ip: %u\n", flow.ipv4.mask.dst_ip); + printf("src_ip: %u\n", flow.ipv4.val.src_ip); + printf("src_ip: %u\n", flow.ipv4.mask.src_ip); + + ::memcpy(&(mac[0]), &(flow.eth.val.dst_mac[0]), 6); + printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.mask.dst_mac[0]), 6); + printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.val.src_mac[0]), 6); + printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ::memcpy(&(mac[0]), &(flow.eth.mask.src_mac[0]), 6); + printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("ether_type: %u\n", flow.eth.val.ether_type); + printf("ether_type: %u\n", flow.eth.mask.ether_type); + printf("vlan_tag: %u\n", flow.eth.val.vlan_tag); + printf("vlan_tag: %u\n", flow.eth.mask.vlan_tag); + */ + + // Create the flows + _verbs.flows = (ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(ibv_flow*)); + check_null(_verbs.flows, + "allocate flows"); + ::memset(_verbs.flows, 0, BF_VERBS_NQP * sizeof(ibv_flow*)); + for(i=0; iwr.wr_id / BF_VERBS_NPKTBUF; + return ibv_post_recv(_verbs.qp[i], &recv_pkt->wr, &recv_wr_bad); + } + inline bf_ibv_recv_pkt* receive() { + int i; + int num_wce; + uint64_t wr_id; + pollfd pfd; + ibv_qp_attr qp_attr; + ibv_cq *ev_cq; + intptr_t ev_cq_ctx; + ibv_wc wc[BF_VERBS_WCBATCH]; + bf_ibv_recv_pkt * recv_head = NULL; + ibv_recv_wr * recv_tail = NULL; + + // Ensure the queue pairs are in a state suitable for receiving + for(i=0; istate) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + break; + case IBV_QPS_RTR: + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + // Setup for poll + pfd.fd = _verbs.cc->fd; + pfd.events = POLLIN; + pfd.revents = 0; + + // poll completion channel's fd with given timeout + int rc = ::poll(&pfd, 1, _timeout); + if( rc == 0) { + // Timeout + errno = EAGAIN; + throw Verbs::Error("timeout"); + } else if( rc < 0) { + // Error + throw Verbs::Error("error"); + } + + // Get the completion event + if( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) ) { + return NULL; + } + + // Ack the event + ibv_ack_cq_events(ev_cq, 1); + + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + if( ibv_req_notify_cq(ev_cq, 0) ) { + return NULL; + } + + // Empty the CQ: poll all of the completions from the CQ (if any exist) + do { + num_wce = ibv_poll_cq(ev_cq, BF_VERBS_WCBATCH, &wc[0]); + if( num_wce < 0 ) { + return NULL; + } + + // Loop through all work completions + for(i=0; iwr; + } else { + recv_tail = &(_verbs.pkt_buf[wr_id].wr); + recv_tail = recv_tail->next; + } + } // for each work completion + } while(num_wce); + + // Ensure list is NULL terminated (if we have a list) + if(recv_tail) { + recv_tail->next = NULL; + } + + return recv_head; + } inline void check_error(int retval, std::string what) { if( retval < 0 ) { destroy_flows(); @@ -236,15 +698,17 @@ class Verbs : public BoundThread { : super_t(what_arg) {} }; - Verbs(int fd, size_t pkt_size_max, int core) - : BoundThread(core), _fd(fd), _pkt_size_max(pkt_size_max) { - ::memset(&_verbs, 0, sizeof(_verbs)); + Verbs(int fd, size_t pkt_size_max) + : _fd(fd), _pkt_size_max(pkt_size_max), _timeout(1) { _timeout = get_timeout_ms(); + ::memset(&_verbs, 0, sizeof(_verbs)); + check_error(ibv_fork_init(), + "make verbs fork safe"); create_context(); - create_buffers(pkt_size_max); + create_buffers(); create_queues(); - link_work_requests(pkt_size_max); + link_work_requests(); create_flows(); } ~Verbs() { @@ -253,5 +717,30 @@ class Verbs : public BoundThread { destroy_buffers(); destroy_context(); } - int recv_packet(uint8_t** pkt_ptr, int flags=0); + inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { + // If we don't have a work-request queue on the go, + // get some new packets. + if( _verbs.pkt != NULL) { + _verbs.pkt = (bf_ibv_recv_pkt *) _verbs.pkt->wr.next; + if( _verbs.pkt == NULL ) { + this->release(_verbs.pkt_batch); + _verbs.pkt_batch = NULL; + } + } + + while( _verbs.pkt_batch == NULL ) { + try { + _verbs.pkt_batch = this->receive(); + } catch(Verbs::Error) { + _verbs.pkt = NULL; + errno = EAGAIN; + return -1; + } + _verbs.pkt = _verbs.pkt_batch; + } + + // IBV returns Eth/UDP/IP headers. Strip them off here + *pkt_ptr = (uint8_t *) _verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; + return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; + } }; diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 17f51cd39..d2b2393a0 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -289,8 +289,8 @@ class UDPPacketSniffer : public PacketCaptureMethod { class UDPVerbsReceiver : public PacketCaptureMethod { Verbs _ibv; public: - UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE, int core=-1) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max, core) {} + UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max) {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = 0; return _ibv.recv_packet(pkt_ptr, flags); @@ -1188,7 +1188,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, method = new UDPPacketSniffer(fd, max_payload_size); #if BF_VERBS_ENABLED } else if( backend == BF_IO_VERBS ) { - method = new UDPVerbsReceiver(fd, max_payload_size, core); + method = new UDPVerbsReceiver(fd, max_payload_size); #endif } else { return BF_STATUS_UNSUPPORTED; From d463a2537bae8b1c7f388fdd74cccbedc2d68def Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 13 Jul 2021 19:04:34 +0000 Subject: [PATCH 173/424] Py3 re-fixes --- tools/like_top.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/like_top.py b/tools/like_top.py index 082047424..37dc0bde0 100755 --- a/tools/like_top.py +++ b/tools/like_top.py @@ -192,7 +192,7 @@ def get_gpu_memory_usage(): pass else: # Parse the ouptut and turn everything into something useful, if possible - lines = output.decode().split('\n')[:-1] + lines = output.split('\n')[:-1] for line in lines: used, total, free, draw, limit, load = line.split(',') data['devCount'] += 1 From 55784eeeef8b0e9315b0b8b72d569cb3846d7940 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 15 Jul 2021 16:25:24 +0000 Subject: [PATCH 174/424] Remove some divergences from JD's ibverb-support branch --- python/bifrost/packet_capture.py | 10 +++++++--- src/bifrost/packet_capture.h | 13 ------------- src/ib_verbs.hpp | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 77b22fcc1..8454b0085 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -94,8 +94,7 @@ def end(self): class UDPCapture(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None, - interface='', port=-1): + buffer_ntime, slot_ntime, sequence_callback, core=None): try: fmt = fmt.encode() except AttributeError: @@ -113,6 +112,12 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, class UDPSniffer(_CaptureBase): def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass + nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( @@ -129,7 +134,6 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, except AttributeError: # Python2 catch pass - nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 0e2bf0bd7..c3e5cc34d 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -111,19 +111,6 @@ BFstatus bfUdpCaptureCreate(BFpacketcapture* obj, BFsize slot_ntime, BFpacketcapture_callback sequence_callback, int core); - -BFstatus bfIbvUdpCaptureCreate(BFpacketcapture* obj, - const char* format, - int fd, - BFring ring, - BFsize nsrc, - BFsize src0, - BFsize max_payload_size, - BFsize buffer_ntime, - BFsize slot_ntime, - BFpacketcapture_callback sequence_callback, - int core); - BFstatus bfUdpSnifferCreate(BFpacketcapture* obj, const char* format, int fd, diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index da76df4cb..51da59c8c 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -50,7 +50,7 @@ #endif #ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 32768 +#define BF_VERBS_NPKTBUF 8192 #endif #ifndef BF_VERBS_WCBATCH From e39cf99756a38c5e1b577736628c892cedd08b7d Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 15 Jul 2021 17:10:24 +0000 Subject: [PATCH 175/424] Make compiling actually work when XGPU isn't used --- src/Makefile | 3 ++- src/bifrost/bf_xgpu.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index ec1b137c1..00b3bf893 100644 --- a/src/Makefile +++ b/src/Makefile @@ -121,8 +121,9 @@ endif ifndef NOCUDA CPPFLAGS += -DBF_CUDA_ENABLED=1 - LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt -lxgpu + LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt ifdef XGPU + CPPFLAGS += -DBF_XGPU_ENABLED=1 LIB += -lxgpu endif endif diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index e06b5be61..39dbbfdb5 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -1,9 +1,11 @@ #include #include +#if BF_XGPU_ENABLED BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum); BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj); BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated); +#endif From 2e7fb1c831aed2c9d4b9e5fd869bd59c105715a5 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 15 Jul 2021 18:51:10 +0000 Subject: [PATCH 176/424] Don't use "pragma pack" Parroting JD: The pragma pack compiler directive affects all structures following the pragma. So, an innocent struct in a header file which wants to be packed can mess up other code in fun ways, depending on orders of header includes. For some reason, IB Verbs configuration seems to be easily broken by this kind of thing. Use struct __attribute__((packed)) {...} instead --- src/formats/lwa352_vbeam.hpp | 3 +-- src/formats/snap2.hpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/formats/lwa352_vbeam.hpp b/src/formats/lwa352_vbeam.hpp index 8cccef753..e7c7fe402 100644 --- a/src/formats/lwa352_vbeam.hpp +++ b/src/formats/lwa352_vbeam.hpp @@ -30,8 +30,7 @@ #include "base.hpp" -#pragma pack(1) -struct lwa352_vbeam_hdr_type { +struct __attribute__((packed)) lwa352_vbeam_hdr_type { uint64_t sync_word; uint64_t sync_time; uint64_t time_tag; diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index a8fc7350f..ea93244b3 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -38,9 +38,8 @@ #define PIPELINE_NPOL 704 #define PIPELINE_NCHAN 32 -#pragma pack(1) // All entries are network (i.e. big) endian -struct snap2_hdr_type { +struct __attribute__((packed)) snap2_hdr_type { uint64_t seq; // Spectra counter == packet counter uint32_t sync_time; // UNIX sync time uint16_t npol; // Number of pols in this packet From f46f3649fc2051e79aea0b39849d1f08c40e04d5 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 15 Jul 2021 19:28:04 +0000 Subject: [PATCH 177/424] Always include xgpu header file I'm not smart enough to make the python bindings get generated when the header entries are wrapped in #if's --- src/bifrost/bf_xgpu.h | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index 39dbbfdb5..fa9504a4b 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -1,11 +1,25 @@ +#ifndef BF_XGPU_H_INCLUDE_GUARD_ +#define BF_XGPU_H_INCLUDE_GUARD_ + #include #include -#if BF_XGPU_ENABLED +#ifdef __cplusplus +extern "C" { +#endif + +//TODO: figure out how to make ctypesgen to the right thing with python generation +//#if(BF_XGPU_ENABLED) BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum); BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj); BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated); +//#endif // BF_XGPU_ENABLED + +#ifdef __cplusplus +} // extern "C" #endif + +#endif // BF_XGPU_H_INCLUDE_GUARD From 5767a0ed99bbbe94390fef8b2ca0f8dfb0d97b23 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Thu, 15 Jul 2021 19:38:22 +0000 Subject: [PATCH 178/424] Bigger packet buffers --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 51da59c8c..da76df4cb 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -50,7 +50,7 @@ #endif #ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 8192 +#define BF_VERBS_NPKTBUF 32768 #endif #ifndef BF_VERBS_WCBATCH From fc4704b21f13e2112d64824456a6c2171e669ffa Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 20 Jul 2021 10:24:45 +0000 Subject: [PATCH 179/424] re-speedup IBV (and presumably fix a bug) Blindly copied from the now-deprecated implementation in ib_verbs.cpp --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index da76df4cb..8db58fe25 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -647,7 +647,7 @@ class Verbs { recv_head = &(_verbs.pkt_buf[wr_id]); recv_tail = &recv_head->wr; } else { - recv_tail = &(_verbs.pkt_buf[wr_id].wr); + recv_tail->next = &(_verbs.pkt_buf[wr_id].wr); recv_tail = recv_tail->next; } } // for each work completion From 15ef4d28dec7487d65c873c54d88a8cad8af6e32 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 20 Jul 2021 04:55:55 -0600 Subject: [PATCH 180/424] @realtimeradio found a missing "->next". --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 51da59c8c..e2019d559 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -647,7 +647,7 @@ class Verbs { recv_head = &(_verbs.pkt_buf[wr_id]); recv_tail = &recv_head->wr; } else { - recv_tail = &(_verbs.pkt_buf[wr_id].wr); + recv_tail->next = &(_verbs.pkt_buf[wr_id].wr); recv_tail = recv_tail->next; } } // for each work completion From b482898b7581a1a7026687fae486a014973db3e0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 20 Jul 2021 15:00:57 -0600 Subject: [PATCH 181/424] Use the upper 8 bits in the COR frame_count word to store the channel decimation value. --- src/formats/cor.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index 705c6db7d..b6b21ae6c 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,6 +62,7 @@ class CORDecoder : virtual public PacketDecoder { const cor_hdr_type* pkt_hdr = (cor_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(cor_hdr_type); int pld_size = pkt_size - sizeof(cor_hdr_type); + uint8_t chan_decim = (be32toh(pkt_hdr->frame_count_word) >> 16) & 0xFF; uint8_t nserver = (be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; uint8_t server = be32toh(pkt_hdr->frame_count_word) & 0xFF; uint16_t nchan_pkt = (pld_size/(8*4)); @@ -76,7 +77,7 @@ class CORDecoder : virtual public PacketDecoder { pkt->src = (stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0)*nserver \ + (server - 1); pkt->chan0 = be16toh(pkt_hdr->first_chan) \ - - nchan_pkt * (server - 1); + - nchan_decim*nchan_pkt * (server - 1); pkt->nchan = nchan_pkt; pkt->tuning = (nserver << 8) | (server - 1); // Stores the number of servers and // the server that sent this packet From 4347ab9ffb1c4e5ce15d01f0e0fdfa0ce8c8f24c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 20 Jul 2021 15:18:11 -0600 Subject: [PATCH 182/424] Missing 'n'. --- src/formats/cor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index b6b21ae6c..bf1660ded 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -62,7 +62,7 @@ class CORDecoder : virtual public PacketDecoder { const cor_hdr_type* pkt_hdr = (cor_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(cor_hdr_type); int pld_size = pkt_size - sizeof(cor_hdr_type); - uint8_t chan_decim = (be32toh(pkt_hdr->frame_count_word) >> 16) & 0xFF; + uint8_t nchan_decim = (be32toh(pkt_hdr->frame_count_word) >> 16) & 0xFF; uint8_t nserver = (be32toh(pkt_hdr->frame_count_word) >> 8) & 0xFF; uint8_t server = be32toh(pkt_hdr->frame_count_word) & 0xFF; uint16_t nchan_pkt = (pld_size/(8*4)); From 35a7b46ec8e3132d643293e68470fad35db69f7c Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 17 Aug 2021 15:47:15 +0000 Subject: [PATCH 183/424] Make beamformer GEMM do the right thing TODO: Is there a more sensible (less-transposey) data ordering. [Probably] --- src/cublas_beamform.cu | 62 +++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu index 4be7aedb6..ff8fe85dd 100644 --- a/src/cublas_beamform.cu +++ b/src/cublas_beamform.cu @@ -21,8 +21,8 @@ __global__ void trans_4bit_to_float(unsigned char *in, int time = blockIdx.x; int chan = blockIdx.y; int pol = TRANSPOSE_POL_BLOCK_SIZE*threadIdx.x; - unsigned char *in_off = in + time*n_chan*n_pol + chan*n_pol + pol; - float *out_off = out + 2*( chan*n_pol*n_time + pol*n_time + time); + unsigned char *in_off = in + time*n_chan*n_pol + chan*n_pol + pol; // 4+4 bit + float *out_off = out + 2*( chan*n_pol*n_time + pol*n_time + time); // 32+32 bit //long long int old_index = time*n_chan*n_pol + chan*n_pol + pol; //long long int new_index = chan*n_pol*n_time + pol*n_time + time; float real, imag; @@ -34,10 +34,11 @@ __global__ void trans_4bit_to_float(unsigned char *in, //imag = lut[in[old_index+i] & 0b1111]; //out[2*(new_index+i)] = real; //out[2*(new_index+i)+1] = imag; - real = lut[temp >> 4]; - imag = lut[temp & 255]; - *out_off++ = real; - *out_off++ = imag; + real = lut[(temp >> 4) & 0b1111]; + imag = lut[temp & 0b1111]; + out_off[0] = real; + out_off[1] = imag; + out_off += 2*n_time; } } @@ -191,7 +192,7 @@ void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int n gpuBLASchk(cublasCreate(&(context.handle))); gpuBLASchk(cublasSetStream(context.handle, context.stream)); gpuBLASchk(cublasSetPointerMode(context.handle, CUBLAS_POINTER_MODE_HOST)); - //gpuBLASchk(cublasSetPointerMode(handle, CUBLAS_POINTER_MODE_DEVICE)); + //gpuBLASchk(cublasSetPointerMode(context.handle, CUBLAS_POINTER_MODE_DEVICE)); gpuBLASchk(cublasSetMathMode(context.handle, CUBLAS_TENSOR_OP_MATH)); context.ninputs = ninputs; @@ -202,6 +203,7 @@ void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int n // Internally allocate intermediate buffers gpuErrchk( cudaMalloc(&context.in32_d, ninputs * nchans * ntimes * 2 * sizeof(float)) ); + //gpuErrchk( cudaMemcpy(context.in32_d, in32_h, ninputs * nchans * ntimes * 2 * sizeof(float), cudaMemcpyHostToDevice) ); // If the context is initialized with ntimeblocks=0, then we do no summing so don't // need the intermediate buffer allocated internally. if (ntimeblocks > 0) { @@ -244,23 +246,24 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { // A matrix: beamforming coeffs (NBEAMS * NANTS) // B matrix: data matrix (NANTS * NTIMES) + /* gpuBLASchk(cublasGemmStridedBatchedEx( context.handle, - CUBLAS_OP_N, // transpose A? - CUBLAS_OP_N, // transpose B? + CUBLAS_OP_T, // transpose A? + CUBLAS_OP_T, // transpose B? context.nbeams, // m context.ntimes, // n context.ninputs, // k - // Coeffs + // Coeffs: [nchans x] nbeams x ninputs (m x k) &alpha, // alpha weights_d, // A CUDA_C_32F, // A type - context.nbeams, // Lda + context.ninputs, // Lda context.nbeams*context.ninputs,// strideA : stride size - // Data + // Data: [nchans x] ninputs x ntimes (k x n) context.in32_d, // B CUDA_C_32F, // B type - context.ninputs, // Ldb + context.ntimes, // Ldb context.ninputs*context.ntimes,// strideB : stride size &beta, // beta // Results @@ -272,6 +275,39 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { CUDA_C_32F, // compute type CUBLAS_GEMM_DEFAULT_TENSOR_OP // algo )); + */ + + gpuBLASchk(cublasGemmStridedBatchedEx( + context.handle, + CUBLAS_OP_N, // transpose A? + CUBLAS_OP_T, // transpose B? + context.ntimes, // n + context.nbeams, // m + context.ninputs, // k + &alpha, // alpha + // + // Data: [nchans x] ninputs x ntimes (k x n) + context.in32_d, // B + CUDA_C_32F, // B type + context.ntimes, // Ldb + context.ninputs*context.ntimes,// strideB : stride size + // + // Coeffs: [nchans x] nbeams x ninputs (m x k) + weights_d, // A + CUDA_C_32F, // A type + context.nbeams, // Lda + context.nbeams*context.ninputs,// strideA : stride size + // + &beta, // beta + // Results + gem_out_d, // C + CUDA_C_32F, // Ctype + context.ntimes, // Ldc + context.nbeams*context.ntimes,// Stride C + context.nchans, // batchCount + CUDA_C_32F, // compute type + CUBLAS_GEMM_DEFAULT_TENSOR_OP // algo + )); cudaStreamSynchronize(context.stream); // Optionally: From e2b3b9701b38cf9a68a27e8fcfb1e81c67b4e0ab Mon Sep 17 00:00:00 2001 From: ubuntu Date: Tue, 17 Aug 2021 16:57:30 +0000 Subject: [PATCH 184/424] Update beamformer calls to match actual data ordering --- src/bifrost/beamform.h | 6 +++--- src/cublas_beamform.cu | 29 ++++++++++++++++++++--------- src/cublas_beamform.cuh | 2 +- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/bifrost/beamform.h b/src/bifrost/beamform.h index 7a5e4d297..8002a691a 100644 --- a/src/bifrost/beamform.h +++ b/src/bifrost/beamform.h @@ -24,7 +24,7 @@ BFstatus bfBeamformInitialize( /* * in: Pointer to ntime x nchan x ninputs x 4+4 bit data block * out: Pointer to output data. - * If ntime_blocks > 0: + * If ntime_blocks > 0: !!!!UNTESTED, probably broken!!!! * For the purposes of generating dynamic spectra, beam 2n and 2n+1 are considered * to be two pols of the same pointing, and are cross-multipled and summed over * ntimes/ntime_blocks to form the output array: @@ -35,7 +35,7 @@ BFstatus bfBeamformInitialize( * coefficients can make appropriate single-pol beam pairs). * If ntime_blocks = 0: * Data are returned as voltages, in order: - * ntimes x nchan x nbeam x complex64 beamformer block + * nchan x nbeam x ntime x complex64 beamformer block * * weights -- pointer to nbeams x nchans x ninputs x complex64 weights */ @@ -49,7 +49,7 @@ BFstatus bfBeamformRun( * Take the output of bfBeamformRun with ntime_blocks = 0, and perform transposing and integration * of data, to deliver a time integrated dual-pol dynamic spectra of the form: * nbeam/2 x ntime/ntimes_sum x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) - * I.e., the format which would be returned by bfBeamformRun is ntime_blocks > 0 + * I.e., the format which would be returned by bfBeamformRun if ntime_blocks > 0 */ BFstatus bfBeamformIntegrate( BFarray *in, diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu index ff8fe85dd..3f635eda9 100644 --- a/src/cublas_beamform.cu +++ b/src/cublas_beamform.cu @@ -45,6 +45,7 @@ __global__ void trans_4bit_to_float(unsigned char *in, // Transpose chan x beam x pol x time x 32+32 float to // beam x time[part-summed] x chan x [XX,YY,XY*_r,XY*_i] x 32 float // Each thread deals with two pols of a beam, and sums over n_time_sum time samples +// n_beam is the _output_ number of beams. I.e., the number of dual-pol beams __global__ void trans_output_and_sum(float *in, float *out, int n_chan, @@ -55,25 +56,28 @@ __global__ void trans_output_and_sum(float *in, int chan = blockIdx.x; int beam = blockIdx.y; int time = threadIdx.x; - long long int old_index = chan*n_beam*n_time*2 + beam*n_time*2 + time*n_time_sum*2; // start index for n_time/n_time_sum samples - long long int new_index = beam*(n_time / n_time_sum)*n_chan + time*n_chan + chan; - float xx=0., yy=0., xy_r=0., xy_i=0.; + // n_beam here is a dual pol beam + // input is: chan x beam x pol [2] x time x complexity + long long int old_index = 2*(chan*n_beam*2*n_time + beam*2*n_time + time*n_time_sum); // start index for n_time/n_time_sum samples + // output is: beam x time x chan x pol-products [4] + long long int new_index = 4*(beam*(n_time / n_time_sum)*n_chan + time*n_chan + chan); + float xx=0., yy=0., xy_r=0., xy_i=0.; // accumulator registers float x_r, x_i, y_r, y_i; int t; for (t=0; t Date: Tue, 17 Aug 2021 15:46:55 -0600 Subject: [PATCH 185/424] The COR packets 'navg' field has the same units as 'time_tag'. --- src/formats/cor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index bf1660ded..c7c7b0787 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -72,7 +72,7 @@ class CORDecoder : virtual public PacketDecoder { pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag); pkt->decimation = be32toh(pkt_hdr->navg); - pkt->seq = pkt->time_tag / 196000000 / (pkt->decimation / 100); + pkt->seq = pkt->time_tag / pkt->decimation; pkt->nsrc = _nsrc; pkt->src = (stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0)*nserver \ + (server - 1); From 9a6e56a7bfe3df15b82433795dbebb46a11a19f8 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Wed, 18 Aug 2021 14:55:33 +0000 Subject: [PATCH 186/424] Supply beam coeffs in chan x beam x input [C-ordered] order --- src/cublas_beamform.cu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu index 3f635eda9..7e2b7bdbb 100644 --- a/src/cublas_beamform.cu +++ b/src/cublas_beamform.cu @@ -284,7 +284,7 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { gpuBLASchk(cublasGemmStridedBatchedEx( context.handle, CUBLAS_OP_N, // transpose A? - CUBLAS_OP_T, // transpose B? + CUBLAS_OP_N, // transpose B? context.ntimes, // n context.nbeams, // m context.ninputs, // k @@ -299,7 +299,7 @@ void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { // Coeffs: [nchans x] nbeams x ninputs (m x k) weights_d, // A CUDA_C_32F, // A type - context.nbeams, // Lda + context.ninputs, // Lda context.nbeams*context.ninputs,// strideA : stride size // &beta, // beta From b9bda798896c3b779b5731f578cea38e6e608ae8 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Fri, 27 Aug 2021 12:14:55 +0000 Subject: [PATCH 187/424] Catch mmap error --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 8db58fe25..eb6f61152 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -277,7 +277,7 @@ class Verbs { _verbs.mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; _verbs.mr_buf = (uint8_t *) ::mmap(NULL, _verbs.mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - check_error(_verbs.mr_buf == MAP_FAILED, + check_error(_verbs.mr_buf == MAP_FAILED ? -1 : 0, "allocate memory region buffer"); check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), "lock memory region buffer"); From b107bfc5f6a35e6aaf8e6cbca5d380d0f358ecdf Mon Sep 17 00:00:00 2001 From: JackH Date: Thu, 18 Nov 2021 21:11:07 +0000 Subject: [PATCH 188/424] Implement source blanking. This is actually quite annoying. The call to blank a source doesn't know about the details of the packet structure, and one can't necessarily blank the right parts of the receive buffer when only given nsrc, src, nchan, chan, since these values have been abused. E.g. the output buffer is in Time x Chan x Antpol order, but the Chan dimension can be a multiple of nchan, and nsrc != the number of Antpols in the system. Hack the information out of the packet stream and then write a clurgy blanking function. Barely tested. --- src/formats/snap2.hpp | 60 ++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index ea93244b3..16140be77 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -33,11 +33,6 @@ #include // SSE #include -// TODO: parameterize somewhere. This isn't -// related to the packet formatting -#define PIPELINE_NPOL 704 -#define PIPELINE_NCHAN 32 - // All entries are network (i.e. big) endian struct __attribute__((packed)) snap2_hdr_type { uint64_t seq; // Spectra counter == packet counter @@ -63,13 +58,13 @@ struct __attribute__((packed)) snap2_hdr_type { class SNAP2Decoder : virtual public PacketDecoder { protected: inline bool valid_packet(const PacketDesc* pkt) const { -//#if BF_SNAP2_DEBUG -// cout << "seq: "<< pkt->seq << endl; -// cout << "src: "<< pkt->src << endl; -// cout << "nsrc: "<< pkt->nsrc << endl; -// cout << "nchan: "<< pkt->nchan << endl; -// cout << "chan0: "<< pkt->chan0 << endl; -//#endif +#if BF_SNAP2_DEBUG + cout << "seq: "<< pkt->seq << endl; + cout << "src: "<< pkt->src << endl; + cout << "nsrc: "<< pkt->nsrc << endl; + cout << "nchan: "<< pkt->nchan << endl; + cout << "chan0: "<< pkt->chan0 << endl; +#endif return ( pkt->seq >= 0 && pkt->src >= 0 @@ -125,8 +120,10 @@ class SNAP2Decoder : virtual public PacketDecoder { }; class SNAP2Processor : virtual public PacketProcessor { -protected: - int _pipeline_nchan = PIPELINE_NCHAN; +private: + bool _initialized = false; + int _npol_tot = 0; + int _npol_pkt = 0; public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, @@ -157,6 +154,12 @@ class SNAP2Processor : virtual public PacketProcessor { int words_per_chan_out = pkt->npol_tot >> 5; int pol_offset_out = pkt->pol0 >> 5; int pkt_chan = pkt->chan0; // The first channel in this packet + + if ( !_initialized ) { + _npol_tot = pkt->npol_tot; + _npol_pkt = pkt->npol; + _initialized = true; + } // Copy packet payload one channel at a time. // Packets have payload format nchans x npols x complexity. @@ -186,16 +189,25 @@ class SNAP2Processor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - //fprintf(stderr, "TRYING TO BLANK OUT A SOURCE WITH MISSING PACKETS. BUT BLANKING NOT IMPLEMENTED\n"); - //typedef aligned256_type otype; - //fprintf(stderr, "You really better not be here\n"); - //otype* __restrict__ aligned_data = (otype*)data; - //for( int t=0; t Time x chan_block x chan x pol_block x pol_words + // -> Time x + int chan_block_offset_bytes = chan_block * nchan * _npol_tot; + int time_offset_bytes = nchan_blocks * nchan * _npol_tot; + int pol_offset_bytes = pol_block*_npol_pkt; + //fprintf(stderr, "Offset bytes: T*%d + [chan block] %d + c*%d + [pol offset] %d\n", time_offset_bytes, chan_block_offset_bytes, _npol_tot, pol_offset_bytes); + for( int t=0; t Date: Sun, 9 Jan 2022 20:02:18 +0000 Subject: [PATCH 189/424] Revert "Implement source blanking." This reverts commit b107bfc5f6a35e6aaf8e6cbca5d380d0f358ecdf. Don't do this for now to make things faster --- src/formats/snap2.hpp | 60 +++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 16140be77..ea93244b3 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -33,6 +33,11 @@ #include // SSE #include +// TODO: parameterize somewhere. This isn't +// related to the packet formatting +#define PIPELINE_NPOL 704 +#define PIPELINE_NCHAN 32 + // All entries are network (i.e. big) endian struct __attribute__((packed)) snap2_hdr_type { uint64_t seq; // Spectra counter == packet counter @@ -58,13 +63,13 @@ struct __attribute__((packed)) snap2_hdr_type { class SNAP2Decoder : virtual public PacketDecoder { protected: inline bool valid_packet(const PacketDesc* pkt) const { -#if BF_SNAP2_DEBUG - cout << "seq: "<< pkt->seq << endl; - cout << "src: "<< pkt->src << endl; - cout << "nsrc: "<< pkt->nsrc << endl; - cout << "nchan: "<< pkt->nchan << endl; - cout << "chan0: "<< pkt->chan0 << endl; -#endif +//#if BF_SNAP2_DEBUG +// cout << "seq: "<< pkt->seq << endl; +// cout << "src: "<< pkt->src << endl; +// cout << "nsrc: "<< pkt->nsrc << endl; +// cout << "nchan: "<< pkt->nchan << endl; +// cout << "chan0: "<< pkt->chan0 << endl; +//#endif return ( pkt->seq >= 0 && pkt->src >= 0 @@ -120,10 +125,8 @@ class SNAP2Decoder : virtual public PacketDecoder { }; class SNAP2Processor : virtual public PacketProcessor { -private: - bool _initialized = false; - int _npol_tot = 0; - int _npol_pkt = 0; +protected: + int _pipeline_nchan = PIPELINE_NCHAN; public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, @@ -154,12 +157,6 @@ class SNAP2Processor : virtual public PacketProcessor { int words_per_chan_out = pkt->npol_tot >> 5; int pol_offset_out = pkt->pol0 >> 5; int pkt_chan = pkt->chan0; // The first channel in this packet - - if ( !_initialized ) { - _npol_tot = pkt->npol_tot; - _npol_pkt = pkt->npol; - _initialized = true; - } // Copy packet payload one channel at a time. // Packets have payload format nchans x npols x complexity. @@ -189,25 +186,16 @@ class SNAP2Processor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - //fprintf(stderr, "Zeroing out source %d of %d (%d chans) (%d nseq)\n", src, nsrc, nchan, nseq); - int npol_blocks = _npol_tot / _npol_pkt; - int nchan_blocks = nsrc / npol_blocks; - int chan_block = src / npol_blocks; - int pol_block = src % npol_blocks; - //fprintf(stderr, "Channel block: %d. Zeroing %d bytes\n", chan_block, _npol_pkt); - // Output buffer is Time x Chan x Pol - // -> Time x chan_block x chan x pol_block x pol_words - // -> Time x - int chan_block_offset_bytes = chan_block * nchan * _npol_tot; - int time_offset_bytes = nchan_blocks * nchan * _npol_tot; - int pol_offset_bytes = pol_block*_npol_pkt; - //fprintf(stderr, "Offset bytes: T*%d + [chan block] %d + c*%d + [pol offset] %d\n", time_offset_bytes, chan_block_offset_bytes, _npol_tot, pol_offset_bytes); - for( int t=0; t Date: Fri, 21 Jan 2022 16:47:58 +0000 Subject: [PATCH 190/424] Add option to transpose xgpu output --- src/bf_xgpu.cpp | 9 ++++++--- src/bifrost/bf_xgpu.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp index 91d55c843..5a340247d 100644 --- a/src/bf_xgpu.cpp +++ b/src/bf_xgpu.cpp @@ -131,13 +131,16 @@ BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump) { /* * Given an xGPU accumulation buffer, grab a subset of visibilities from - * and gather them in a new buffer, in order chan x visibility x complexity [int32] + * and gather them in a new buffer, in order + * chan x visibility x complexity [int32] (if transpose=0) + * or + * visibility x chan * complexity [int32] (if transpose!=0) * BFarray *in : Pointer to a BFarray with storage in device memory, where xGPU results reside * BFarray *in : Pointer to a BFarray with storage in device memory where collated visibilities should be written. * BFarray *vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. * int nchan_sum: The number of frequency channels to sum over */ -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum) { +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum, int transpose) { long long unsigned nvis = num_contiguous_elements(vismap); int xgpu_error; if (in->space != BF_SPACE_CUDA) { @@ -155,7 +158,7 @@ BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *co if (num_contiguous_elements(conj) != nvis) { return BF_STATUS_INVALID_SHAPE; } - xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, (int *)conj->data, nvis, nchan_sum); + xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, (int *)conj->data, nvis, nchan_sum, transpose); if (xgpu_error != XGPU_OK) { fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); return BF_STATUS_INTERNAL_ERROR; diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h index fa9504a4b..b8f21b783 100644 --- a/src/bifrost/bf_xgpu.h +++ b/src/bifrost/bf_xgpu.h @@ -13,7 +13,7 @@ extern "C" { BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum); +BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum, int transpose); BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj); BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated); //#endif // BF_XGPU_ENABLED From 26f91b7f2642de5217c419ac55f35e69ceec1bd6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 3 Mar 2022 13:26:16 -0700 Subject: [PATCH 191/424] Added in IB verbs support for sending packets. --- python/bifrost/packet_writer.py | 18 +- src/bifrost/packet_writer.h | 9 +- src/ib_verbs.hpp | 446 ++++++++++++++++++++++++++++---- src/packet_writer.cpp | 20 +- src/packet_writer.hpp | 190 ++++++++++++-- 5 files changed, 603 insertions(+), 80 deletions(-) diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 398caa39f..88d503e41 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -52,6 +52,8 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass + def set_rate_limit(self, rate_limit_Bps): + _check(_bf.bfPacketWriterSetRateLimit(self.obj, rate_limit_Bps)) def reset_counter(self): _check(_bf.bfPacketWriterResetCounter(self.obj)) def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): @@ -75,6 +77,20 @@ def __init__(self, fmt, sock, core=None): BifrostObject.__init__( self, _bf.bfUdpTransmitCreate, _bf.bfPacketWriterDestroy, fmt, sock.fileno(), core) + + +class UDPVerbsTransmit(_WriterBase): + def __init__(self, fmt, sock, core=None): + try: + fmt = fmt.encode() + except AttributeError: + # Python2 catch + pass + if core is None: + core = -1 + BifrostObject.__init__( + self, _bf.bfUdpVerbsTransmitCreate, _bf.bfPacketWriterDestroy, + fmt, sock.fileno(), core) class DiskWriter(_WriterBase): diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index 837892706..76614c7d1 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -62,7 +62,14 @@ BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, const char* format, int fd, int core); +BFstatus bfUdpVerbsTransmitCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core); BFstatus bfPacketWriterDestroy(BFpacketwriter obj); +BFstatus bfPacketWriterSetRateLimit(BFpacketwriter obj, + unsigned int rate_limit); +BFstatus bfPacketWriterResetRateLimit(BFpacketwriter obj); BFstatus bfPacketWriterResetCounter(BFpacketwriter obj); BFstatus bfPacketWriterSend(BFpacketwriter obj, BFheaderinfo info, diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index e2019d559..9942cba9d 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2020-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,9 +42,18 @@ #include #include #include +#include #include +// Catch for older InfiniBand verbs installs that do not have the +// IBV_RAW_PACKET_CAP_IP_CSUM feature check. +#ifndef IBV_RAW_PACKET_CAP_IP_CSUM +#define BF_ENABLE_VERBS_OFFLOAD 0 +#else +#define BF_ENABLE_VERBS_OFFLOAD 1 +#endif + #ifndef BF_VERBS_NQP #define BF_VERBS_NQP 1 #endif @@ -65,6 +74,11 @@ struct bf_ibv_recv_pkt{ uint32_t length; }; +struct bf_ibv_send_pkt{ + ibv_send_wr wr; + ibv_sge sg; +}; + struct bf_ibv_flow { ibv_flow_attr attr; ibv_flow_spec_eth eth; @@ -88,8 +102,62 @@ struct bf_ibv { bf_ibv_recv_pkt* pkt_buf; bf_ibv_recv_pkt* pkt; bf_ibv_recv_pkt* pkt_batch; + + // Send + ibv_cq** send_cq; + + uint8_t* send_mr_buf; + size_t send_mr_size; + ibv_mr* send_mr; + + bf_ibv_send_pkt* send_pkt_buf; + bf_ibv_send_pkt* send_pkt_head; + + uint8_t offload_csum; + uint8_t hardware_pacing; }; +struct __attribute__((packed)) bf_ethernet_hdr { + uint8_t dst_mac[6]; + uint8_t src_mac[6]; + uint16_t type; +}; + +struct __attribute__((packed)) bf_ipv4_hdr { + uint8_t version_ihl; + uint8_t tos; + uint16_t length; + uint16_t id; + uint16_t flags_frag; + uint8_t ttl; + uint8_t proto; + uint16_t checksum; + uint32_t src_addr; + uint32_t dst_addr; +}; + +inline void bf_ipv4_update_checksum(bf_ipv4_hdr* hdr) { + hdr->checksum = 0; + uint16_t *block = reinterpret_cast(hdr); + + uint32_t checksum = 0; + for(uint32_t i=0; i 0xFFFF ) { + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + hdr->checksum = ~htons((uint16_t) checksum); +} + +struct __attribute__((packed)) bf_udp_hdr { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +}; + + class Verbs { int _fd; size_t _pkt_size_max; @@ -142,6 +210,40 @@ class Verbs { ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); } + void get_remote_mac_address(uint8_t* mac) { + uint32_t ip; + char ip_str[INET_ADDRSTRLEN]; + this->get_remote_ip_address(&(ip_str[0])); + inet_pton(AF_INET, &(ip_str[0]), &ip); + + if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { + ETHER_MAP_IP_MULTICAST(&ip, mac); + } else { + int ret = -1; + char cmd[256] = {'\0'}; + char line[256] = {'\0'}; + char* end; + sprintf(cmd, "ping -c 1 %s", ip_str); + FILE* fp = popen(cmd, "r"); + sprintf(cmd, "ip neigh | grep %s | awk '{print $5}'", ip_str); + fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + if( strncmp(&(line[2]), ":", 1) == 0 ) { + ret = 0; + mac[0] = (uint8_t) strtol(&line[0], &end, 16); + mac[1] = (uint8_t) strtol(&line[3], &end, 16); + mac[2] = (uint8_t) strtol(&line[6], &end, 16); + mac[3] = (uint8_t) strtol(&line[9], &end, 16); + mac[4] = (uint8_t) strtol(&line[12], &end, 16); + mac[5] = (uint8_t) strtol(&line[15], &end, 16); + } + } + check_error(ret, "determine remote hardware address"); + } + } void get_ip_address(char* ip) { sockaddr_in sin; socklen_t len = sizeof(sin); @@ -149,6 +251,13 @@ class Verbs { "query socket name"); inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); } + void get_remote_ip_address(char* ip) { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + } uint16_t get_port() { sockaddr_in sin; socklen_t len = sizeof(sin); @@ -156,6 +265,20 @@ class Verbs { "query socket name"); return ntohs(sin.sin_port); } + uint16_t get_remote_port() { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + return ntohs(sin.sin_port); + } + uint8_t get_ttl() { + uint8_t ttl; + socklen_t len = sizeof(ttl); + check_error(::getsockopt(_fd, IPPROTO_IP, IP_TTL, &ttl, &len), + "determine TTL"); + return ttl; + } int get_timeout_ms() { timeval value; socklen_t size = sizeof(value); @@ -182,7 +305,7 @@ class Verbs { int ndev, found; ibv_device** ibv_dev_list = NULL; ibv_context* ibv_ctx = NULL; - ibv_device_attr ibv_dev_attr; + ibv_device_attr_ex ibv_dev_attr; ibv_port_attr ibv_port_attr; union ibv_gid ibv_gid; @@ -192,13 +315,6 @@ class Verbs { this->get_mac_address(&(mac[0])); uint64_t gid = this->get_interface_gid(); - /* - std::cout << "MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; - std::cout << "GID: " << std::hex << int(htons( gid & 0xFFFF)) << ":" << int(htons((gid >> 16) & 0xFFFF)) - << ":" << int(htons((gid >> 32) & 0xFFFF)) << ":" << int(htons((gid >> 48) & 0xFFFF)) << std::dec << std::endl; - */ - // Find the right device /* Query all devices */ ibv_dev_list = ibv_get_device_list(&ndev); @@ -211,11 +327,11 @@ class Verbs { check_null(ibv_ctx, "open device"); - check_error(ibv_query_device(ibv_ctx, &ibv_dev_attr), + check_error(ibv_query_device_ex(ibv_ctx, NULL, &ibv_dev_attr), "query device"); /* Loop through the ports on the device */ - for(p=1; p<=ibv_dev_attr.phys_port_cnt; p++) { + for(p=1; p<=ibv_dev_attr.orig_attr.phys_port_cnt; p++) { check_error(ibv_query_port(ibv_ctx, p, &ibv_port_attr), "query port"); @@ -227,8 +343,18 @@ class Verbs { /* Did we find a match? */ if( (ibv_gid.global.subnet_prefix == 0x80feUL) \ && (ibv_gid.global.interface_id == gid) ) { - found = 1; - break; + found = 1; + #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD + if( ibv_dev_attr.raw_packet_caps & IBV_RAW_PACKET_CAP_IP_CSUM ) { + _verbs.offload_csum = 1; + } else { + _verbs.offload_csum = 0; + } + #else + _verbs.offload_csum = 0; + #endif + std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; + break; } } @@ -284,6 +410,25 @@ class Verbs { _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, "register memory region"); + + // Start Send + + _verbs.send_pkt_buf = (bf_ibv_send_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); + check_null(_verbs.send_pkt_buf, + "allocate send packet buffer"); + ::memset(_verbs.send_pkt_buf, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); + _verbs.send_mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; + _verbs.send_mr_buf = (uint8_t *) ::mmap(NULL, _verbs.send_mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); + + check_error(_verbs.send_mr_buf == MAP_FAILED, + "allocate memory region buffer"); + check_error(::mlock(_verbs.send_mr_buf, _verbs.send_mr_size), + "lock memory region buffer"); + _verbs.send_mr = ibv_reg_mr(_verbs.pd, _verbs.send_mr_buf, _verbs.send_mr_size, IBV_ACCESS_LOCAL_WRITE); + check_null(_verbs.send_mr, + "register memory region"); + + // End Send } void destroy_buffers() { int failures = 0; @@ -303,6 +448,26 @@ class Verbs { free(_verbs.pkt_buf); } + // Start Send + + if( _verbs.send_mr ) { + if( ibv_dereg_mr(_verbs.send_mr) ) { + failures += 1; + } + } + + if( _verbs.send_mr_buf ) { + if( ::munmap(_verbs.send_mr_buf, _verbs.send_mr_size) ) { + failures += 1; + } + } + + if( _verbs.send_pkt_buf ) { + free(_verbs.send_pkt_buf); + } + + // End Send + if( _verbs.pd ) { if( ibv_dealloc_pd(_verbs.pd) ) { failures += 1; @@ -323,7 +488,7 @@ class Verbs { check_error(::fcntl(_verbs.cc->fd, F_SETFD, flags | O_CLOEXEC), "set completion channel to non-blocking"); ::madvise(_verbs.cc, sizeof(ibv_pd), MADV_DONTFORK); - + // Setup the completion queues _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); check_null(_verbs.cq, @@ -340,14 +505,29 @@ class Verbs { "change completion queue request notifications"); } + // Start Send + + // Setup the completion queues + _verbs.send_cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); + check_null(_verbs.send_cq, + "allocate send completion queues"); + ::memset(_verbs.send_cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); + for(i=0; ilkey; + } + } + + // Link the work requests to send queue + uint32_t send_flags = 0; + #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD + if( _verbs.offload_csum ) { + send_flags = IBV_SEND_IP_CSUM; + } + #endif + + for(i=0; iget_ip_address(&(ip_str[0])); inet_pton(AF_INET, &(ip_str[0]), &ip); - std::cout << "IP is: " << ip << " (" << ip_str << ")" << std::endl; ::memcpy(&(flow.ipv4.val.dst_ip), &ip, 4); ::memset(&(flow.ipv4.mask.dst_ip), 0xff, 4); @@ -480,47 +712,10 @@ class Verbs { this->get_mac_address(&(mac[0])); if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { ETHER_MAP_IP_MULTICAST(&ip, mac); - /* - std::cout << "Multicast MAC: " << std::hex << int(mac[0]) << ":" << int(mac[1]) << ":" << int(mac[2]) - << ":" << int(mac[3]) << ":" << int(mac[4]) << ":" << int(mac[5]) << std::dec << std::endl; - */ } ::memcpy(&flow.eth.val.dst_mac, &mac, 6); ::memset(&flow.eth.mask.dst_mac, 0xff, 6); - /* - printf("size: %i\n", flow.attr.size); - printf(" attr: %i vs %lu\n", flow.attr.size, sizeof(ibv_flow_attr)); - printf(" eth: %i vs %lu\n", flow.eth.size, sizeof(ibv_flow_spec_eth)); - printf(" ipv4: %i vs %lu\n", flow.ipv4.size, sizeof(ibv_flow_spec_ipv4)); - printf(" udp: %i vs %lu\n", flow.udp.size, sizeof(ibv_flow_spec_tcp_udp)); - printf("specs: %i\n", flow.attr.num_of_specs); - - printf("type: %i (%i)\n", flow.udp.type, IBV_FLOW_SPEC_UDP); - printf("dst_port: %u\n", flow.udp.val.dst_port); - printf("dst_port: %u\n", flow.udp.mask.dst_port); - printf("src_port: %u\n", flow.udp.val.src_port); - printf("src_port: %u\n", flow.udp.mask.src_port); - - printf("dst_ip: %u\n", flow.ipv4.val.dst_ip); - printf("dst_ip: %u\n", flow.ipv4.mask.dst_ip); - printf("src_ip: %u\n", flow.ipv4.val.src_ip); - printf("src_ip: %u\n", flow.ipv4.mask.src_ip); - - ::memcpy(&(mac[0]), &(flow.eth.val.dst_mac[0]), 6); - printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.mask.dst_mac[0]), 6); - printf("dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.val.src_mac[0]), 6); - printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - ::memcpy(&(mac[0]), &(flow.eth.mask.src_mac[0]), 6); - printf("src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - printf("ether_type: %u\n", flow.eth.val.ether_type); - printf("ether_type: %u\n", flow.eth.mask.ether_type); - printf("vlan_tag: %u\n", flow.eth.val.vlan_tag); - printf("vlan_tag: %u\n", flow.eth.mask.vlan_tag); - */ - // Create the flows _verbs.flows = (ibv_flow**) ::malloc(BF_VERBS_NQP * sizeof(ibv_flow*)); check_null(_verbs.flows, @@ -568,8 +763,8 @@ class Verbs { ibv_cq *ev_cq; intptr_t ev_cq_ctx; ibv_wc wc[BF_VERBS_WCBATCH]; - bf_ibv_recv_pkt * recv_head = NULL; - ibv_recv_wr * recv_tail = NULL; + bf_ibv_recv_pkt *recv_head = NULL; + ibv_recv_wr *recv_tail = NULL; // Ensure the queue pairs are in a state suitable for receiving for(i=0; istate) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + case IBV_QPS_RTR: + qp_attr.qp_state = IBV_QPS_RTS; + if(ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE)) { + return NULL; + } + break; + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + for(i=0; iwr.next = &(_verbs.send_pkt_head->wr); + _verbs.send_pkt_head = send_pkt; + } // for each work completion + } while(num_wce); + } + + if( npackets == 0 || !_verbs.send_pkt_head ) { + return NULL; + } + + send_head = _verbs.send_pkt_head; + send_tail = _verbs.send_pkt_head; + for(i=0; iwr.next; i++) { + send_tail = (bf_ibv_send_pkt*) send_tail->wr.next; + } + + _verbs.send_pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; + send_tail->wr.next = NULL; + + return send_head; + } inline void check_error(int retval, std::string what) { if( retval < 0 ) { destroy_flows(); @@ -743,4 +1006,73 @@ class Verbs { *pkt_ptr = (uint8_t *) _verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; } + inline void get_ethernet_header(bf_ethernet_hdr* hdr) { + uint8_t src_mac[6], dst_mac[6]; + this->get_mac_address(&(src_mac[0])); + this->get_remote_mac_address(&(dst_mac[0])); + + ::memset(hdr, 0, sizeof(bf_ethernet_hdr)); + ::memcpy(hdr->dst_mac, dst_mac, 6); + ::memcpy(hdr->src_mac, src_mac, 6); + hdr->type = htons(0x0800); // IPv4 + } + inline void get_ipv4_header(bf_ipv4_hdr* hdr, size_t udp_length=0) { + uint8_t ttl = this->get_ttl(); + uint32_t src_ip, dst_ip; + char src_ip_str[INET_ADDRSTRLEN], dst_ip_str[INET_ADDRSTRLEN]; + this->get_ip_address(&(src_ip_str[0])); + inet_pton(AF_INET, &(src_ip_str[0]), &src_ip); + this->get_remote_ip_address(&(dst_ip_str[0])); + inet_pton(AF_INET, &(dst_ip_str[0]), &dst_ip); + + ::memset(hdr, 0, sizeof(bf_ipv4_hdr)); + hdr->version_ihl = htons(0x4500); // v4 + 20-byte header + hdr->length = htons((uint16_t) (20 + 8 + udp_length)); + hdr->flags_frag = htons(1<<14); // don't fragment + hdr->ttl = ttl; + hdr->proto = 0x11; // UDP + hdr->src_addr = src_ip; + hdr->dst_addr = dst_ip; + if( !_verbs.offload_csum ) { + bf_ipv4_update_checksum(hdr); + } + } + inline void get_udp_header(bf_udp_hdr* hdr, size_t udp_length=0) { + uint16_t src_port, dst_port; + src_port = this->get_port(); + dst_port = this->get_remote_port(); + + ::memset(hdr, 0, sizeof(bf_udp_hdr)); + hdr->src_port = htons(src_port); + hdr->dst_port = htons(dst_port); + hdr->length = htons((uint16_t) (8 + udp_length)); + } + inline int sendmmsg(mmsghdr *mmsg, int npackets, int flags=0) { + int ret; + bf_ibv_send_pkt* head; + ibv_send_wr *s; + + int i; + uint32_t j; + uint64_t offset; + for(i=0; iqueue(npackets); + ret = ibv_post_send(_verbs.qp[0], &(head->wr), &s); + if( ret ) { + ret = -1; + } else { + ret = npackets; + } + return ret; + } }; diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index 21bcbede5..7e09a1140 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -145,12 +145,30 @@ BFstatus bfUdpTransmitCreate(BFpacketwriter* obj, return BFpacketwriter_create(obj, format, fd, core, BF_IO_UDP); } +BFstatus bfUdpVerbsTransmitCreate(BFpacketwriter* obj, + const char* format, + int fd, + int core) { + return BFpacketwriter_create(obj, format, fd, core, BF_IO_VERBS); +} + BFstatus bfPacketWriterDestroy(BFpacketwriter obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); delete obj; return BF_STATUS_SUCCESS; } +BFstatus bfPacketWriterSetRateLimit(BFpacketwriter obj, + uint32_t rate_limit) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->set_rate_limit(rate_limit)); +} + +BFstatus bfPacketWriterResetRateLimit(BFpacketwriter obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_TRY_RETURN(obj->reset_rate_limit()); +} + BFstatus bfPacketWriterResetCounter(BFpacketwriter obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); BF_TRY_RETURN(obj->reset_counter()); diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 04e4e23a2..ebc0d94d9 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -44,9 +44,48 @@ #include // For memcpy, memset #include +#include #include #include #include +#include +#include + +class RateLimiter { + uint32_t _rate; + uint64_t _counter; + bool _first; + std::chrono::high_resolution_clock::time_point _start; + std::chrono::high_resolution_clock::time_point _stop; +public: + RateLimiter(uint32_t rate_limit) + : _rate(rate_limit), _counter(0), _first(true) {} + inline void set_rate(uint32_t rate_limit) { _rate = rate_limit; } + inline uint32_t get_rate() { return _rate; } + inline void reset() { _first = true; _counter = 0; } + inline void begin() { + if( _first ) { + _start = std::chrono::high_resolution_clock::now(); + _first = false; + } + } + inline void end_and_wait(size_t npackets) { + if( _rate > 0 ) { + _stop = std::chrono::high_resolution_clock::now(); + _counter += npackets; + double elapsed_needed = (double) _counter / _rate; + std::chrono::duration elapsed_actual = std::chrono::duration_cast>(_stop-_start); + + double sleep_needed = elapsed_needed - elapsed_actual.count(); + if( sleep_needed > 0.001 ) { + timespec sleep; + sleep.tv_sec = (int) sleep_needed; + sleep.tv_nsec = (int) ((sleep_needed - sleep.tv_sec)*1e9); + nanosleep(&sleep, NULL); + } + } + } +}; class PacketWriterMethod { protected: @@ -89,45 +128,144 @@ class DiskPacketWriter : public PacketWriterMethod { }; class UDPPacketSender : public PacketWriterMethod { + int _last_count; + mmsghdr* _mmsg; + iovec* _iovs; public: UDPPacketSender(int fd) - : PacketWriterMethod(fd) {} + : PacketWriterMethod(fd), _last_count(0), _mmsg(NULL), _iovs(NULL) {} + ~UDPPacketSender() { + if( _mmsg ) { + free(_mmsg); + } + if( _iovs ) { + free(_iovs); + } + } ssize_t send_packets(char* hdrs, int hdr_size, char* data, int data_size, int npackets, int flags=0) { - struct mmsghdr *mmsg = NULL; - struct iovec *iovs = NULL; - mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - iovs = (struct iovec *) malloc(sizeof(struct iovec)*2*npackets); - memset(mmsg, 0, sizeof(struct mmsghdr)*npackets); + if( npackets != _last_count ) { + if( _mmsg ) { + free(_mmsg); + } + if( _iovs ) { + free(_iovs); + } + + _last_count = npackets; + _mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); + _iovs = (struct iovec *) malloc(sizeof(struct iovec)*5*npackets); + ::mlock(_mmsg, sizeof(struct mmsghdr)*npackets); + ::mlock(_iovs, sizeof(struct iovec)*5*npackets); + } + memset(_mmsg, 0, sizeof(struct mmsghdr)*npackets); for(int i=0; ireset_stats(); } + inline void set_rate_limit(uint32_t rate_limit) { _limiter.set_rate(rate_limit); } + inline uint32_t get_rate_limit() { return _limiter.get_rate(); } + inline void reset_rate_limit() { _limiter.reset(); } inline ssize_t send(char* hdrs, int hdr_size, char* datas, int data_size, int npackets) { + _limiter.begin(); ssize_t nsent = _method->send_packets(hdrs, hdr_size, datas, data_size, npackets); if( nsent == -1 ) { _stats.ninvalid += npackets; @@ -160,6 +303,7 @@ class PacketWriterThread : public BoundThread { } else { _stats.nvalid += npackets; _stats.nvalid_bytes += npackets * (hdr_size + data_size); + _limiter.end_and_wait(npackets); } return nsent; } @@ -225,6 +369,8 @@ class BFpacketwriter_impl { << "core0 : " << _writer->get_core() << "\n"; } virtual ~BFpacketwriter_impl() {} + inline void set_rate_limit(uint32_t rate_limit) { _writer->set_rate_limit(rate_limit); } + inline void reset_rate_limit() { _writer->reset_rate_limit(); } inline void reset_counter() { _framecount = 0; } BFstatus send(BFheaderinfo info, BFoffset seq, @@ -370,10 +516,14 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, method = new DiskPacketWriter(fd); } else if( backend == BF_IO_UDP ) { method = new UDPPacketSender(fd); +#if BF_VERBS_ENABLED + } else if( backend == BF_IO_VERBS ) { + method = new UDPVerbsSender(fd); +#endif } else { return BF_STATUS_UNSUPPORTED; } - PacketWriterThread* writer = new PacketWriterThread(method, core); + PacketWriterThread* writer = new PacketWriterThread(method, 0, core); if( std::string(format).substr(0, 8) == std::string("generic_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_generic_impl(writer, nsamples), From dc4c194c377b1cf517cc454cc1fd424ed1baee6d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 3 Mar 2022 13:29:38 -0700 Subject: [PATCH 192/424] Update the docs. --- user.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user.mk b/user.mk index 891c05ff5..b9fedc3c3 100644 --- a/user.mk +++ b/user.mk @@ -30,4 +30,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #NUMA = 1 # Enable use of numa library for setting affinity of ring memory #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture -#VERBS = 1 # Enable use of IB verbs with udp_verbs_capture +#VERBS = 1 # Enable use of IB verbs with udp_verbs_capture and udp_verbs_transmit From 8ed17e275a004917d2e431a484a05e43fc2e22fd Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 3 Mar 2022 13:34:38 -0700 Subject: [PATCH 193/424] Initial work on RDMA for sending rings between servers. --- python/bifrost/rdma.py | 194 +++++++++++++++++++++++++ src/Makefile | 14 +- src/bifrost/rdma.h | 64 +++++++++ src/rdma.cpp | 144 +++++++++++++++++++ src/rdma.hpp | 313 +++++++++++++++++++++++++++++++++++++++++ user.mk | 1 + 6 files changed, 728 insertions(+), 2 deletions(-) create mode 100644 python/bifrost/rdma.py create mode 100644 src/bifrost/rdma.h create mode 100644 src/rdma.cpp create mode 100644 src/rdma.hpp diff --git a/python/bifrost/rdma.py b/python/bifrost/rdma.py new file mode 100644 index 000000000..44e47aafc --- /dev/null +++ b/python/bifrost/rdma.py @@ -0,0 +1,194 @@ + +# Copyright (c) 2022, The Bifrost Authors. All rights reserved. +# Copyright (c) 2022, The University of New Mexico. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of The Bifrost Authors nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Python2 compatibility +from __future__ import absolute_import + +from bifrost.libbifrost import _bf, _check, _get, BifrostObject +from bifrost.ndarray import ndarray, asarray +from bifrost.proclog import ProcLog +import bifrost.affinity as cpu_affinity + +import time +import ctypes + +class RdmaSender(BifrostObject): + def __init__(self, sock, message_size): + BifrostObject.__init__( + self, _bf.bfRdmaCreate, _bf.bfRdmaDestroy, + sock.fileno(), message_size, 1) + def send_header(self, time_tag, header, offset_from_head): + try: + header = header.encode() + except AttributeError: + # Python2 catch + pass + header_buf = ctypes.create_string_buffer(header) + _check(_bf.bfRdmaSendHeader(self.obj, + time_tag, + len(header), + ctypes.cast(header_buf, ctypes.c_void_p), + offset_from_head)) + def send_span(self, span_data): + _check(_bf.bfRdmaSendSpan(self.obj, + asarray(span_data).as_BFarray())) + +class RdmaReceiver(BifrostObject): + def __init__(self, sock, message_size, buffer_factor=5): + BifrostObject.__init__( + self, _bf.bfRdmaCreate, _bf.bfRdmaDestroy, + sock.fileno(), message_size, 0) + self.message_size = message_size + self.buffer_factor = buffer_factor + + self.time_tag = ctypes.c_ulong(0) + self.header_size = ctypes.c_ulong(0) + self.offset_from_head = ctypes.c_ulong(0) + self.span_size = ctypes.c_ulong(0) + self.contents_bufs = [] + for i in range(self.buffer_factor): + contents_buf = ctypes.create_string_buffer(self.message_size) + self.contents_bufs.append(contents_buf) + self.index = 0 + def receive(self): + contents_buf = self.contents_bufs[self.index] + self.index += 1 + if self.index == self.buffer_factor: + self.index = 0 + + _check(_bf.bfRdmaReceive(self.obj, + ctypes.POINTER(ctypes.c_ulong)(self.time_tag), + ctypes.POINTER(ctypes.c_ulong)(self.header_size), + ctypes.POINTER(ctypes.c_ulong)(self.offset_from_head), + ctypes.POINTER(ctypes.c_ulong)(self.span_size), + ctypes.addressof(contents_buf))) + if self.header_size.value > 0: + contents = ctypes.cast(contents_buf, ctypes.c_char_p) + contents = contents.value + return self.time_tag.value, self.header_size.value, contents + else: + span_data = ndarray(shape=(self.span_size.value,), dtype='u8', buffer=ctypes.addressof(contents_buf)) + return span_data + +class RingSender(object): + def __init__(self, iring, sock, gulp_size, guarantee=True, core=-1): + self.iring = iring + self.sock = sock + self.gulp_size = gulp_size + self.guarantee = guarantee + self.core = core + + self.bind_proclog = ProcLog(type(self).__name__+"/bind") + self.in_proclog = ProcLog(type(self).__name__+"/in") + self.sequence_proclog = ProcLog(type(self).__name__+"/sequence0") + self.perf_proclog = ProcLog(type(self).__name__+"/perf") + + self.in_proclog.update( {'nring':1, 'ring0':self.iring.name}) + + def main(self): + sender = RdmaSender(self.sock, self.gulp_size) + + for iseq in self.iring.read(guarantee=self.guarantee): + ihdr = json.loads(iseq.header.tostring()) + sender.send_header(iseq.time_tag, len(ihdr), ihdr, 0) + self.sequence_proclog.update(ihdr) + + prev_time = time.time() + iseq_spans = iseq.read(self.gulp_size) + for ispan in iseq_spans: + if ispan.size < self.gulp_size: + continue + curr_time = time.time() + acquire_time = curr_time - prev_time + prev_time = curr_time + + sender.send_span(ispan) + + curr_time = time.time() + process_time = curr_time - prev_time + prev_time = curr_time + self.perf_proclog.update({'acquire_time': acquire_time, + 'reserve_time': -1, + 'process_time': process_time,}) + + +class RingReceiver(object): + def __init__(self, oring, sock, gulp_size, guarantee=True, core=-1): + self.oring = oring + self.sock = sock + self.gulp_size = gulp_size + self.guarantee = guarantee + self.core = core + + self.bind_proclog = ProcLog(type(self).__name__+"/bind") + self.out_proclog = ProcLog(type(self).__name__+"/out") + self.sequence_proclog = ProcLog(type(self).__name__+"/sequence0") + self.perf_proclog = ProcLog(type(self).__name__+"/perf") + + self.out_proclog.update( {'nring':1, 'ring0':self.oring.name}) + + def main(self): + cpu_affinity.set_core(self.core) + self.bind_proclog.update({'ncore': 1, + 'core0': cpu_affinity.get_core(),}) + + receiver = RdmaReceiver(self.sock, self.gulp_size) + + with self.oring.begin_writing() as oring: + prev_time = time.time() + data = receiver.receive() + while True: + while not isinstance(data, tuple): + data = receiver.receive() + time_tag, _, ihdr = data + self.sequence_proclog.update(ihdr) + + ohdr = ihdr.copy() + + with oring.begin_sequence(time_tag=time_tag, header=ohdr) as oseq: + while True: + data = receiver.receive() + if isinstance(data, tuple): + break + curr_time = time.time() + acquire_time = curr_time - prev_time + prev_time = curr_time + + with oseq.reserve(self.gulp_size) as ospan: + curr_time = time.time() + reserve_time = curr_time - prev_time + prev_time = curr_time + + odata[...] = data + + curr_time = time.time() + process_time = curr_time - prev_time + prev_time = curr_time + self.perf_proclog.update({'acquire_time': acquire_time, + 'reserve_time': reserve_time, + 'process_time': process_time,}) diff --git a/src/Makefile b/src/Makefile index b00ea3960..9d6f0c9a1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,6 +20,10 @@ LIBBIFROST_OBJS = \ unpack.o \ quantize.o \ proclog.o +ifdef RDMA + LIBBIFROST_OBJS += \ + rdma.o +endif ifndef NOCUDA # These files require the CUDA Toolkit to compile LIBBIFROST_OBJS += \ @@ -100,11 +104,17 @@ ifdef VMA endif ifdef VERBS - # Requires Mellanox libvma to be installed - LIB += -lvma -libverbs + # Requires Mellanox libibverbs to be installed + LIB += -libverbs CPPFLAGS += -DBF_VERBS_ENABLED=1 endif +ifdef RDMA + # Requires Mellanox libibverbs and librdmacm to be installed + LIB += -libverbs -librdmacm + CPPFLAGS += -DBF_RDMA_ENABLED=1 +endif + ifdef ALIGNMENT CPPFLAGS += -DBF_ALIGNMENT=$(ALIGNMENT) endif diff --git a/src/bifrost/rdma.h b/src/bifrost/rdma.h new file mode 100644 index 000000000..93ccc9e6c --- /dev/null +++ b/src/bifrost/rdma.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2022, The University of New Mexico. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BF_RDMA_H_INCLUDE_GUARD_ +#define BF_RDMA_H_INCLUDE_GUARD_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct BFrdma_impl* BFrdma; + +BFstatus bfRdmaCreate(BFrdma* obj, + int fd, + size_t message_size, + int is_server); +BFstatus bfRdmaDestroy(BFrdma obj); +BFstatus bfRdmaSendHeader(BFrdma obj, + BFoffset time_tag, + BFsize header_size, + const void* header, + BFoffset offset_from_head); +BFstatus bfRdmaSendSpan(BFrdma obj, + BFarray const* span); +BFstatus bfRdmaReceive(BFrdma obj, + BFoffset* time_tag, + BFsize* header_size, + BFoffset* offset_from_head, + BFsize* span_size, + void* contents); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // BF_RDMA_H_INCLUDE_GUARD_ diff --git a/src/rdma.cpp b/src/rdma.cpp new file mode 100644 index 000000000..3b26fb342 --- /dev/null +++ b/src/rdma.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2022, The University of New Mexico. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rdma.hpp" +#include "utils.hpp" + +ssize_t BFrdma_impl::send_header(BFoffset time_tag, + BFsize header_size, + const void* header, + BFoffset offset_from_head) { + BF_ASSERT(header_size <= this->max_message_size(), BF_STATUS_INVALID_SHAPE); + + bf_message msg; + msg.type = bf_message::MSG_HEADER; + msg.time_tag = time_tag; + msg.length = header_size; + msg.offset = offset_from_head; + + return _rdma->send(&msg, header); +} + +ssize_t BFrdma_impl::send_span(BFarray const* span) { + size_t span_size = BF_DTYPE_NBYTE(span->dtype); + for(int i=0; indim; i++) { + span_size *= span->shape[i]; + } + BF_ASSERT(span_size <= this->max_message_size(), BF_STATUS_INVALID_SHAPE); + + bf_message msg; + msg.type = bf_message::MSG_SPAN; + msg.time_tag = 0; + msg.length = span_size; + msg.offset = 0; + + return _rdma->send(&msg, span->data); +} + +ssize_t BFrdma_impl::receive(BFoffset* time_tag, + BFsize* header_size, + BFoffset* offset_from_head, + BFsize* span_size, + void* contents) { + bf_message msg; + ::memset(&msg, 0, sizeof(bf_message)); + ssize_t nrecv; + nrecv = _rdma->receive(&msg, contents); + if( msg.type == bf_message::MSG_HEADER) { + *time_tag = msg.time_tag; + *header_size = msg.length; + *offset_from_head = msg.offset; + *span_size = 0; + } else { + *time_tag = 0; + *header_size = 0; + *offset_from_head = 0; + *span_size = msg.length; + + } + + return nrecv; +} + +BFstatus bfRdmaCreate(BFrdma* obj, + int fd, + size_t message_size, + int is_server) { + BF_ASSERT(message_size <= BF_RDMA_MAX_MEMORY, BF_STATUS_INSUFFICIENT_STORAGE); + BF_TRY_RETURN_ELSE(*obj = new BFrdma_impl(fd, message_size, is_server), + *obj = 0); +} + +BFstatus bfRdmaDestroy(BFrdma obj) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + delete obj; + return BF_STATUS_SUCCESS; +} + +BFstatus bfRdmaSendHeader(BFrdma obj, + BFoffset time_tag, + BFsize header_size, + const void* header, + BFoffset offset_from_head) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(header, BF_STATUS_INVALID_POINTER); + ssize_t nsent; + nsent = obj->send_header(time_tag, header_size, header, offset_from_head); + if( nsent < 0 ) { + return BF_STATUS_INTERNAL_ERROR; + } + return BF_STATUS_SUCCESS; +} + +BFstatus bfRdmaSendSpan(BFrdma obj, + BFarray const* span) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + BF_ASSERT(span, BF_STATUS_INVALID_POINTER); + ssize_t nsent; + nsent = obj->send_span(span); + if( nsent < 0 ) { + return BF_STATUS_INTERNAL_ERROR; + } + return BF_STATUS_SUCCESS; +} + +BFstatus bfRdmaReceive(BFrdma obj, + BFoffset* time_tag, + BFsize* header_size, + BFoffset* offset_from_head, + BFsize* span_size, + void* contents) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + ssize_t nrecv; + nrecv = obj->receive(time_tag, header_size, offset_from_head, span_size, contents); + if( nrecv < 0 ) { + return BF_STATUS_INTERNAL_ERROR; + } + return BF_STATUS_SUCCESS; +} diff --git a/src/rdma.hpp b/src/rdma.hpp new file mode 100644 index 000000000..655afdf6a --- /dev/null +++ b/src/rdma.hpp @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2022, The University of New Mexico. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "assert.hpp" +#include + +#include // For ntohs +#include // For mlock + +#include +#include +#include +#include +#include // For posix_memalign +#include // For memcpy, memset + +#include +#include + +#ifndef BF_RDMA_MAX_MEMORY +#define BF_RDMA_MAX_MEMORY 134217728 +#endif + +struct __attribute__((aligned(8))) bf_message { + enum { + MSG_HEADER = 0, + MSG_SPAN = 1, + MSG_REPLY = 2, + } type; + uint64_t time_tag; + uint64_t offset; + uint64_t length; +}; + +struct bf_rdma { + struct rdma_cm_id* listen_id; + struct rdma_cm_id* id; + + struct rdma_addrinfo* res; + struct ibv_wc wc; + + size_t buf_size; + uint8_t* buf; + uint8_t* send_buf; + struct ibv_mr* mr; + struct ibv_mr* send_mr; +}; + +class Rdma { + int _fd; + size_t _message_size; + bool _is_server; + bf_rdma _rdma; + + void get_ip_address(char* ip) { + sockaddr_in sin; + socklen_t len = sizeof(sin); + if( _is_server ) { + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + } else { + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + } + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + } + uint16_t get_port() { + sockaddr_in sin; + socklen_t len = sizeof(sin); + if( _is_server ) { + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + } else { + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + } + return ntohs(sin.sin_port); + } + void create_connection(size_t message_size) { + struct rdma_addrinfo hints; + struct ibv_qp_init_attr init_attr; + struct ibv_qp_attr qp_attr; + + char server[INET_ADDRSTRLEN]; + char port[7]; + this->get_ip_address(&(server[0])); + snprintf(&(port[0]), 7, "%d", this->get_port()); + + ::memset(&hints, 0, sizeof(hints)); + if( _is_server ) { + hints.ai_flags = RAI_PASSIVE; + } + hints.ai_port_space = RDMA_PS_TCP; + check_error(rdma_getaddrinfo(&(server[0]), &(port[0]), &hints, &(_rdma.res)), + "query RDMA address information"); + + ::memset(&init_attr, 0, sizeof(init_attr)); + init_attr.cap.max_send_wr = init_attr.cap.max_recv_wr = 1; + init_attr.cap.max_send_sge = init_attr.cap.max_recv_sge = 1; + init_attr.cap.max_inline_data = 0; + if( !_is_server ) { + init_attr.qp_context = _rdma.id; + } + init_attr.sq_sig_all = 1; + + if( _is_server ) { + check_error(rdma_create_ep(&(_rdma.listen_id), _rdma.res, NULL, &init_attr), + "create the RDMA identifier"); + + check_error(rdma_listen(_rdma.listen_id, 0), + "listen for incoming connections"); + + check_error(rdma_get_request(_rdma.listen_id, &(_rdma.id)), + "get connection request"); + + ::memset(&qp_attr, 0, sizeof(qp_attr)); + ::memset(&init_attr, 0, sizeof(init_attr)); + check_error(ibv_query_qp(_rdma.id->qp, &qp_attr, IBV_QP_CAP, &init_attr), + "query the queue pair"); + } else { + check_error(rdma_create_ep(&(_rdma.id), _rdma.res, NULL, &init_attr), + "create the RDMA identifier"); + } + + _rdma.buf_size = message_size + sizeof(bf_message); + check_error(::posix_memalign((void**)&(_rdma.buf), 32, _rdma.buf_size), + "allocate buffer"); + check_error(::mlock(_rdma.buf, _rdma.buf_size), + "lock buffer"); + _rdma.mr = rdma_reg_msgs(_rdma.id, _rdma.buf, _rdma.buf_size); + check_null(_rdma.mr, "create memory region"); + + check_error(::posix_memalign((void**)&(_rdma.send_buf), 32, _rdma.buf_size), + "allocate send buffer"); + check_error(::mlock(_rdma.send_buf, _rdma.buf_size), + "lock send buffer"); + _rdma.send_mr = rdma_reg_msgs(_rdma.id, _rdma.send_buf, _rdma.buf_size); + check_null(_rdma.send_mr, "create send memory region"); + + if( _is_server ) { + check_error(rdma_accept(_rdma.id, NULL), + "accept incomining connections"); + } else { + check_error(rdma_connect(_rdma.id, NULL), + "connect"); + + check_error(rdma_post_recv(_rdma.id, NULL, _rdma.buf, _rdma.buf_size, _rdma.mr), + "set RDMA post receive"); + } + } + inline void close_connection() { + if( _rdma.id ) { + rdma_disconnect(_rdma.id); + } + + if( _rdma.mr ) { + rdma_dereg_mr(_rdma.mr); + } + + if( _rdma.send_mr ) { + rdma_dereg_mr(_rdma.send_mr); + } + + if( _rdma.buf ) { + ::munlock(_rdma.buf, _rdma.buf_size); + ::free(_rdma.buf); + } + + if( _rdma.send_buf ) { + ::munlock(_rdma.send_buf, _rdma.buf_size); + ::free(_rdma.send_buf); + } + + if( _rdma.id ) { + rdma_destroy_ep(_rdma.id); + } + + if( _rdma.listen_id ) { + rdma_destroy_ep(_rdma.listen_id); + } + + if( _rdma.res ) { + rdma_freeaddrinfo(_rdma.res); + } + } + inline void check_error(int retval, std::string what) { + if( retval < 0 ) { + close_connection(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw Rdma::Error(ss.str()); + } + } + inline void check_null(void* ptr, std::string what) { + if( ptr == NULL ) { + close_connection(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw Rdma::Error(ss.str()); + } + } +public: + class Error : public std::runtime_error { + typedef std::runtime_error super_t; + protected: + virtual const char* what() const throw() { + return super_t::what(); + } + public: + Error(const std::string& what_arg) + : super_t(what_arg) {} + }; + + Rdma(int fd, size_t message_size, bool is_server) + : _fd(fd), _message_size(message_size), _is_server(is_server) { + ::memset(&_rdma, 0, sizeof(_rdma)); + create_connection(message_size); + } + ~Rdma() { + close_connection(); + } + inline size_t max_message_size() { return _message_size; } + inline ssize_t send(const bf_message* msg, const void* buf) { + ::memcpy(_rdma.send_buf, msg, sizeof(bf_message)); + ::memcpy(_rdma.send_buf+sizeof(bf_message), buf, msg->length); + + check_error(rdma_post_send(_rdma.id, NULL, _rdma.send_buf, _rdma.buf_size, _rdma.send_mr, 0), + "queue send request"); + check_error(rdma_get_send_comp(_rdma.id, &(_rdma.wc)), + "get send completion"); + + bf_message *reply; + check_error(rdma_post_recv(_rdma.id, NULL, _rdma.buf, sizeof(bf_message), _rdma.mr), + "queue receive request"); + check_error(rdma_get_recv_comp(_rdma.id, &(_rdma.wc)), + "get receive completion"); + + reply = reinterpret_cast(_rdma.buf); + if( reply->type != bf_message::MSG_REPLY ) { + return -1; + } + return msg->length; + } + inline ssize_t receive(bf_message* msg, void* buf) { + check_error(rdma_get_recv_comp(_rdma.id, &(_rdma.wc)), + "get receive completion"); + + ::memcpy(msg, _rdma.buf, sizeof(bf_message)); + ::memcpy(buf, _rdma.buf+sizeof(bf_message), msg->length); + + bf_message* reply; + reply = reinterpret_cast(_rdma.send_buf); + reply->type = bf_message::MSG_REPLY; + check_error(rdma_post_send(_rdma.id, NULL, _rdma.send_buf, sizeof(bf_message), _rdma.send_mr, 0), + "queue send request"); + check_error(rdma_get_send_comp(_rdma.id, &(_rdma.wc)), + "get send completion"); + check_error(rdma_post_recv(_rdma.id, NULL, _rdma.buf, _rdma.buf_size, _rdma.mr), + "queue receive request"); + + return msg->length; + } +}; + +class BFrdma_impl { + Rdma* _rdma; + +public: + inline BFrdma_impl(int fd, size_t message_size, int is_server) { + _rdma = new Rdma(fd, message_size, is_server); + } + inline size_t max_message_size() { return _rdma->max_message_size(); } + ssize_t send_header(BFoffset time_tag, + BFsize header_size, + const void* header, + BFoffset offset_from_head); + ssize_t send_span(BFarray const* span); + ssize_t receive(BFoffset* time_tag, + BFsize* header_size, + BFoffset* offset_from_head, + BFsize* span_size, + void* contents); +}; diff --git a/user.mk b/user.mk index b9fedc3c3..c43aaa387 100644 --- a/user.mk +++ b/user.mk @@ -31,3 +31,4 @@ ALIGNMENT ?= 4096 # Memory allocation alignment #HWLOC = 1 # Enable use of hwloc library for memory binding in udp_capture #VMA = 1 # Enable use of Mellanox libvma in udp_capture #VERBS = 1 # Enable use of IB verbs with udp_verbs_capture and udp_verbs_transmit +#RDMA = 1 # Enable use of RDMA for ring sharing From 2ab86ca0c6466d9e26312c54d9c244be2f52f17f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 17:56:18 -0600 Subject: [PATCH 194/424] Various fixes. --- configure | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 12 +++- src/Makefile.in | 5 +- 3 files changed, 155 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 9b068b575..3a53b79fa 100755 --- a/configure +++ b/configure @@ -723,6 +723,8 @@ GPU_MAX_ARCH CUDA_VERSION HAVE_CUDA CUDA_HOME +HAVE_RDMA +HAVE_VERBS HAVE_VMA HAVE_HWLOC HAVE_NUMA @@ -836,6 +838,8 @@ with_ctags enable_numa enable_hwloc enable_vma +enable_verbs +enable_rdma with_cuda_home enable_cuda with_nvcc_flags @@ -1510,6 +1514,8 @@ Optional Features: --disable-numa disable numa support (default=no) --disable-hwloc disable hwloc support (default=no) --enable-vma enable vma support (default=no) + --enable-verbs enable Infiniband verbs support (default=no) + --enable-rdma enable RDMA support (default=no) --disable-cuda disable cuda support (default=no) --enable-debug enable debugging mode (default=no) --enable-trace enable tracing mode for nvprof/nvvp (default=no) @@ -19273,6 +19279,124 @@ fi fi +# +# Infiniband Verbs +# + +# Check whether --enable-verbs was given. +if test ${enable_verbs+y} +then : + enableval=$enable_verbs; enable_verbs=yes +else $as_nop + enable_verbs=no +fi + +HAVE_VERBS=0 + +if test x$enable_verbs != xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ibv_query_device in -lverbs" >&5 +printf %s "checking for ibv_query_device in -lverbs... " >&6; } +if test ${ac_cv_lib_verbs_ibv_query_device+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lverbs $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +namespace conftest { + extern "C" int ibv_query_device (); +} +int +main (void) +{ +return conftest::ibv_query_device (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO" +then : + ac_cv_lib_verbs_ibv_query_device=yes +else $as_nop + ac_cv_lib_verbs_ibv_query_device=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_verbs_ibv_query_device" >&5 +printf "%s\n" "$ac_cv_lib_verbs_ibv_query_device" >&6; } +if test "x$ac_cv_lib_verbs_ibv_query_device" = xyes +then : + HAVE_VERBS=1 + + LIBS="$LIBS -lverbs" +fi + +fi + +# +# RDMA +# + +# Check whether --enable-rdma was given. +if test ${enable_rdma+y} +then : + enableval=$enable_rdma; enable_rdma=yes +else $as_nop + enable_rdma=no +fi + +HAVE_RDMA=0 + +if test x$enable_rdma != xno +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rdma_get_devices in -lrdma" >&5 +printf %s "checking for rdma_get_devices in -lrdma... " >&6; } +if test ${ac_cv_lib_rdma_rdma_get_devices+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrdma $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +namespace conftest { + extern "C" int rdma_get_devices (); +} +int +main (void) +{ +return conftest::rdma_get_devices (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO" +then : + ac_cv_lib_rdma_rdma_get_devices=yes +else $as_nop + ac_cv_lib_rdma_rdma_get_devices=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdma_rdma_get_devices" >&5 +printf "%s\n" "$ac_cv_lib_rdma_rdma_get_devices" >&6; } +if test "x$ac_cv_lib_rdma_rdma_get_devices" = xyes +then : + HAVE_RDMA=1 + + LIBS="$LIBS -lrdmacm" +fi + +fi + # # CUDA # @@ -24761,6 +24885,24 @@ else $as_nop printf "%s\n" "$as_me: libvma: no" >&6;} fi +if test x$HAVE_VERBS = x1 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: libverbs: yes" >&5 +printf "%s\n" "$as_me: libverbs: yes" >&6;} +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: libverbs: no" >&5 +printf "%s\n" "$as_me: libverbs: no" >&6;} +fi + +if test x$HAVE_RDMA = x1 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: librdmacm: yes" >&5 +printf "%s\n" "$as_me: librdmacm: yes" >&6;} +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: librdmacm: no" >&5 +printf "%s\n" "$as_me: librdmacm: no" >&6;} +fi + if test x$HAVE_PYTHON = x1 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: python bindings: yes" >&5 diff --git a/configure.ac b/configure.ac index 401a0473d..68822eeb8 100644 --- a/configure.ac +++ b/configure.ac @@ -146,11 +146,11 @@ AS_IF([test x$enable_verbs != xno], LIBS="$LIBS -lverbs"])]) # -# RDMA connection manager +# RDMA # AC_ARG_ENABLE([rdma], - AS_HELP_STRING([--enable-rdma, + AS_HELP_STRING([--enable-rdma], [enable RDMA support (default=no)]), [enable_rdma=yes], [enable_rdma=no]) @@ -354,6 +354,14 @@ AS_IF([test x$HAVE_VMA = x1], [AC_MSG_NOTICE(libvma: yes)], [AC_MSG_NOTICE(libvma: no)]) +AS_IF([test x$HAVE_VERBS = x1], + [AC_MSG_NOTICE(libverbs: yes)], + [AC_MSG_NOTICE(libverbs: no)]) + +AS_IF([test x$HAVE_RDMA = x1], + [AC_MSG_NOTICE(librdmacm: yes)], + [AC_MSG_NOTICE(librdmacm: no)]) + AS_IF([test x$HAVE_PYTHON = x1], [AC_MSG_NOTICE(python bindings: yes)], [AC_MSG_NOTICE(python bindings: no)]) diff --git a/src/Makefile.in b/src/Makefile.in index 618102b96..95ceef166 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -17,6 +17,7 @@ PYINSTALLFLAGS ?= @PYINSTALLFLAGS@ HAVE_CXX14 ?= @HAVE_CXX14@ HAVE_RECVMSG ?= @HAVE_RECVMSG@ +HAVE_RDMA ?= @HAVE_RDMA@ HAVE_CUDA ?= @HAVE_CUDA@ @@ -43,8 +44,8 @@ ifeq ($(HAVE_RECVMSG),1) LIBBIFROST_OBJS += \ address.o \ udp_socket.o \ - udp_capture.o \ - udp_transmit.o + packet_capture.o \ + packet_writer.o endif ifeq ($(HAVE_RDMA),1) LIBBIFROST_OBJS += \ From e208e370df6be2c3179d3d427fa3fb4824fe58ea Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 18:16:43 -0600 Subject: [PATCH 195/424] Added in verbs and RDMA info. --- python/bifrost/version/__main__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/bifrost/version/__main__.py b/python/bifrost/version/__main__.py index a810664cd..874075d97 100644 --- a/python/bifrost/version/__main__.py +++ b/python/bifrost/version/__main__.py @@ -49,6 +49,8 @@ def _yes_no(value): print(" NUMA support %s" % _yes_no(BF_NUMA_ENABLED)) print(" Hardware locality support: %s" % _yes_no(BF_HWLOC_ENABLED)) print(" Mellanox messaging accelerator (VMA) support: %s" % _yes_no(BF_VMA_ENABLED)) + print(" Infiniband verbs support: %s" % _yes_no(BF_VERBS_ENABLED)) + print(" RDMA ring transport support: %s" % _yes_no(BF_RDMA_ENABLED)) print(" Logging directory: %s" % BF_PROCLOG_DIR) print(" Debugging: %s" % _yes_no(BF_DEBUG_ENABLED)) print(" CUDA support: %s" % _yes_no(BF_CUDA_ENABLED)) From 0ecd7a51474961b94371f0d58f36f6b72729a2ea Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 18:16:57 -0600 Subject: [PATCH 196/424] Python3 fixes. --- test/test_disk_io.py | 20 ++++++++++++++++---- test/test_udp_io.py | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index e4836736d..f58fe61dc 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -55,7 +55,11 @@ def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): 'complex': True, 'nbit': 8} #print "******** CFREQ:", hdr['cfreq'] - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') @@ -95,7 +99,11 @@ def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ 'complex': True, 'nbit': 4} #print "******** CFREQ:", hdr['cfreq'] - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') @@ -135,7 +143,11 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ 'complex': False, 'nbit': 32} #print("******** HDR:", hdr) - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 78181eb86..bee98bbfa 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -57,7 +57,11 @@ def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): 'complex': True, 'nbit': 8} #print "******** CFREQ:", hdr['cfreq'] - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') @@ -97,7 +101,11 @@ def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ 'complex': True, 'nbit': 4} #print "******** CFREQ:", hdr['cfreq'] - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') @@ -136,7 +144,11 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ 'complex': False, 'nbit': 32} print("******** HDR:", hdr) - hdr_str = json.dumps(hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass # TODO: Can't pad with NULL because returned as C-string #hdr_str = json.dumps(hdr).ljust(4096, '\0') #hdr_str = json.dumps(hdr).ljust(4096, ' ') From 45b5c6d2f84c8610d3c1efee5f933e9df79e29ac Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 18:39:44 -0600 Subject: [PATCH 197/424] MacOS fixes (but more are needed). --- src/formats/base.hpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 64583a83b..585e629fd 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +34,18 @@ #include // For ntohs +#if defined __APPLE__ && __APPLE__ + +#include +#define htobe16(x) OSSwapHostToBigInt16(x) +#define be16toh(x) OSSwapBigToHostInt16(x) +#define htobe32(x) OSSwapHostToBigInt32(x) +#define be32toh(x) OSSwapBigToHostInt32(x) +#define htobe64(x) OSSwapHostToBigInt64(x) +#define be64toh(x) OSSwapBigToHostInt64(x) + +#endif + #define BF_UNPACK_FACTOR 1 #define JUMBO_FRAME_SIZE 9000 From 4c982114fe8066068c2a52deac3357dc8cacd467 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 19:05:56 -0600 Subject: [PATCH 198/424] More MacOS fixes. --- src/Socket.hpp | 23 ++++++++++++++++++++++- src/packet_capture.hpp | 6 ++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Socket.hpp b/src/Socket.hpp index 31e7e611b..ea9e80cd4 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -124,10 +124,16 @@ client.send/recv_block/packet(...); #include #include #include + +#if defined __linux__ && __linux__ + //#include #include #include +#endif + + #if defined __APPLE__ && __APPLE__ #include @@ -642,6 +648,7 @@ void Socket::sniff(sockaddr_storage local_address, if( _mode != Socket::MODE_CLOSED ) { throw Socket::Error("Socket is already open"); } +#if defined __linux__ && __linux__ this->open(AF_PACKET, htons(ETH_P_IP)); // Allow binding multiple sockets to one port @@ -684,6 +691,10 @@ void Socket::sniff(sockaddr_storage local_address, // Make the socket promiscuous this->set_promiscuous(true); +#else + #warning packet sniffing is not supported on this OS + check_error(-1, "unsupported on this OS"); +#endif } // TODO: Add timeout support? Bit of a pain to implement. void Socket::connect(sockaddr_storage remote_address) { @@ -1088,6 +1099,7 @@ int Socket::interface_from_addr(sockaddr* address, return found; } void Socket::set_promiscuous(int state) { +#if defined __linux__ && __linux__ sockaddr_storage addr = this->get_local_address(); struct ifreq ethreq; @@ -1114,9 +1126,13 @@ void Socket::set_promiscuous(int state) { check_error(ioctl(_fd, SIOCSIFFLAGS, ðreq), "change interface setup"); } - +#else + #warning promiscuous network interfaces are not supported on this OS + check_error(-1, "unsupported on this OS"); +#endif } int Socket::get_promiscuous() { +#if defined __linux__ && __linux__ sockaddr_storage addr = this->get_local_address(); struct ifreq ethreq; @@ -1137,6 +1153,11 @@ int Socket::get_promiscuous() { } else { return false; } +#else + #warning promiscuous network interfaces are not supported on this OS + check_error(-1, "unsupported on this OS"); + return false; +#endif } #if __cplusplus >= 201103L diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 253a2ca49..8f54dc82f 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -55,6 +55,12 @@ using bifrost::ring::WriteSequence; #include #include +#if defined __APPLE__ && __APPLE__ + +#define lseek64 lseek + +#endif + #ifndef BF_HWLOC_ENABLED #define BF_HWLOC_ENABLED 0 //#define BF_HWLOC_ENABLED 1 From e5767756b79281c87caf959de2e3517a42a9470e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 22 Mar 2022 19:54:05 -0600 Subject: [PATCH 199/424] Add in Socket.hpp to clear the last few problems on MacOS. --- src/packet_capture.hpp | 1 + src/packet_writer.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 8f54dc82f..d74a9997b 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -37,6 +37,7 @@ using bifrost::ring::RingWriter; using bifrost::ring::WriteSpan; using bifrost::ring::WriteSequence; #include "proclog.hpp" +#include "Socket.hpp" #include "formats/formats.hpp" #include "hw_locality.hpp" diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 15acb6373..f64eed5ad 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -30,6 +30,7 @@ #include #include #include "proclog.hpp" +#include "Socket.hpp" #include "formats/formats.hpp" #include "utils.hpp" #include "hw_locality.hpp" From c326768465981823be379b08a5352c9994482a28 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 23 Mar 2022 10:47:39 -0600 Subject: [PATCH 200/424] Move the RDMA buffer size control into configure and config.h. --- configure.ac | 9 +++++++++ src/bifrost/config.h.in | 1 + src/rdma.cpp | 2 +- src/rdma.hpp | 5 +---- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 68822eeb8..cb594257f 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,15 @@ AS_IF([test x$enable_rdma != xno], [AC_SUBST([HAVE_RDMA], [1]) LIBS="$LIBS -lrdmacm"])]) +AC_ARG_WITH([rdma_max_mem], + AS_HELP_STRING([--with-rdma-max-mem=N], + [maximum RDMA buffer size in bytes (default=134217728)]), + [], + [with_rdma_max_mem=134217728]) +AC_SUBST([RDMA_MAXMEM], [$with_rdma_max_mem]) +AS_IF([test x$HAVE_RDMA = x0], + [AC_SUBST([RDMA_MAXMEM], [0])]) + # # CUDA # diff --git a/src/bifrost/config.h.in b/src/bifrost/config.h.in index 1ffd99528..b70a49a52 100644 --- a/src/bifrost/config.h.in +++ b/src/bifrost/config.h.in @@ -57,6 +57,7 @@ extern "C" { #define BF_VMA_ENABLED @HAVE_VMA@ #define BF_VERBS_ENABLED @HAVE_VERBS@ #define BF_RDMA_ENABLED @HAVE_RDMA@ +#define BF_RDMA_MAXMEM @RDMA_MAXMEM@ // Debugging features #define BF_DEBUG_ENABLED @HAVE_DEBUG@ diff --git a/src/rdma.cpp b/src/rdma.cpp index 3b26fb342..102c693ae 100644 --- a/src/rdma.cpp +++ b/src/rdma.cpp @@ -90,7 +90,7 @@ BFstatus bfRdmaCreate(BFrdma* obj, int fd, size_t message_size, int is_server) { - BF_ASSERT(message_size <= BF_RDMA_MAX_MEMORY, BF_STATUS_INSUFFICIENT_STORAGE); + BF_ASSERT(message_size <= BF_RDMA_MAXMEM, BF_STATUS_INSUFFICIENT_STORAGE); BF_TRY_RETURN_ELSE(*obj = new BFrdma_impl(fd, message_size, is_server), *obj = 0); } diff --git a/src/rdma.hpp b/src/rdma.hpp index 655afdf6a..9c2819ca3 100644 --- a/src/rdma.hpp +++ b/src/rdma.hpp @@ -28,6 +28,7 @@ */ #include "assert.hpp" +#include #include #include // For ntohs @@ -43,10 +44,6 @@ #include #include -#ifndef BF_RDMA_MAX_MEMORY -#define BF_RDMA_MAX_MEMORY 134217728 -#endif - struct __attribute__((aligned(8))) bf_message { enum { MSG_HEADER = 0, From 1ae5f6e0b31d2f3de66ba9b24634d6a16cf0044a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 23 Mar 2022 10:48:24 -0600 Subject: [PATCH 201/424] Rebuild configure. --- configure | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/configure b/configure index 3a53b79fa..19abe2c48 100755 --- a/configure +++ b/configure @@ -723,6 +723,7 @@ GPU_MAX_ARCH CUDA_VERSION HAVE_CUDA CUDA_HOME +RDMA_MAXMEM HAVE_RDMA HAVE_VERBS HAVE_VMA @@ -840,6 +841,7 @@ enable_hwloc enable_vma enable_verbs enable_rdma +with_rdma_max_mem with_cuda_home enable_cuda with_nvcc_flags @@ -1546,6 +1548,8 @@ Optional Packages: --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-ctags=[PATH] absolute path to ctags executable + --with-rdma-max-mem=N maximum RDMA buffer size in bytes + (default=134217728) --with-cuda-home CUDA install path (default=/usr/local/cuda) --with-nvcc-flags flags to pass to NVCC (default='-O3 -Xcompiler "-Wall"') @@ -19397,6 +19401,23 @@ fi fi + +# Check whether --with-rdma_max_mem was given. +if test ${with_rdma_max_mem+y} +then : + withval=$with_rdma_max_mem; +else $as_nop + with_rdma_max_mem=134217728 +fi + +RDMA_MAXMEM=$with_rdma_max_mem + +if test x$HAVE_RDMA = x0 +then : + RDMA_MAXMEM=0 + +fi + # # CUDA # From e768e2ea0aaadf7a250c9d98d127d00791ebe9f8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 24 Mar 2022 21:14:44 -0600 Subject: [PATCH 202/424] Is this the answer? --- src/Socket.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Socket.hpp b/src/Socket.hpp index ea9e80cd4..b16b1e297 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. + * Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -137,6 +137,7 @@ client.send/recv_block/packet(...); #if defined __APPLE__ && __APPLE__ #include +#include #include #define SOCK_NONBLOCK O_NONBLOCK @@ -609,7 +610,7 @@ void Socket::bind(sockaddr_storage local_address, // ... and work accordingly if( !multicast ) { // Normal address - check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), + check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(struct sockaddr)), "bind socket"); if( _type == SOCK_STREAM ) { check_error(::listen(_fd, max_conn_queue), From 7cc53ecc2de2610aa7a6beb3598c0e70b1d5a52b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 24 Mar 2022 21:18:11 -0600 Subject: [PATCH 203/424] Removing debugging. --- test/test_udp_io.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index bee98bbfa..2f677d29a 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -143,7 +143,7 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ 'npol': 4, 'complex': False, 'nbit': 32} - print("******** HDR:", hdr) + #print("******** HDR:", hdr) try: hdr_str = json.dumps(hdr).encode() except AttributeError: @@ -258,7 +258,6 @@ def test_read_tbn(self): # Compare ## Reorder to match what we sent out final = np.array(final, dtype=np.uint8) - print('tbn_final:', final.shape) final = final.reshape(-1,512,32,2) final = final.transpose(0,2,1,3).copy() final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) @@ -477,7 +476,6 @@ def test_read_pbeam(self): # Compare ## Reorder to match what we sent out final = np.array(final, dtype=np.float32) - print("final:", final.shape) final = final.reshape(-1,128*4,1) final = final.transpose(0,2,1).copy() ## Reduce to match the capture block size From 12a6d7a764d41f47d8c934b336b426e5bd7b9249 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 11:29:51 -0600 Subject: [PATCH 204/424] Fix library names in configure. --- configure | 38 +++++++++++++++++++------------------- configure.ac | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/configure b/configure index c38069fd8..91bc65f0d 100755 --- a/configure +++ b/configure @@ -19303,14 +19303,14 @@ HAVE_VERBS=0 if test x$enable_verbs != xno then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ibv_query_device in -lverbs" >&5 -printf %s "checking for ibv_query_device in -lverbs... " >&6; } -if test ${ac_cv_lib_verbs_ibv_query_device+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ibv_query_device in -libverbs" >&5 +printf %s "checking for ibv_query_device in -libverbs... " >&6; } +if test ${ac_cv_lib_ibverbs_ibv_query_device+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS -LIBS="-lverbs $LIBS" +LIBS="-libverbs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19327,21 +19327,21 @@ return conftest::ibv_query_device (); _ACEOF if ac_fn_cxx_try_link "$LINENO" then : - ac_cv_lib_verbs_ibv_query_device=yes + ac_cv_lib_ibverbs_ibv_query_device=yes else $as_nop - ac_cv_lib_verbs_ibv_query_device=no + ac_cv_lib_ibverbs_ibv_query_device=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_verbs_ibv_query_device" >&5 -printf "%s\n" "$ac_cv_lib_verbs_ibv_query_device" >&6; } -if test "x$ac_cv_lib_verbs_ibv_query_device" = xyes +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ibverbs_ibv_query_device" >&5 +printf "%s\n" "$ac_cv_lib_ibverbs_ibv_query_device" >&6; } +if test "x$ac_cv_lib_ibverbs_ibv_query_device" = xyes then : HAVE_VERBS=1 - LIBS="$LIBS -lverbs" + LIBS="$LIBS -libverbs" fi fi @@ -19362,14 +19362,14 @@ HAVE_RDMA=0 if test x$enable_rdma != xno then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rdma_get_devices in -lrdma" >&5 -printf %s "checking for rdma_get_devices in -lrdma... " >&6; } -if test ${ac_cv_lib_rdma_rdma_get_devices+y} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rdma_get_devices in -lrdmacm" >&5 +printf %s "checking for rdma_get_devices in -lrdmacm... " >&6; } +if test ${ac_cv_lib_rdmacm_rdma_get_devices+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS -LIBS="-lrdma $LIBS" +LIBS="-lrdmacm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19386,17 +19386,17 @@ return conftest::rdma_get_devices (); _ACEOF if ac_fn_cxx_try_link "$LINENO" then : - ac_cv_lib_rdma_rdma_get_devices=yes + ac_cv_lib_rdmacm_rdma_get_devices=yes else $as_nop - ac_cv_lib_rdma_rdma_get_devices=no + ac_cv_lib_rdmacm_rdma_get_devices=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdma_rdma_get_devices" >&5 -printf "%s\n" "$ac_cv_lib_rdma_rdma_get_devices" >&6; } -if test "x$ac_cv_lib_rdma_rdma_get_devices" = xyes +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rdmacm_rdma_get_devices" >&5 +printf "%s\n" "$ac_cv_lib_rdmacm_rdma_get_devices" >&6; } +if test "x$ac_cv_lib_rdmacm_rdma_get_devices" = xyes then : HAVE_RDMA=1 diff --git a/configure.ac b/configure.ac index ffc95f4dd..c51d966ed 100644 --- a/configure.ac +++ b/configure.ac @@ -141,9 +141,9 @@ AC_ARG_ENABLE([verbs], [enable_verbs=no]) AC_SUBST([HAVE_VERBS], [0]) AS_IF([test x$enable_verbs != xno], - [AC_CHECK_LIB([verbs], [ibv_query_device], + [AC_CHECK_LIB([ibverbs], [ibv_query_device], [AC_SUBST([HAVE_VERBS], [1]) - LIBS="$LIBS -lverbs"])]) + LIBS="$LIBS -libverbs"])]) # # RDMA @@ -156,7 +156,7 @@ AC_ARG_ENABLE([rdma], [enable_rdma=no]) AC_SUBST([HAVE_RDMA], [0]) AS_IF([test x$enable_rdma != xno], - [AC_CHECK_LIB([rdma], [rdma_get_devices], + [AC_CHECK_LIB([rdmacm], [rdma_get_devices], [AC_SUBST([HAVE_RDMA], [1]) LIBS="$LIBS -lrdmacm"])]) From 509e7821ca5a7506ce05d53e80e86ccf267a3494 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 12:42:20 -0600 Subject: [PATCH 205/424] Add in missing object. --- src/Makefile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.in b/src/Makefile.in index c06001690..ff1609bb5 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -45,6 +45,7 @@ ifeq ($(HAVE_RECVMSG),1) LIBBIFROST_OBJS += \ address.o \ udp_socket.o \ + hw_locality.o \ packet_capture.o \ packet_writer.o endif From 8585bdd9270742b52cd49611222d68a4e00c24ba Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 12:46:09 -0600 Subject: [PATCH 206/424] Use config.h. --- src/hw_locality.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hw_locality.hpp b/src/hw_locality.hpp index e0245f666..d70437719 100644 --- a/src/hw_locality.hpp +++ b/src/hw_locality.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,6 +29,7 @@ #pragma once #include +#include #if BF_HWLOC_ENABLED #include From 120ca755c3ea8a8d04440e94879dfde52a7eff58 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 14:42:43 -0600 Subject: [PATCH 207/424] Update for libhwloc 2. --- src/hw_locality.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hw_locality.cpp b/src/hw_locality.cpp index 85739c002..0e4d97427 100644 --- a/src/hw_locality.cpp +++ b/src/hw_locality.cpp @@ -27,6 +27,7 @@ */ #include "hw_locality.hpp" +#include #if BF_HWLOC_ENABLED int HardwareLocality::bind_memory_to_core(int core) { @@ -35,7 +36,14 @@ int HardwareLocality::bind_memory_to_core(int core) { int ret = 0; if( 0 <= core && core < ncore ) { hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); +#if HWLOC_API_VERSION >= 0x00020000 + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + if( !hwloc_bitmap_intersects(cpuset, hwloc_topology_get_allowed_cpuset(_topo)) ) { + throw std::runtime_error("requested core is not in the list of allowed cores"); + } +#else hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); +#endif hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; From 6fa61061c721533e083e74fa573a182439ba44c2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 15:02:30 -0600 Subject: [PATCH 208/424] Also catch cudaMemoryTypeUnregistered in bfGetSpace(). --- src/memory.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/memory.cpp b/src/memory.cpp index 10f68335f..8ca29cdc3 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -63,14 +63,15 @@ BFstatus bfGetSpace(const void* ptr, BFspace* space) { #if defined(CUDA_VERSION) && CUDA_VERSION >= 10000 } else { switch( ptr_attrs.type ) { - case cudaMemoryTypeHost: *space = BF_SPACE_SYSTEM; break; - case cudaMemoryTypeDevice: *space = BF_SPACE_CUDA; break; - case cudaMemoryTypeManaged: *space = BF_SPACE_CUDA_MANAGED; break; - default: { - // This should never be reached - BF_FAIL("Valid memoryType", BF_STATUS_INTERNAL_ERROR); - } - } + case cudaMemoryTypeUnregistered: // fall-through + case cudaMemoryTypeHost: *space = BF_SPACE_SYSTEM; break; + case cudaMemoryTypeDevice: *space = BF_SPACE_CUDA; break; + case cudaMemoryTypeManaged: *space = BF_SPACE_CUDA_MANAGED; break; + default: { + // This should never be reached + BF_FAIL("Valid memoryType", BF_STATUS_INTERNAL_ERROR); + } + } } #else } else if( ptr_attrs.isManaged ) { From 0938ee897a8c543cd91bd999172df939791fb1ab Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 15:05:45 -0600 Subject: [PATCH 209/424] Catch by reference. --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 9942cba9d..fbd200541 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -994,7 +994,7 @@ class Verbs { while( _verbs.pkt_batch == NULL ) { try { _verbs.pkt_batch = this->receive(); - } catch(Verbs::Error) { + } catch(Verbs::Error const&) { _verbs.pkt = NULL; errno = EAGAIN; return -1; From 9212dd26dcfeb14b45a535accc61a3e56186faf6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 29 Mar 2022 16:18:54 -0600 Subject: [PATCH 210/424] I know it is only 16 bytes long. --- src/ib_verbs.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index fbd200541..0fc139d7f 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -185,7 +185,10 @@ class Verbs { if( strncmp(&(line[0]), "lo", 2) == 0 ) { is_lo = 1; } + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-truncation" strncpy(name, &(line[0]), IFNAMSIZ); + #pragma GCC diagnostic pop } pclose(fp); @@ -197,7 +200,10 @@ class Verbs { if( line[strlen(line)-1] == '\n' ) { line[strlen(line)-1] = '\0'; } + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-truncation" strncpy(name, &(line[0]), IFNAMSIZ); + #pragma GCC diagnostic pop } pclose(fp); } From e0ab683a0eab9f789658e8789b0f197743bde7b0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Apr 2022 13:20:35 -0600 Subject: [PATCH 211/424] Enable Verbs and RDMA support by default. --- configure | 12 ++++++------ configure.ac | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 91bc65f0d..1a960651c 100755 --- a/configure +++ b/configure @@ -1519,8 +1519,8 @@ Optional Features: --disable-numa disable numa support (default=no) --disable-hwloc disable hwloc support (default=no) --enable-vma enable vma support (default=no) - --enable-verbs enable Infiniband verbs support (default=no) - --enable-rdma enable RDMA support (default=no) + --disable-verbs disable Infiniband verbs support (default=no) + --diable-rdma disable RDMA support (default=no) --disable-cuda disable cuda support (default=no) --enable-debug enable debugging mode (default=no) --enable-trace enable tracing mode for nvprof/nvvp (default=no) @@ -19294,9 +19294,9 @@ fi # Check whether --enable-verbs was given. if test ${enable_verbs+y} then : - enableval=$enable_verbs; enable_verbs=yes + enableval=$enable_verbs; enable_verbs=no else $as_nop - enable_verbs=no + enable_verbs=yes fi HAVE_VERBS=0 @@ -19353,9 +19353,9 @@ fi # Check whether --enable-rdma was given. if test ${enable_rdma+y} then : - enableval=$enable_rdma; enable_rdma=yes + enableval=$enable_rdma; enable_rdma=no else $as_nop - enable_rdma=no + enable_rdma=yes fi HAVE_RDMA=0 diff --git a/configure.ac b/configure.ac index c51d966ed..e5e6f66b9 100644 --- a/configure.ac +++ b/configure.ac @@ -135,10 +135,10 @@ AS_IF([test x$enable_vma != xno], # AC_ARG_ENABLE([verbs], - AS_HELP_STRING([--enable-verbs], - [enable Infiniband verbs support (default=no)]), - [enable_verbs=yes], - [enable_verbs=no]) + AS_HELP_STRING([--disable-verbs], + [disable Infiniband verbs support (default=no)]), + [enable_verbs=no], + [enable_verbs=yes]) AC_SUBST([HAVE_VERBS], [0]) AS_IF([test x$enable_verbs != xno], [AC_CHECK_LIB([ibverbs], [ibv_query_device], @@ -150,10 +150,10 @@ AS_IF([test x$enable_verbs != xno], # AC_ARG_ENABLE([rdma], - AS_HELP_STRING([--enable-rdma], - [enable RDMA support (default=no)]), - [enable_rdma=yes], - [enable_rdma=no]) + AS_HELP_STRING([--diable-rdma], + [disable RDMA support (default=no)]), + [enable_rdma=no], + [enable_rdma=yes]) AC_SUBST([HAVE_RDMA], [0]) AS_IF([test x$enable_rdma != xno], [AC_CHECK_LIB([rdmacm], [rdma_get_devices], From 2398102e7007fff91abc4089604f009f0c08d02b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 10 Jun 2022 13:08:24 -0600 Subject: [PATCH 212/424] We already require C++11. --- src/Socket.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Socket.hpp b/src/Socket.hpp index f98f65c0f..0760e77bf 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -1156,8 +1156,7 @@ int Socket::get_promiscuous() { return false; #endif } - -#if __cplusplus >= 201103L + void Socket::replace(Socket& s) { _fd = s._fd; s._fd = -1; _type = std::move(s._type); From b591d93af7f68fb5adf7cf60eff2f7907d232765 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 23 Jun 2022 12:41:16 -0600 Subject: [PATCH 213/424] Cleanup. --- src/Socket.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Socket.hpp b/src/Socket.hpp index 0760e77bf..99132f5c0 100644 --- a/src/Socket.hpp +++ b/src/Socket.hpp @@ -152,14 +152,12 @@ inline static int accept4(int sockfd, inline static sa_family_t get_family(int sockfd) { int ret; sockaddr addr; - socklen_t len = sizeof(addr); - ret = ::getsockname(sockfd, &addr, &len); - if(ret<0) { + socklen_t addr_len = sizeof(addr); + sockaddr_in* addr4 = reinterpret_cast(&addr); + if( ::getsockname(sockfd, (struct sockaddr*)&addr, &addr_len) < 0 ) { return AF_UNSPEC; } - - sockaddr_in* sa = reinterpret_cast (&addr); - return sa->sin_family; + return addr4->sin_family; } inline static int get_mtu(int sockfd) { @@ -624,7 +622,7 @@ void Socket::bind(sockaddr_storage local_address, base_address.sin_family = reinterpret_cast(&local_address)->sin_family; base_address.sin_addr.s_addr = htonl(INADDR_ANY); base_address.sin_port = htons(reinterpret_cast(&local_address)->sin_port); - check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(local_address)), + check_error(::bind(_fd, (struct sockaddr*)&local_address, sizeof(struct sockaddr)), "bind socket"); if( _type == SOCK_STREAM ) { From 35fcb140d3286bbb5d9b9624f81585252ffcaf7d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 14:11:05 -0600 Subject: [PATCH 214/424] Change the sleep from 1 to 5 ms. Change the multicast address. --- test/test_udp_io.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 2f677d29a..9a44f17da 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -251,7 +251,7 @@ def test_read_tbn(self): desc, data = self._get_tbn_data() for p in range(data.shape[0]): oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(1e-3) + time.sleep(0.005) reader.join() accumu.join() @@ -329,7 +329,7 @@ def test_read_drx(self): for p in range(data.shape[0]): oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) - time.sleep(1e-3) + time.sleep(0.005) reader.join() accumu.join() @@ -391,7 +391,7 @@ def test_read_drx_single(self): desc.set_nsrc(2) for p in range(data.shape[0]): oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) - time.sleep(1e-3) + time.sleep(0.005) reader.join() accumu.join() @@ -469,7 +469,7 @@ def test_read_pbeam(self): desc, data = self._get_pbeam_data() for p in range(data.shape[0]): oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) - time.sleep(1e-3) + time.sleep(0.005) reader.join() accumu.join() @@ -489,7 +489,7 @@ def test_read_pbeam(self): osock.close() def test_write_multicast(self): - addr = Address('224.0.0.101', 7147) + addr = Address('224.0.0.251', 7147) sock = UDPSocket() sock.connect(addr) op = UDPTransmit('tbn', sock) @@ -505,7 +505,7 @@ def test_read_multicast(self): ring = Ring(name="capture_multi") # Setup the blocks - addr = Address('224.0.0.101', 7147) + addr = Address('224.0.0.251', 7147) ## Output via UDPTransmit osock = UDPSocket() osock.connect(addr) @@ -529,7 +529,7 @@ def test_read_multicast(self): desc, data = self._get_tbn_data() for p in range(data.shape[0]): oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(1e-3) + time.sleep(0.005) reader.join() accumu.join() From b2aa8884e8d69d63e513d2f8a8faebb1fb8d50ba Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 14:39:02 -0600 Subject: [PATCH 215/424] Skip the first two frames? --- test/test_udp_io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 9a44f17da..6bdd8f7cb 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -263,7 +263,7 @@ def test_read_tbn(self): final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) ## Reduce to match the capture block size data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): + for i in range(2, data.shape[0]): np.testing.assert_equal(final[i,...], data[i,...]) # Clean up @@ -341,7 +341,7 @@ def test_read_drx(self): final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) ## Reduce to match the capture block size data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): + for i in range(2, data.shape[0]): np.testing.assert_equal(final[i,...], data[i,...]) # Clean up @@ -404,7 +404,7 @@ def test_read_drx_single(self): ## Reduce to match the capture block size data = data[:final.shape[0],...] data = data[:,[0,1],:] - for i in range(1, data.shape[0]): + for i in range(2, data.shape[0]): np.testing.assert_equal(final[i,...], data[i,...]) # Clean up @@ -480,7 +480,7 @@ def test_read_pbeam(self): final = final.transpose(0,2,1).copy() ## Reduce to match the capture block size data = data[:(final.shape[0]//240-1)*240,...] - for i in range(1, data.shape[0]): + for i in range(2, data.shape[0]): np.testing.assert_equal(final[i,...], data[i,...]) # Clean up @@ -541,7 +541,7 @@ def test_read_multicast(self): final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) ## Reduce to match the capture block size data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): + for i in range(2, data.shape[0]): np.testing.assert_equal(final[i,...], data[i,...]) # Clean up From e0f83bbd8511597d3f7a2a707135952fb463ecd5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 15:28:02 -0600 Subject: [PATCH 216/424] Allow the 32 and 64-bit integer types. Allow the numpy 64-bit floating point type. --- python/bifrost/header_standard.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/python/bifrost/header_standard.py b/python/bifrost/header_standard.py index ba45a5c96..53bd49700 100644 --- a/python/bifrost/header_standard.py +++ b/python/bifrost/header_standard.py @@ -43,6 +43,8 @@ """ +import numpy as np + from bifrost import telemetry telemetry.track_module() @@ -51,13 +53,13 @@ # Format: # 'parameter name':(type, minimum) STANDARD_HEADER = { - 'nchans': (int, 1), - 'nifs': (int, 1, ), - 'nbits': (int, 1), - 'fch1': (float, 0), - 'foff': (float, None), - 'tstart': (float, 0), - 'tsamp': (float, 0)} + 'nchans': ((int, np.int32, np.int64), 1), + 'nifs': ((int, np.int32, np.int64), 1, ), + 'nbits': ((int, np.int32, np.int64), 1), + 'fch1': ((float, np.float64), 0), + 'foff': ((float, np.float64), None), + 'tstart': ((float, np.float64), 0), + 'tsamp': ((float, np.float64), 0)} def enforce_header_standard(header_dict): """Raise an error if the header dictionary passed From 4ed1217f86e8b37ac52ff8f308802a514fcce0e5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 15:28:21 -0600 Subject: [PATCH 217/424] Use the explicit numpy integer/floating point types. --- test/test_header_standard.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_header_standard.py b/test/test_header_standard.py index d5288f512..787868eee 100644 --- a/test/test_header_standard.py +++ b/test/test_header_standard.py @@ -48,9 +48,9 @@ def test_simple_header(self): def test_numpy_types(self): """Same values, but some are numpy types""" self.header_dict = { - 'nchans': np.int(1), 'nifs': 1, 'nbits': 8, - 'fch1': np.float(100.0), 'foff': np.float(1e-5), - 'tstart': 1e5, 'tsamp': np.float(1e-5)} + 'nchans': np.int32(1), 'nifs': 1, 'nbits': 8, + 'fch1': np.float64(100.0), 'foff': np.float64(1e-5), + 'tstart': 1e5, 'tsamp': np.float64(1e-5)} def test_extra_parameters(self): """Add some extra parameters""" self.header_dict = { From 726ef67a1d8bcad9ec6e8b72c5f8809f60b474b0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 15:36:39 -0600 Subject: [PATCH 218/424] Don't resize, reallocate. --- python/bifrost/sigproc2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/bifrost/sigproc2.py b/python/bifrost/sigproc2.py index a85956091..e718773d3 100644 --- a/python/bifrost/sigproc2.py +++ b/python/bifrost/sigproc2.py @@ -363,12 +363,12 @@ def read(self, nframe_or_start, end=None): #requested_nbyte = nframe * self.frame_nbyte requested_nbyte = nframe * self.frame_nbyte * self.nbit // 8 if self.buf.nbytes != requested_nbyte: - self.buf.resize(requested_nbyte) + self.buf = np.empty(requested_nbyte, np.uint8) nbyte = self.f.readinto(self.buf) if nbyte * 8 % self.frame_nbit != 0: raise IOError("File read returned incomplete frame (truncated file?)") if nbyte < self.buf.nbytes: - self.buf.resize(nbyte) + self.buf = self.buf[:nbyte] nframe = nbyte * 8 // (self.frame_size * self.nbit) data = self.buf data = unpack(data, self.nbit) From df530a54002e89b053bb6cbc3d7be5f856b1b85c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 15:38:00 -0600 Subject: [PATCH 219/424] Update dates. --- python/bifrost/header_standard.py | 2 +- python/bifrost/sigproc2.py | 2 +- test/test_header_standard.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/bifrost/header_standard.py b/python/bifrost/header_standard.py index 53bd49700..6e703ef33 100644 --- a/python/bifrost/header_standard.py +++ b/python/bifrost/header_standard.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016-2021, The Bifrost Authors. All rights reserved. +# Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions diff --git a/python/bifrost/sigproc2.py b/python/bifrost/sigproc2.py index e718773d3..baa328ea3 100644 --- a/python/bifrost/sigproc2.py +++ b/python/bifrost/sigproc2.py @@ -1,5 +1,5 @@ -# Copyright (c) 2016-2020, The Bifrost Authors. All rights reserved. +# Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions diff --git a/test/test_header_standard.py b/test/test_header_standard.py index 787868eee..44faadf20 100644 --- a/test/test_header_standard.py +++ b/test/test_header_standard.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016, The Bifrost Authors. All rights reserved. +# Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions From 8b84db15c901280ffbb38a38b55940b8a9501a87 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 15:50:41 -0600 Subject: [PATCH 220/424] Debug. --- test/test_udp_io.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 6bdd8f7cb..2edbd99e8 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -403,9 +403,11 @@ def test_read_drx_single(self): final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) ## Reduce to match the capture block size data = data[:final.shape[0],...] - data = data[:,[0,1],:] - for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for i in range(1, data.shape[0]): + print(i) + for j in range(2): + print(j) + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop From db9125497ceb08af44da1a590eb02c542fc159d9 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 17:34:32 -0600 Subject: [PATCH 221/424] Expand all loops. --- test/test_udp_io.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 2edbd99e8..9bd19b43d 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -264,7 +264,8 @@ def test_read_tbn(self): ## Reduce to match the capture block size data = data[:final.shape[0],...] for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop @@ -342,7 +343,8 @@ def test_read_drx(self): ## Reduce to match the capture block size data = data[:final.shape[0],...] for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop @@ -404,9 +406,7 @@ def test_read_drx_single(self): ## Reduce to match the capture block size data = data[:final.shape[0],...] for i in range(1, data.shape[0]): - print(i) for j in range(2): - print(j) np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up @@ -544,7 +544,8 @@ def test_read_multicast(self): ## Reduce to match the capture block size data = data[:final.shape[0],...] for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop From 5957cd3186da9d64cc378b49f8d0b2d2673b74cf Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 18:13:07 -0600 Subject: [PATCH 222/424] Formatting. --- test/test_udp_io.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 9bd19b43d..fe2e2a125 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -266,7 +266,7 @@ def test_read_tbn(self): for i in range(2, data.shape[0]): for j in range(data.shape[1]): np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + # Clean up del oop isock.close() @@ -345,7 +345,7 @@ def test_read_drx(self): for i in range(2, data.shape[0]): for j in range(data.shape[1]): np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + # Clean up del oop isock.close() @@ -408,7 +408,7 @@ def test_read_drx_single(self): for i in range(1, data.shape[0]): for j in range(2): np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + # Clean up del oop isock.close() @@ -546,7 +546,7 @@ def test_read_multicast(self): for i in range(2, data.shape[0]): for j in range(data.shape[1]): np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + # Clean up del oop isock.close() From 38f520b18d22ac24df874908176e1fab3d70c74b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 4 Aug 2022 18:37:29 -0600 Subject: [PATCH 223/424] Back to 1 ms. --- test/test_udp_io.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index fe2e2a125..b38e2038d 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -251,7 +251,7 @@ def test_read_tbn(self): desc, data = self._get_tbn_data() for p in range(data.shape[0]): oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(0.005) + time.sleep(0.001) reader.join() accumu.join() @@ -330,7 +330,7 @@ def test_read_drx(self): for p in range(data.shape[0]): oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) - time.sleep(0.005) + time.sleep(0.001) reader.join() accumu.join() @@ -393,7 +393,7 @@ def test_read_drx_single(self): desc.set_nsrc(2) for p in range(data.shape[0]): oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) - time.sleep(0.005) + time.sleep(0.001) reader.join() accumu.join() @@ -471,7 +471,7 @@ def test_read_pbeam(self): desc, data = self._get_pbeam_data() for p in range(data.shape[0]): oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) - time.sleep(0.005) + time.sleep(0.001) reader.join() accumu.join() @@ -531,7 +531,7 @@ def test_read_multicast(self): desc, data = self._get_tbn_data() for p in range(data.shape[0]): oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(0.005) + time.sleep(0.001) reader.join() accumu.join() From a3a35b25165a9e4546dc6793963d6bb4ced46abd Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 8 Aug 2022 12:49:28 -0600 Subject: [PATCH 224/424] Work on moving ring memory binding control over to hwloc. --- configure | 71 ----------------------------------------- configure.ac | 19 ----------- src/Makefile.in | 2 +- src/bifrost/config.h.in | 1 - src/hw_locality.cpp | 39 ++++++++++++++++++++-- src/hw_locality.hpp | 6 ++-- src/ring.cpp | 4 +-- src/ring_impl.cpp | 16 ++++------ src/ring_impl.hpp | 10 ++++-- 9 files changed, 57 insertions(+), 111 deletions(-) diff --git a/configure b/configure index 97b882fcb..41592130d 100755 --- a/configure +++ b/configure @@ -737,7 +737,6 @@ HAVE_RDMA HAVE_VERBS HAVE_VMA HAVE_HWLOC -HAVE_NUMA HAVE_FLOAT128 HAVE_OPENMP LIBOBJS @@ -849,7 +848,6 @@ with_gnu_ld with_sysroot enable_libtool_lock with_ctags -enable_numa enable_hwloc enable_vma enable_verbs @@ -1527,7 +1525,6 @@ Optional Features: --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) - --disable-numa disable numa support (default=no) --disable-hwloc disable hwloc support (default=no) --enable-vma enable vma support (default=no) --disable-verbs disable Infiniband verbs support (default=no) @@ -21011,65 +21008,6 @@ then : fi -# -# NUMA -# - -# Check whether --enable-numa was given. -if test ${enable_numa+y} -then : - enableval=$enable_numa; enable_numa=no -else $as_nop - enable_numa=yes -fi - -HAVE_NUMA=0 - -if test x$enable_numa != xno -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for numa_node_of_cpu in -lnuma" >&5 -printf %s "checking for numa_node_of_cpu in -lnuma... " >&6; } -if test ${ac_cv_lib_numa_numa_node_of_cpu+y} -then : - printf %s "(cached) " >&6 -else $as_nop - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnuma $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -namespace conftest { - extern "C" int numa_node_of_cpu (); -} -int -main (void) -{ -return conftest::numa_node_of_cpu (); - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_link "$LINENO" -then : - ac_cv_lib_numa_numa_node_of_cpu=yes -else $as_nop - ac_cv_lib_numa_numa_node_of_cpu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_numa_numa_node_of_cpu" >&5 -printf "%s\n" "$ac_cv_lib_numa_numa_node_of_cpu" >&6; } -if test "x$ac_cv_lib_numa_numa_node_of_cpu" = xyes -then : - HAVE_NUMA=1 - - LIBS="$LIBS -lnuma" -fi - -fi - # # HWLOC # @@ -27010,15 +26948,6 @@ else $as_nop printf "%s\n" "$as_me: cuda: no" >&6;} fi -if test x$HAVE_NUMA = x1 -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: numa: yes" >&5 -printf "%s\n" "$as_me: numa: yes" >&6;} -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: numa: no" >&5 -printf "%s\n" "$as_me: numa: no" >&6;} -fi - if test x$HAVE_HWLOC = x1 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: hwloc: yes" >&5 diff --git a/configure.ac b/configure.ac index fb08e5891..5cd52c2cc 100644 --- a/configure.ac +++ b/configure.ac @@ -91,21 +91,6 @@ AC_SUBST([HAVE_FLOAT128], [0]) AS_IF([test x$HAVE_HAVE_LONG_DOUBLE_WIDER = x1], [AC_SUBST([HAVE_FLOAT128], [0])]) -# -# NUMA -# - -AC_ARG_ENABLE([numa], - AS_HELP_STRING([--disable-numa], - [disable numa support (default=no)]), - [enable_numa=no], - [enable_numa=yes]) -AC_SUBST([HAVE_NUMA], [0]) -AS_IF([test x$enable_numa != xno], - [AC_CHECK_LIB([numa], [numa_node_of_cpu], - [AC_SUBST([HAVE_NUMA], [1]) - LIBS="$LIBS -lnuma"])]) - # # HWLOC # @@ -404,10 +389,6 @@ AS_IF([test x$HAVE_CUDA = x1], [AC_MSG_NOTICE(cuda: yes - v$CUDA_VERSION - $GPU_ARCHS)], [AC_MSG_NOTICE(cuda: no)]) -AS_IF([test x$HAVE_NUMA = x1], - [AC_MSG_NOTICE(numa: yes)], - [AC_MSG_NOTICE(numa: no)]) - AS_IF([test x$HAVE_HWLOC = x1], [AC_MSG_NOTICE(hwloc: yes)], [AC_MSG_NOTICE(hwloc: no)]) diff --git a/src/Makefile.in b/src/Makefile.in index 9ca7a0aae..ed787ea83 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -32,6 +32,7 @@ LIBBIFROST_OBJS = \ common.o \ memory.o \ affinity.o \ + hw_locality.o \ cuda.o \ fileutils.o \ testsuite.o \ @@ -47,7 +48,6 @@ ifeq ($(HAVE_RECVMSG),1) LIBBIFROST_OBJS += \ address.o \ udp_socket.o \ - hw_locality.o \ packet_capture.o \ packet_writer.o endif diff --git a/src/bifrost/config.h.in b/src/bifrost/config.h.in index 314896b2c..8db213af1 100644 --- a/src/bifrost/config.h.in +++ b/src/bifrost/config.h.in @@ -56,7 +56,6 @@ extern "C" { // Features #define BF_FLOAT128_ENABLED @HAVE_FLOAT128@ #define BF_OPENMP_ENABLED @HAVE_OPENMP@ -#define BF_NUMA_ENABLED @HAVE_NUMA@ #define BF_HWLOC_ENABLED @HAVE_HWLOC@ #define BF_VMA_ENABLED @HAVE_VMA@ #define BF_VERBS_ENABLED @HAVE_VERBS@ diff --git a/src/hw_locality.cpp b/src/hw_locality.cpp index 0e4d97427..4f40eeca6 100644 --- a/src/hw_locality.cpp +++ b/src/hw_locality.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,23 @@ #include #if BF_HWLOC_ENABLED -int HardwareLocality::bind_memory_to_core(int core) { +int HardwareLocality::get_numa_node_of_core(int core) { + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); + int ret = -1; + if( 0 <= core && core < ncore ) { + hwloc_obj_t obj = hwloc_get_obj_by_type(_topo, HWLOC_OBJ_CORE, core); + hwloc_obj_t tmp = NULL; + while( (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, tmp)) != NULL ) { + if( hwloc_bitmap_isset(obj->nodeset, tmp->os_index) ) { + ret = tmp->os_index; + } + } + } + return ret; +} + +int HardwareLocality::bind_thread_memory_to_core(int core) { int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); int ret = 0; @@ -52,4 +68,23 @@ int HardwareLocality::bind_memory_to_core(int core) { } return ret; } + +int HardwareLocality::bind_memory_area_to_numa_node(const void* addr, size_t size, int node) { + int nnode = hwloc_get_nbobjs_by_type(_topo, HWLOC_OBJ_NUMANODE); + int ret = 0; + if( 0 <= node && node < nnode ) { + hwloc_obj_t obj = hwloc_get_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, node); +#if HWLOC_API_VERSION >= 0x00020000 + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->nodeset); +#else + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); +#endif + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_area_membind(_topo, addr, size, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } + return ret; +} #endif // BF_HWLOC_ENABLED diff --git a/src/hw_locality.hpp b/src/hw_locality.hpp index d70437719..3e80be59d 100644 --- a/src/hw_locality.hpp +++ b/src/hw_locality.hpp @@ -45,7 +45,9 @@ class HardwareLocality { ~HardwareLocality() { hwloc_topology_destroy(_topo); } - int bind_memory_to_core(int core); + int get_numa_node_of_core(int core); + int bind_thread_memory_to_core(int core); + int bind_memory_area_to_numa_node(const void* addr, size_t size, int node); }; #endif // BF_HWLOC_ENABLED @@ -57,7 +59,7 @@ class BoundThread { BoundThread(int core) { bfAffinitySetCore(core); #if BF_HWLOC_ENABLED - assert(_hwloc.bind_memory_to_core(core) == 0); + assert(_hwloc.bind_thread_memory_to_core(core) == 0); #endif } }; diff --git a/src/ring.cpp b/src/ring.cpp index cf96eb372..0cf0f3d79 100644 --- a/src/ring.cpp +++ b/src/ring.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. + * Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -69,7 +69,7 @@ BFstatus bfRingGetSpace(BFring ring, BFspace* space) { BFstatus bfRingSetAffinity(BFring ring, int core) { BF_ASSERT(ring, BF_STATUS_INVALID_HANDLE); BF_ASSERT(core >= -1, BF_STATUS_INVALID_ARGUMENT); - BF_ASSERT(BF_NUMA_ENABLED, BF_STATUS_UNSUPPORTED); + BF_ASSERT(BF_HWLOC_ENABLED, BF_STATUS_UNSUPPORTED); BF_TRY_RETURN(ring->set_core(core)); } BFstatus bfRingGetAffinity(BFring ring, int* core) { diff --git a/src/ring_impl.cpp b/src/ring_impl.cpp index e0471b7ab..b1126142f 100644 --- a/src/ring_impl.cpp +++ b/src/ring_impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. + * Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -45,6 +45,7 @@ // Work out whether/how to support independent specification of // buffer_factor. +#include "hw_locality.hpp" #include "ring_impl.hpp" #include "utils.hpp" #include "assert.hpp" @@ -54,10 +55,6 @@ #include #include "cuda.hpp" -#if BF_NUMA_ENABLED -#include -#endif - // This implements a lock with the condition that no reads or writes // can be open while it is held. class RingReallocLock { @@ -162,12 +159,11 @@ void BFring_impl::resize(BFsize contiguous_span, //std::cout << "Allocating " << new_nbyte << std::endl; BF_ASSERT_EXCEPTION(bfMalloc((void**)&new_buf, new_nbyte, _space) == BF_STATUS_SUCCESS, BF_STATUS_MEM_ALLOC_FAILED); -#if BF_NUMA_ENABLED +#if BF_HWLOC_ENABLED if( _core != -1 ) { - BF_ASSERT_EXCEPTION(numa_available() != -1, BF_STATUS_UNSUPPORTED); - int node = numa_node_of_cpu(_core); + int node = _hwloc.get_numa_node_of_core(_core); BF_ASSERT_EXCEPTION(node != -1, BF_STATUS_INVALID_ARGUMENT); - numa_tonode_memory(new_buf, new_nbyte, node); + _hwloc.bind_memory_area_to_numa_node(new_buf, new_nbyte, node); } #endif if( _buf ) { @@ -479,7 +475,7 @@ void BFring_impl::finish_sequence(BFsequence_sptr sequence, void BFring_impl::_write_proclog_entry() { char cinfo[32]=""; - #if BF_NUMA_ENABLED + #if BF_HWLOC_ENABLED snprintf(cinfo, 31, "binding : %i\n", _core); #endif _size_log.update("space : %s\n" diff --git a/src/ring_impl.hpp b/src/ring_impl.hpp index 5824fd923..94c9e274a 100644 --- a/src/ring_impl.hpp +++ b/src/ring_impl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Bifrost Authors. All rights reserved. + * Copyright (c) 2016-2022, The Bifrost Authors. All rights reserved. * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,6 +32,7 @@ #include #include "assert.hpp" #include "proclog.hpp" +#include "hw_locality.hpp" #include #include @@ -96,8 +97,11 @@ class BFring_impl { BFsize _nwrite_open; BFsize _nrealloc_pending; - int _core; - ProcLog _size_log; +#if BF_HWLOC_ENABLED + HardwareLocality _hwloc; +#endif + int _core; + ProcLog _size_log; std::queue _sequence_queue; std::map _sequence_map; From e964ad9131b1ed68f60095acc21363827a9e952a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 8 Aug 2022 13:04:01 -0600 Subject: [PATCH 225/424] Add hwloc into the software that gets installed. --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 60bcc2ebf..614b7e52c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,6 +36,7 @@ jobs: exuberant-ctags \ gfortran \ git \ + libhwloc-dev \ libopenblas-dev \ pkg-config \ software-properties-common @@ -47,6 +48,7 @@ jobs: ctags-exuberant \ gawk \ gnu-sed \ + hwloc \ pkg-config - uses: actions/setup-python@v2 with: From 180047e04d9c67d6c69cea840d90002afa831009 Mon Sep 17 00:00:00 2001 From: Christopher League Date: Sun, 14 Aug 2022 15:28:34 -0600 Subject: [PATCH 226/424] Remove stray reference to BF_NUMA_ENABLED Since libnuma removed on this branch in favor of hwloc, this generated NameError: name 'BF_NUMA_ENABLED' is not defined when running python -m bifrost.version --config --- python/bifrost/version/__main__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/bifrost/version/__main__.py b/python/bifrost/version/__main__.py index c3c1bc84a..5e3150fd9 100644 --- a/python/bifrost/version/__main__.py +++ b/python/bifrost/version/__main__.py @@ -46,7 +46,6 @@ def _yes_no(value): print("\nConfiguration:") print(" Memory alignment: %i B" % BF_ALIGNMENT) print(" OpenMP support: %s" % _yes_no(BF_OPENMP_ENABLED)) - print(" NUMA support %s" % _yes_no(BF_NUMA_ENABLED)) print(" Hardware locality support: %s" % _yes_no(BF_HWLOC_ENABLED)) print(" Mellanox messaging accelerator (VMA) support: %s" % _yes_no(BF_VMA_ENABLED)) print(" Infiniband verbs support: %s" % _yes_no(BF_VERBS_ENABLED)) From 768b3fb4c145f1ecfcaefb039868efd8377036d0 Mon Sep 17 00:00:00 2001 From: Christopher League Date: Sun, 14 Aug 2022 19:40:01 -0600 Subject: [PATCH 227/424] Add test of bifrost.version program Maybe this would have noticed the issue with a stray NameError. --- test/test_version.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 test/test_version.py diff --git a/test/test_version.py b/test/test_version.py new file mode 100644 index 000000000..4ab08501e --- /dev/null +++ b/test/test_version.py @@ -0,0 +1,10 @@ +import unittest +import subprocess +import sys + +class TestVersion(unittest.TestCase): + def test_plain_version(self): + subprocess.check_output([sys.executable, '-m', 'bifrost.version']) + + def test_version_config(self): + subprocess.check_output([sys.executable, '-m', 'bifrost.version', '--config']) From 0ba58be4cd2b58dccf0f7cee0633f6eae9c25621 Mon Sep 17 00:00:00 2001 From: Christopher League Date: Sun, 14 Aug 2022 19:43:18 -0600 Subject: [PATCH 228/424] Use unittest discover -v Verbose output shows each test as it occurs, or the reason if skipped. More informative log trace for CI compared to "...sss..." --- .github/workflows/main.yml | 2 +- Makefile.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 614b7e52c..1e93fceca 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,7 +83,7 @@ jobs: cd test bash ./download_test_data.sh python -c "from bifrost import telemetry; telemetry.disable()" - coverage run --source=bifrost.ring,bifrost,bifrost.pipeline -m unittest discover + coverage run --source=bifrost.ring,bifrost,bifrost.pipeline -m unittest discover -v coverage xml - name: "Upload Coverage" env: diff --git a/Makefile.in b/Makefile.in index 852b2f951..29c5728b4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -21,7 +21,7 @@ libbifrost: test: #$(MAKE) -C $(SRC_DIR) test ifeq ($(HAVE_PYTHON),1) - cd test && ./download_test_data.sh ; python -m unittest discover + cd test && ./download_test_data.sh ; python -m unittest discover -v endif .PHONY: test clean: From 139590b45bfa075f3699944446a6323da2566dec Mon Sep 17 00:00:00 2001 From: Christopher League Date: Fri, 5 Aug 2022 08:59:45 -0600 Subject: [PATCH 229/424] Fix make_dir so it chmods only if new dir created Before, it led to permission denied exceptions when /dev/shm/bifrost had been created by someone else. (We create it 0777 so can just proceed to use it even if owner is different.) (Cherry-picked bc888554 from python-streams onto ibverb-support.) --- src/fileutils.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/fileutils.cpp b/src/fileutils.cpp index 58aa6dae1..dfc203210 100644 --- a/src/fileutils.cpp +++ b/src/fileutils.cpp @@ -48,9 +48,11 @@ std::string get_home_dir(void) { void make_dir(std::string path, int perms) { #if defined(HAVE_CXX_FILESYSTEM) && HAVE_CXX_FILESYSTEM - std::filesystem::create_directories(path); - std::filesystem::permissions(path, (std::filesystem::perms) perms, - std::filesystem::perm_options::replace); + bool created = std::filesystem::create_directories(path); + if(created) { + std::filesystem::permissions(path, (std::filesystem::perms) perms, + std::filesystem::perm_options::replace); + } #else std::ostringstream cmd; cmd << "mkdir -p -m " << std::oct << perms << ' ' << path; From aa2b469fba841c8f791aca8c2bab913e5a370dc2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 1 Nov 2022 07:56:06 -0600 Subject: [PATCH 230/424] Fix the 'packets sent' stats. --- src/packet_writer.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index f64eed5ad..bba615786 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -302,8 +302,10 @@ class PacketWriterThread : public BoundThread { _stats.ninvalid += npackets; _stats.ninvalid_bytes += npackets * (hdr_size + data_size); } else { - _stats.nvalid += npackets; - _stats.nvalid_bytes += npackets * (hdr_size + data_size); + _stats.nvalid += nsent; + _stats.nvalid_bytes += nsent * (hdr_size + data_size); + _stats.ninvalid += (npackets - nsent); + _stats.ninvalid_bytes += (npackets - nsent) * (hdr_size + data_size); _limiter.end_and_wait(npackets); } return nsent; From 80d516ec368f35728a9efeec2c8170ff282f99fc Mon Sep 17 00:00:00 2001 From: Jack Hickish Date: Tue, 6 Dec 2022 14:50:02 +0000 Subject: [PATCH 231/424] diable -> disable typo (#192) --- configure | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 41592130d..5afb00c01 100755 --- a/configure +++ b/configure @@ -1528,7 +1528,7 @@ Optional Features: --disable-hwloc disable hwloc support (default=no) --enable-vma enable vma support (default=no) --disable-verbs disable Infiniband verbs support (default=no) - --diable-rdma disable RDMA support (default=no) + --disable-rdma disable RDMA support (default=no) --disable-cuda disable cuda support (default=no) --enable-debug enable debugging mode (default=no) --enable-trace enable tracing mode for nvprof/nvvp (default=no) diff --git a/configure.ac b/configure.ac index 5cd52c2cc..e1387aae2 100644 --- a/configure.ac +++ b/configure.ac @@ -144,7 +144,7 @@ AS_IF([test x$enable_verbs != xno], # AC_ARG_ENABLE([rdma], - AS_HELP_STRING([--diable-rdma], + AS_HELP_STRING([--disable-rdma], [disable RDMA support (default=no)]), [enable_rdma=no], [enable_rdma=yes]) From 854ffd18f32b59d5c18dba1f2d17ee26a7dbed7b Mon Sep 17 00:00:00 2001 From: Christopher League Date: Tue, 6 Dec 2022 09:10:48 -0500 Subject: [PATCH 232/424] Enable py3.10 in CI and tests Cherry-picked 8db12226496e547e569c76579cf6a6e662db4cb0 and resolved conflicts. --- .github/workflows/main.yml | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1e93fceca..05f724fc0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,6 @@ +--- name: "Build and Test" -on: [push, pull_request] +"on": [push, pull_request] jobs: pre_build: runs-on: ubuntu-latest @@ -7,7 +8,7 @@ jobs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - id: skip_check - uses: fkirc/skip-duplicate-actions@v3.4.1 + uses: fkirc/skip-duplicate-actions@v5 with: concurrent_skipping: 'same_content' skip_after_successful_duplicate: 'true' @@ -19,7 +20,7 @@ jobs: strategy: matrix: os: [self-hosted, ubuntu-latest, macos-latest] - python-version: ['2.7', '3.6', '3.8'] + python-version: ['2.7', '3.6', '3.8', '3.10'] exclude: - os: macos-latest python-version: 2.7 @@ -50,10 +51,9 @@ jobs: gnu-sed \ hwloc \ pkg-config - - uses: actions/setup-python@v2 + - uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.python-version }} - - uses: actions/checkout@v2 - name: "Software Install - Python" run: python -m pip install \ setuptools \ @@ -67,9 +67,21 @@ jobs: coverage - name: "Software Install - Python, part 2" if: ${{ matrix.os == 'self-hosted' && matrix.python-version != '2.7' }} + # Setting CPLUS_INCLUDE_PATH helps pycuda find the right + # Python header files to use with its embedded + # subset of Boost. + env: + CPLUS_INCLUDE_PATH: "${{ env.pythonLocation }}/include/python\ + ${{ matrix.python-version }}" run: python -m pip install \ - cupy \ - pycuda + cupy-cuda112 \ + pycuda \ + numba \ + jupyterlab \ + jupyter_client \ + nbformat \ + nbconvert + - uses: actions/checkout@v3 - name: "Build and Install" run: | ./configure @@ -83,12 +95,13 @@ jobs: cd test bash ./download_test_data.sh python -c "from bifrost import telemetry; telemetry.disable()" - coverage run --source=bifrost.ring,bifrost,bifrost.pipeline -m unittest discover -v + coverage run --source=bifrost.ring,bifrost,bifrost.pipeline \ + -m unittest discover -v coverage xml - name: "Upload Coverage" env: - UNITTEST_OS: ${{ matrix.os }} - UNITTEST_PY: ${{ matrix.python-version }} + UNITTEST_OS: ${{ matrix.os }} + UNITTEST_PY: ${{ matrix.python-version }} if: ${{ matrix.os == 'self-hosted' && matrix.python-version == '3.8' }} uses: codecov/codecov-action@v2 with: From 2c51bb8280a5f9a485ee3b1a823099ef8949bcda Mon Sep 17 00:00:00 2001 From: Christopher League Date: Tue, 6 Dec 2022 10:46:26 -0500 Subject: [PATCH 233/424] Pin ubuntu-20.04 for python-3.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seems to be the work-around for “Version 3.6 with arch x64 not found.” See issue 544 on github:actions/setup-python --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 05f724fc0..95726b66f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: "Build and Test" "on": [push, pull_request] jobs: pre_build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: @@ -19,7 +19,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [self-hosted, ubuntu-latest, macos-latest] + os: [self-hosted, ubuntu-20.04, macos-latest] python-version: ['2.7', '3.6', '3.8', '3.10'] exclude: - os: macos-latest @@ -27,7 +27,7 @@ jobs: fail-fast: false steps: - name: "Software Install - Ubuntu" - if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'self-hosted' }} + if: ${{ matrix.os == 'ubuntu-20.04' || matrix.os == 'self-hosted' }} run: | sudo apt-get update && \ sudo apt-get install -y \ From b0d6740f02601a8405d42f6f182b4241b0596360 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 16 Feb 2023 13:39:11 -0700 Subject: [PATCH 234/424] Add in tests for SSE/AVX/AVX512 support. --- configure.ac | 78 +++++++++++++++++++++++++++++++++++++++++ src/bifrost/config.h.in | 3 ++ 2 files changed, 81 insertions(+) diff --git a/configure.ac b/configure.ac index e1387aae2..4d593a9b0 100644 --- a/configure.ac +++ b/configure.ac @@ -91,6 +91,84 @@ AC_SUBST([HAVE_FLOAT128], [0]) AS_IF([test x$HAVE_HAVE_LONG_DOUBLE_WIDER = x1], [AC_SUBST([HAVE_FLOAT128], [0])]) +# +# SSE +# + +AC_DEFUN([AC_CHECK_SSE], [ + AC_MSG_CHECKING([for SSE support]) + + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + int main() { + __m128 x = _mm_set1_ps(1.0f); + x = _mm_add_ps(x, x); + return _mm_cvtss_f32(x) != 2.0f; + } + ]]) + ], [ + AC_SUBST([HAVE_SSE], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +AC_SUBST([HAVE_SSE], [0]) +AC_CHECK_SSE + +# +# AVX +# + +AC_DEFUN([AC_CHECK_AVX], [ + AC_MSG_CHECKING([for AVX support]) + + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + int main() { + __m256d x = _mm256_set1_pd(1.0); + x = _mm256_add_pd(x, x); + return _mm256_cvtsd_f64(x) != 2.0; + } + ]]) + ], [ + AC_SUBST([HAVE_AVX], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +AC_SUBST([HAVE_AVX], [0]) +AC_CHECK_AVX + +# +# AVX512 +# + +AC_DEFUN([AC_CHECK_AVX512], [ + AC_MSG_CHECKING([for AVX-512 support]) + + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + int main() { + __m512d x = _mm512_set1_pd(1.0); + x = _mm512_add_pd(x, x); + return _mm512_cvtsd_f64(x) != 2.0; + } + ]]) + ], [ + AC_SUBST([HAVE_AVX512], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) +AC_SUBST([HAVE_AVX512], [1]) +AC_CHECK_AVX512 + # # HWLOC # diff --git a/src/bifrost/config.h.in b/src/bifrost/config.h.in index 8db213af1..5b47aa193 100644 --- a/src/bifrost/config.h.in +++ b/src/bifrost/config.h.in @@ -54,6 +54,9 @@ extern "C" { #define BF_MAP_KERNEL_DISK_CACHE_VERSION (1000*@PACKAGE_VERSION_MAJOR@ + 10*@PACKAGE_VERSION_MINOR@) // Features +#define BF_SSE_ENABLED @HAVE_SSE@ +#define BF_AVX_ENABLED @HAVE_AVX@ +#define BF_AVX512_ENABLED @HAVE_AVX512@ #define BF_FLOAT128_ENABLED @HAVE_FLOAT128@ #define BF_OPENMP_ENABLED @HAVE_OPENMP@ #define BF_HWLOC_ENABLED @HAVE_HWLOC@ From cc1502174680ddc25a0fe6a1bd128357a2ef5a41 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 16 Feb 2023 13:40:59 -0700 Subject: [PATCH 235/424] Rebuild configure. --- configure | 479 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 376 insertions(+), 103 deletions(-) diff --git a/configure b/configure index 5afb00c01..5aac6db62 100755 --- a/configure +++ b/configure @@ -737,6 +737,9 @@ HAVE_RDMA HAVE_VERBS HAVE_VMA HAVE_HWLOC +HAVE_AVX512 +HAVE_AVX +HAVE_SSE HAVE_FLOAT128 HAVE_OPENMP LIBOBJS @@ -771,6 +774,7 @@ ac_ct_AR AR DLLTOOL OBJDUMP +FILECMD LN_S NM ac_ct_DUMPBIN @@ -3337,8 +3341,8 @@ esac -macro_version='2.4.6' -macro_revision='2.4.6' +macro_version='2.4.7' +macro_revision='2.4.7' @@ -4961,13 +4965,13 @@ else mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 @@ -5105,7 +5109,7 @@ esac fi fi - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; @@ -5209,7 +5213,7 @@ else $as_nop lt_cv_sys_max_cmd_len=8192; ;; - bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) + bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -5252,7 +5256,7 @@ else $as_nop sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi @@ -5457,6 +5461,114 @@ esac +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. +set dummy ${ac_tool_prefix}file; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_FILECMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$FILECMD"; then + ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_FILECMD="${ac_tool_prefix}file" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +FILECMD=$ac_cv_prog_FILECMD +if test -n "$FILECMD"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 +printf "%s\n" "$FILECMD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_FILECMD"; then + ac_ct_FILECMD=$FILECMD + # Extract the first word of "file", so it can be a program name with args. +set dummy file; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_prog_ac_ct_FILECMD+y} +then : + printf %s "(cached) " >&6 +else $as_nop + if test -n "$ac_ct_FILECMD"; then + ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_FILECMD="file" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD +if test -n "$ac_ct_FILECMD"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 +printf "%s\n" "$ac_ct_FILECMD" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + if test "x$ac_ct_FILECMD" = x; then + FILECMD=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + FILECMD=$ac_ct_FILECMD + fi +else + FILECMD="$ac_cv_prog_FILECMD" +fi + + + + + + + if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 @@ -5600,7 +5712,7 @@ beos*) bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_cmd='$FILECMD -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; @@ -5634,14 +5746,14 @@ darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac @@ -5655,7 +5767,7 @@ haiku*) ;; hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' @@ -5702,7 +5814,7 @@ netbsd*) newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_cmd=$FILECMD lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; @@ -6451,13 +6563,29 @@ esac fi : ${AR=ar} -: ${AR_FLAGS=cru} +# Use ARFLAGS variable as AR's operation code to sync the variable naming with +# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have +# higher priority because thats what people were doing historically (setting +# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS +# variable obsoleted/removed. + +test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} +lt_ar_flags=$AR_FLAGS + + + + + + +# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override +# by AR_FLAGS because that was never working and AR_FLAGS is about to die. + @@ -6921,7 +7049,7 @@ esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" @@ -6939,20 +7067,20 @@ fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ @@ -6976,7 +7104,7 @@ for ac_symprfx in "" "_"; do if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. - # Also find C++ and __fastcall symbols from MSVC++, + # Also find C++ and __fastcall symbols from MSVC++ or ICC, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ @@ -6994,9 +7122,9 @@ for ac_symprfx in "" "_"; do " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -7199,7 +7327,7 @@ case $with_sysroot in #( fi ;; #( /*) - lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` ;; #( no|'') ;; #( @@ -7325,7 +7453,7 @@ ia64-*-hpux*) ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; @@ -7346,7 +7474,7 @@ ia64-*-hpux*) printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; @@ -7358,7 +7486,7 @@ ia64-*-hpux*) ;; esac else - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; @@ -7384,7 +7512,7 @@ mips64*-*linux*) printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; @@ -7392,7 +7520,7 @@ mips64*-*linux*) emul="${emul}64" ;; esac - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; @@ -7400,7 +7528,7 @@ mips64*-*linux*) emul="${emul}ltsmip" ;; esac - case `/usr/bin/file conftest.$ac_objext` in + case `$FILECMD conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; @@ -7424,14 +7552,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; @@ -7539,7 +7667,7 @@ printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `/usr/bin/file conftest.o` in + case `$FILECMD conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) @@ -8322,8 +8450,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cru libconftest.a conftest.o" >&5 - $AR cru libconftest.a conftest.o 2>&5 + echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 + $AR $AR_FLAGS libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF @@ -8351,11 +8479,11 @@ printf "%s\n" "$lt_cv_ld_force_load" >&6; } darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) - case ${MACOSX_DEPLOYMENT_TARGET},$host in - 10.[012],*|,*powerpc*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - *) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + case $MACOSX_DEPLOYMENT_TARGET,$host in + 10.[012],*|,*powerpc*-darwin[5-8]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + *) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac @@ -8753,8 +8881,8 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a '.a' archive for static linking (except MSVC, -# which needs '.lib'). +# All known linkers require a '.a' archive for static linking (except MSVC and +# ICC, which need '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld @@ -9266,7 +9394,7 @@ lt_prog_compiler_static= lt_prog_compiler_static='-qstaticlink' ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' @@ -9689,15 +9817,15 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time + # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. + # Microsoft Visual C++ or Intel C++ Compiler. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) + # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) with_gnu_ld=yes ;; openbsd* | bitrig*) @@ -9749,7 +9877,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9861,6 +9989,7 @@ _LT_EOF emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes + file_list_spec='@' ;; interix[3-9]*) @@ -9875,7 +10004,7 @@ _LT_EOF # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) @@ -9918,7 +10047,7 @@ _LT_EOF compiler_needs_object=yes ;; esac - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes @@ -9930,7 +10059,7 @@ _LT_EOF if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi @@ -9946,7 +10075,7 @@ _LT_EOF archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi @@ -10078,7 +10207,7 @@ _LT_EOF if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no @@ -10349,12 +10478,12 @@ fi cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. + # Microsoft Visual C++ or Intel C++ Compiler. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in - cl*) - # Native MSVC + cl* | icl*) + # Native MSVC or ICC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes @@ -10395,7 +10524,7 @@ fi fi' ;; *) - # Assume MSVC wrapper + # Assume MSVC and ICC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. @@ -10436,8 +10565,8 @@ fi output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -10471,7 +10600,7 @@ fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -10722,6 +10851,7 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes + file_list_spec='@' ;; osf3*) @@ -11414,7 +11544,7 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; @@ -11424,14 +11554,14 @@ cygwin* | mingw* | pw32* | cegcc*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl*) - # Native MSVC + *,cl* | *,icl*) + # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' @@ -11450,7 +11580,7 @@ cygwin* | mingw* | pw32* | cegcc*) done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -11487,7 +11617,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) - # Assume MSVC wrapper + # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; @@ -11520,7 +11650,7 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -12673,30 +12803,41 @@ striplib= old_striplib= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 printf %s "checking whether stripping libraries is possible... " >&6; } -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } +if test -z "$STRIP"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP"; then + if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + case $host_os in + darwin*) + # FIXME - insert some real tests, host_os isn't really good enough striplib="$STRIP -x" old_striplib="$STRIP -S" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + ;; + freebsd*) + if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then + old_striplib="$STRIP --strip-debug" + striplib="$STRIP --strip-unneeded" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - fi - ;; - *) - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 + fi + ;; + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - ;; - esac + ;; + esac + fi fi @@ -13466,8 +13607,8 @@ fi cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in - ,cl* | no,cl*) - # Native MSVC + ,cl* | no,cl* | ,icl* | no,icl*) + # Native MSVC or ICC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' @@ -13558,11 +13699,11 @@ fi output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else @@ -13597,6 +13738,7 @@ fi emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes + file_list_spec_CXX='@' ;; dgux*) @@ -13627,7 +13769,7 @@ fi archive_cmds_need_lc_CXX=no ;; - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes @@ -13764,7 +13906,7 @@ fi # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in @@ -13904,13 +14046,13 @@ fi archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' @@ -14567,7 +14709,7 @@ lt_prog_compiler_static_CXX= ;; esac ;; - freebsd* | dragonfly*) + freebsd* | dragonfly* | midnightbsd*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) @@ -14650,7 +14792,7 @@ lt_prog_compiler_static_CXX= lt_prog_compiler_static_CXX='-qstaticlink' ;; *) - case `$CC -V 2>&1 | sed 5q` in + case `$CC -V 2>&1 | $SED 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' @@ -15037,7 +15179,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) @@ -15045,7 +15187,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries ;; cygwin* | mingw* | cegcc*) case $cc_basename in - cl*) + cl* | icl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) @@ -15393,7 +15535,7 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) @@ -15402,14 +15544,14 @@ cygwin* | mingw* | pw32* | cegcc*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl*) - # Native MSVC + *,cl* | *,icl*) + # Native MSVC or ICC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' @@ -15428,7 +15570,7 @@ cygwin* | mingw* | pw32* | cegcc*) done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -15465,7 +15607,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) - # Assume MSVC wrapper + # Assume MSVC and ICC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; @@ -15497,7 +15639,7 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly*) +freebsd* | dragonfly* | midnightbsd*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -21008,6 +21150,129 @@ then : fi +# +# SSE +# + + +HAVE_SSE=0 + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSE support" >&5 +printf %s "checking for SSE support... " >&6; } + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + int main() { + __m128 x = _mm_set1_ps(1.0f); + x = _mm_add_ps(x, x); + return _mm_cvtss_f32(x) != 2.0f; + } + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + + HAVE_SSE=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + +# +# AVX +# + + +HAVE_AVX=0 + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX support" >&5 +printf %s "checking for AVX support... " >&6; } + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + int main() { + __m256d x = _mm256_set1_pd(1.0); + x = _mm256_add_pd(x, x); + return _mm256_cvtsd_f64(x) != 2.0; + } + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + + HAVE_AVX=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + +# +# AVX512 +# + + +HAVE_AVX512=1 + + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX-512 support" >&5 +printf %s "checking for AVX-512 support... " >&6; } + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include + int main() { + __m512d x = _mm512_set1_pd(1.0); + x = _mm512_add_pd(x, x); + return _mm512_cvtsd_f64(x) != 2.0; + } + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO" +then : + + HAVE_AVX512=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + + # # HWLOC # @@ -25392,6 +25657,7 @@ lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_q lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' @@ -25400,6 +25666,7 @@ want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' @@ -25574,6 +25841,7 @@ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ +FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ @@ -25582,7 +25850,6 @@ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ -AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ @@ -26304,6 +26571,9 @@ to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd +# A file(cmd) program that detects file types. +FILECMD=$lt_FILECMD + # An object symbol dumper. OBJDUMP=$lt_OBJDUMP @@ -26328,8 +26598,11 @@ sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR +# Flags to create an archive (by configure). +lt_ar_flags=$lt_ar_flags + # Flags to create an archive. -AR_FLAGS=$lt_AR_FLAGS +AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec @@ -26719,7 +26992,7 @@ ltmain=$ac_aux_dir/ltmain.sh # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '$q' "$ltmain" >> "$cfgfile" \ + $SED '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || From f7e79f4734df3448ed20637863b01c18d45104b9 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 16 Feb 2023 14:26:22 -0700 Subject: [PATCH 236/424] What using SSE/AVX for CHIPS? --- src/formats/base.hpp | 18 ++++++++++++ src/formats/chips.hpp | 64 ++++++++++++++++--------------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/formats/base.hpp b/src/formats/base.hpp index 585e629fd..ac31fefee 100644 --- a/src/formats/base.hpp +++ b/src/formats/base.hpp @@ -34,6 +34,24 @@ #include // For ntohs +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + +#include + +#endif + +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED + +#include + +#endif + +#if defined BF_AVX512_ENABLED && BF_AVX512_ENABLED + +#include + +#endif + #if defined __APPLE__ && __APPLE__ #include diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 982584e16..401aba811 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -107,47 +107,29 @@ class CHIPSProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan = 0; - //cout << pkt->src << ", " << pkt->nsrc << endl; - //cout << pkt->nchan << endl; - /* - // HACK TESTING disabled - for( ; channchan/4*4; chan+=4 ) { - __m128i tmp0 = ((__m128i*)&in[chan])[0]; - __m128i tmp1 = ((__m128i*)&in[chan])[1]; - __m128i tmp2 = ((__m128i*)&in[chan+1])[0]; - __m128i tmp3 = ((__m128i*)&in[chan+1])[1]; - __m128i tmp4 = ((__m128i*)&in[chan+2])[0]; - __m128i tmp5 = ((__m128i*)&in[chan+2])[1]; - __m128i tmp6 = ((__m128i*)&in[chan+3])[0]; - __m128i tmp7 = ((__m128i*)&in[chan+3])[1]; - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[0], tmp2); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+1)])[1], tmp3); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[0], tmp4); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+2)])[1], tmp5); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[0], tmp6); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*(chan+3)])[1], tmp7); - } - */ - //for( ; channchan; ++chan ) { - /* - for( ; chan<10; ++chan ) { // HACK TESTING - __m128i tmp0 = ((__m128i*)&in[chan])[0]; - __m128i tmp1 = ((__m128i*)&in[chan])[1]; - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[0], tmp0); - _mm_store_si128(&((__m128i*)&out[pkt->src + pkt->nsrc*chan])[1], tmp1); - } - */ - //if( pkt->src < 8 ) { // HACK TESTING - //for( ; chan<32; ++chan ) { // HACK TESTING - for( ; channchan; ++chan ) { // HACK TESTING - ::memcpy(&out[pkt->src + pkt->nsrc*chan], - &in[chan], sizeof(otype)); - //out[pkt->src + pkt->nsrc*chan] = in[chan]; - //::memset( - } - //} + //cout << pkt->src << ", " << pkt->nsrc << endl; + //cout << pkt->nchan << endl; + for( ; channchan; ++chan ) { +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED + __m256i data = _mm256_loadu_si256(reinterpret_cast(&in[chan])); + _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), + data); +#else +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; + aligned128_type* ddst = (aligned128_type*) &out[pkt->src + pkt->nsrc*chan]; + + __m128i lo = _mm_loadu_si128(reinterpret_cast(dsrc)); + __m128i hi = _mm_loadu_si128(reinterpret_cast(dsrc+1)); + + _mm_store_si128(reinterpret_cast<__m128i*>(ddst), lo); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), hi); +#else + ::memcpy(&out[pkt->src + pkt->nsrc*chan], + &in[chan], sizeof(otype)); +#endif +#endif + } } inline void blank_out_source(uint8_t* data, From 01808d2149b7ea01c4c56ee0f942f14c58067332 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 09:41:58 -0700 Subject: [PATCH 237/424] Merge the ethernet+IPv4+UDP headers into a single structure. Reuse the header memory allocation when sending packets. --- src/ib_verbs.hpp | 16 ++++++++---- src/packet_writer.cpp | 18 +++++++++---- src/packet_writer.hpp | 60 ++++++++++++++++++++++++------------------- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 0fc139d7f..22ae44a57 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -1063,11 +1063,17 @@ class Verbs { uint64_t offset; for(i=0; idtype)/8) * _nsamples; int npackets = in->shape[0]*in->shape[1]; - char* hdrs; - hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); + if( hdr_size != _last_size || npackets != _last_count ) { + if( _hdrs ) { + free(_hdrs) + } + + _last_size = hdr_size; + _last_count = npackets; + _hdr = (char*) malloc(npackets*hdr_size*sizeof(char)); + ::mlock(_hdr, npackets*hdr_size*sizeof(char)); + } + for(i=0; ishape[0]; i++) { hdr_base->seq = seq + i*seq_increment; for(j=0; jshape[1]; j++) { hdr_base->src = src + j*src_increment; - (*_filler)(hdr_base, _framecount, hdrs+hdr_size*(i*in->shape[1]+j)); + (*_filler)(hdr_base, _framecount, _hdrs+hdr_size*(i*in->shape[1]+j)); } _framecount++; } - _writer->send(hdrs, hdr_size, (char*) in->data, data_size, npackets); + _writer->send(_hdrs, hdr_size, (char*) in->data, data_size, npackets); this->update_stats_log(); - free(hdrs); return BF_STATUS_SUCCESS; } diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index bba615786..be82fa3be 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -189,15 +189,19 @@ class UDPPacketSender : public PacketWriterMethod { #if defined BF_VERBS_ENABLED && BF_VERBS_ENABLED #include "ib_verbs.hpp" +struct __attribute__((packed)) bf_udp_header { + bf_ethernet_hdr ethernet; + bf_ipv4_hdr ipv4; + bf_udp_hdr udp; +}; + class UDPVerbsSender : public PacketWriterMethod { - Verbs _ibv; - bf_ethernet_hdr _ethernet; - bf_ipv4_hdr _ipv4; - bf_udp_hdr _udp; - int _last_size; - int _last_count; - mmsghdr* _mmsg; - iovec* _iovs; + Verbs _ibv; + bf_udp_header _udp_header + int _last_size; + int _last_count; + mmsghdr* _mmsg; + iovec* _iovs; public: UDPVerbsSender(int fd) : PacketWriterMethod(fd), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), @@ -226,32 +230,28 @@ class UDPVerbsSender : public PacketWriterMethod { _last_count = npackets; _mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - _iovs = (struct iovec *) malloc(sizeof(struct iovec)*5*npackets); + _iovs = (struct iovec *) malloc(sizeof(struct iovec)*3*npackets); ::mlock(_mmsg, sizeof(struct mmsghdr)*npackets); - ::mlock(_iovs, sizeof(struct iovec)*5*npackets); + ::mlock(_iovs, sizeof(struct iovec)*3*npackets); } memset(_mmsg, 0, sizeof(struct mmsghdr)*npackets); if( (hdr_size + data_size) != _last_size ) { _last_size = hdr_size + data_size; - _ibv.get_ethernet_header(&_ethernet); - _ibv.get_ipv4_header(&_ipv4, _last_size); - _ibv.get_udp_header(&_udp, _last_size); + _ibv.get_ethernet_header(&(_udp_header.ethernet)); + _ibv.get_ipv4_header(&(_udp_header.ipv4), _last_size); + _ibv.get_udp_header(&(_udp_header.udp), _last_size); } for(int i=0; iget_core() << "\n"; } - virtual ~BFpacketwriter_impl() {} + inline ~BFpacketwriter_impl() { + if( _hdrs ) { + free(hdrs); + } + } inline void set_rate_limit(uint32_t rate_limit) { _writer->set_rate_limit(rate_limit); } inline void reset_rate_limit() { _writer->reset_rate_limit(); } inline void reset_counter() { _framecount = 0; } From ac40ad4ca87d34d2793c7595e7bc12a1f31022d7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 10:33:14 -0700 Subject: [PATCH 238/424] Typos. --- src/packet_writer.cpp | 4 ++-- src/packet_writer.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index dd7561076..a9a134d28 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -66,8 +66,8 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo info, _last_size = hdr_size; _last_count = npackets; - _hdr = (char*) malloc(npackets*hdr_size*sizeof(char)); - ::mlock(_hdr, npackets*hdr_size*sizeof(char)); + _hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); + ::mlock(_hdrs, npackets*hdr_size*sizeof(char)); } for(i=0; ishape[0]; i++) { diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index be82fa3be..900e6eca3 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -377,7 +377,7 @@ class BFpacketwriter_impl { } inline ~BFpacketwriter_impl() { if( _hdrs ) { - free(hdrs); + free(_hdrs); } } inline void set_rate_limit(uint32_t rate_limit) { _writer->set_rate_limit(rate_limit); } From 3dbc82bad83b436ff6349b38ca668fa4f749b0da Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 11:52:02 -0700 Subject: [PATCH 239/424] Missed one. --- src/packet_writer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index a9a134d28..71d356298 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -61,7 +61,7 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo info, if( hdr_size != _last_size || npackets != _last_count ) { if( _hdrs ) { - free(_hdrs) + free(_hdrs); } _last_size = hdr_size; From 6bf780712a8708519854f0294da3c25440b621e0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 12:43:38 -0700 Subject: [PATCH 240/424] Switch to pointer arithmetic. --- src/formats/drx.hpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 10058ccf9..987ccfc40 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -111,15 +111,17 @@ class DRXProcessor : virtual public PacketProcessor { size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; int samp = 0; - for( ; samp<4096; ++samp ) { // HACK TESTING - out[samp*pkt->nsrc + pkt->src] = in[samp]; - } + uint8_t const* in_ptr = in; + uint8_t* out_ptr = out + pkt->src; + for (int samp = 0; samp < 4096; ++samp) { + *out_ptr = *in_ptr; + in_ptr++; + out_ptr += pkt->nsrc; + } } inline void blank_out_source(uint8_t* data, @@ -127,13 +129,12 @@ class DRXProcessor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; + uint8_t* __restrict__ aligned_data = (uint8_t*) data; for( int t=0; t Date: Mon, 20 Feb 2023 12:46:00 -0700 Subject: [PATCH 241/424] Boilerplate update. --- src/formats/drx.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 987ccfc40..6d8bf9b18 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions From 6a02f67b7b57eaa79727050b4c687abe9d1e8894 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 12:51:50 -0700 Subject: [PATCH 242/424] Further cleanup. --- src/formats/drx.hpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 6d8bf9b18..dd6aad539 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -114,13 +114,10 @@ class DRXProcessor : virtual public PacketProcessor { uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - int samp = 0; - uint8_t const* in_ptr = in; - uint8_t* out_ptr = out + pkt->src; - for (int samp = 0; samp < 4096; ++samp) { - *out_ptr = *in_ptr; - in_ptr++; - out_ptr += pkt->nsrc; + for (int samp=0; samp<4096; ++samp) { + *(out + pkt->src) = *in; + in++; + out += pkt->nsrc; } } @@ -132,8 +129,9 @@ class DRXProcessor : virtual public PacketProcessor { uint8_t* __restrict__ aligned_data = (uint8_t*) data; for( int t=0; t Date: Mon, 20 Feb 2023 15:20:44 -0700 Subject: [PATCH 243/424] Revert. --- src/formats/drx.hpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index dd6aad539..53566d022 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -111,14 +111,15 @@ class DRXProcessor : virtual public PacketProcessor { size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - for (int samp=0; samp<4096; ++samp) { - *(out + pkt->src) = *in; - in++; - out += pkt->nsrc; - } + int samp = 0; + for( ; samp<4096; ++samp ) { // HACK TESTING + out[samp*pkt->nsrc + pkt->src] = in[samp]; + } } inline void blank_out_source(uint8_t* data, @@ -126,13 +127,12 @@ class DRXProcessor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*) data; + uint8_t* __restrict__ aligned_data = (uint8_t*)data; for( int t=0; t Date: Mon, 20 Feb 2023 15:21:46 -0700 Subject: [PATCH 244/424] Move bf_comb_udp_hdr here and fix a bug. --- src/ib_verbs.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 22ae44a57..84bf0bc25 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -157,6 +157,12 @@ struct __attribute__((packed)) bf_udp_hdr { uint16_t checksum; }; +struct __attribute__((packed)) bf_comb_udp_hdr { + bf_ethernet_hdr ethernet; + bf_ipv4_hdr ipv4; + bf_udp_hdr udp; +}; + class Verbs { int _fd; @@ -1059,7 +1065,6 @@ class Verbs { ibv_send_wr *s; int i; - uint32_t j; uint64_t offset; for(i=0; i Date: Mon, 20 Feb 2023 15:24:27 -0700 Subject: [PATCH 245/424] Moves and renames. --- src/packet_writer.cpp | 12 ++++++------ src/packet_writer.hpp | 36 +++++++++++++++--------------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index 71d356298..d89a41823 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -60,26 +60,26 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo info, int npackets = in->shape[0]*in->shape[1]; if( hdr_size != _last_size || npackets != _last_count ) { - if( _hdrs ) { - free(_hdrs); + if( _pkt_hdrs ) { + free(_pkt_hdrs); } _last_size = hdr_size; _last_count = npackets; - _hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); - ::mlock(_hdrs, npackets*hdr_size*sizeof(char)); + _pkt_hdrs = (char*) malloc(npackets*hdr_size*sizeof(char)); + ::mlock(_pkt_hdrs, npackets*hdr_size*sizeof(char)); } for(i=0; ishape[0]; i++) { hdr_base->seq = seq + i*seq_increment; for(j=0; jshape[1]; j++) { hdr_base->src = src + j*src_increment; - (*_filler)(hdr_base, _framecount, _hdrs+hdr_size*(i*in->shape[1]+j)); + (*_filler)(hdr_base, _framecount, _pkt_hdrs+hdr_size*(i*in->shape[1]+j)); } _framecount++; } - _writer->send(_hdrs, hdr_size, (char*) in->data, data_size, npackets); + _writer->send(_pkt_hdrs, hdr_size, (char*) in->data, data_size, npackets); this->update_stats_log(); return BF_STATUS_SUCCESS; diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 900e6eca3..7b977b416 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -189,19 +189,13 @@ class UDPPacketSender : public PacketWriterMethod { #if defined BF_VERBS_ENABLED && BF_VERBS_ENABLED #include "ib_verbs.hpp" -struct __attribute__((packed)) bf_udp_header { - bf_ethernet_hdr ethernet; - bf_ipv4_hdr ipv4; - bf_udp_hdr udp; -}; - class UDPVerbsSender : public PacketWriterMethod { - Verbs _ibv; - bf_udp_header _udp_header - int _last_size; - int _last_count; - mmsghdr* _mmsg; - iovec* _iovs; + Verbs _ibv; + bf_comb_udp_hdr _udp_hdr; + int _last_size; + int _last_count; + mmsghdr* _mmsg; + iovec* _iovs; public: UDPVerbsSender(int fd) : PacketWriterMethod(fd), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), @@ -238,16 +232,16 @@ class UDPVerbsSender : public PacketWriterMethod { if( (hdr_size + data_size) != _last_size ) { _last_size = hdr_size + data_size; - _ibv.get_ethernet_header(&(_udp_header.ethernet)); - _ibv.get_ipv4_header(&(_udp_header.ipv4), _last_size); - _ibv.get_udp_header(&(_udp_header.udp), _last_size); + _ibv.get_ethernet_header(&(_udp_hdr.ethernet)); + _ibv.get_ipv4_header(&(_udp_hdr.ipv4), _last_size); + _ibv.get_udp_header(&(_udp_hdr.udp), _last_size); } for(int i=0; iget_core() << "\n"; } inline ~BFpacketwriter_impl() { - if( _hdrs ) { - free(_hdrs); + if(_pkt_hdrs) { + free(_pkt_hdrs); } } inline void set_rate_limit(uint32_t rate_limit) { _writer->set_rate_limit(rate_limit); } From 647e2b3f0258b221cadf23651abbbc25482d76a8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 15:24:39 -0700 Subject: [PATCH 246/424] Catch by reference. --- src/Socket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Socket.cpp b/src/Socket.cpp index 136333f8f..cec457c24 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -671,7 +671,7 @@ void Socket::close() { try { this->set_promiscuous(false); } - catch( Socket::Error ) {} + catch( Socket::Error const& ) {} ::close(_fd); _fd = -1; _family = AF_UNSPEC; From 689312c95bd37939a8b40f82d968394376cfb7ad Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 15:38:10 -0700 Subject: [PATCH 247/424] There must have been some kind of non-printing character in there... --- src/formats/drx.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/formats/drx.hpp b/src/formats/drx.hpp index 53566d022..55ad4406e 100644 --- a/src/formats/drx.hpp +++ b/src/formats/drx.hpp @@ -115,10 +115,11 @@ class DRXProcessor : virtual public PacketProcessor { // However, they require aligned memory (otherwise segfault) uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; - - int samp = 0; - for( ; samp<4096; ++samp ) { // HACK TESTING - out[samp*pkt->nsrc + pkt->src] = in[samp]; + + for( int samp=0; samp<4096; ++samp ) { // HACK TESTING + *(out + pkt->src) = *in; + in++; + out += pkt->nsrc; } } @@ -127,11 +128,13 @@ class DRXProcessor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; + uint8_t* __restrict__ aligned_data = (uint8_t*) data; for( int t=0; t Date: Mon, 20 Feb 2023 15:59:23 -0700 Subject: [PATCH 248/424] More SSE. --- src/formats/chips.hpp | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 401aba811..b4ab9bba8 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -30,8 +30,6 @@ #include "base.hpp" -//#include // SSE - struct __attribute__((packed)) chips_hdr_type { uint8_t roach; // Note: 1-based uint8_t gbe; // (AKA tuning) @@ -111,19 +109,17 @@ class CHIPSProcessor : virtual public PacketProcessor { //cout << pkt->nchan << endl; for( ; channchan; ++chan ) { #if defined BF_AVX_ENABLED && BF_AVX_ENABLED - __m256i data = _mm256_loadu_si256(reinterpret_cast(&in[chan])); _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), - data); + _mm256_loadu_si256(reinterpret_cast(&in[chan]))); #else #if defined BF_SSE_ENABLED && BF_SSE_ENABLED const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; aligned128_type* ddst = (aligned128_type*) &out[pkt->src + pkt->nsrc*chan]; - __m128i lo = _mm_loadu_si128(reinterpret_cast(dsrc)); - __m128i hi = _mm_loadu_si128(reinterpret_cast(dsrc+1)); - - _mm_store_si128(reinterpret_cast<__m128i*>(ddst), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), hi); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst), + _mm_loadu_si128(reinterpret_cast(dsrc))); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), + _mm_loadu_si128(reinterpret_cast(dsrc+1))); #else ::memcpy(&out[pkt->src + pkt->nsrc*chan], &in[chan], sizeof(otype)); @@ -141,8 +137,22 @@ class CHIPSProcessor : virtual public PacketProcessor { otype* __restrict__ aligned_data = (otype*)data; for( int t=0; t(&aligned_data[src + nsrc*(c + nchan*t)]), + _mm256_setzero_si256()); +#else +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nchan*t)]; + + _mm_store_si128(reinterpret_cast<__m128i*>(ddst), + _mm_setzero_si128()); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), + _mm_setzero_si128(); +#else ::memset(&aligned_data[src + nsrc*(c + nchan*t)], 0, sizeof(otype)); +#endif +#endif } } } From 51fd2c7622f6e2c098f1636cca52eeab0f687a81 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 20 Feb 2023 16:00:31 -0700 Subject: [PATCH 249/424] Typo. --- src/formats/chips.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index b4ab9bba8..e293667fa 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -147,7 +147,7 @@ class CHIPSProcessor : virtual public PacketProcessor { _mm_store_si128(reinterpret_cast<__m128i*>(ddst), _mm_setzero_si128()); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_setzero_si128(); + _mm_setzero_si128()); #else ::memset(&aligned_data[src + nsrc*(c + nchan*t)], 0, sizeof(otype)); From 4452b71608eae4b00af9a9ed0226303edd4304fe Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 31 May 2023 09:51:02 -0600 Subject: [PATCH 250/424] Fixed AVX512 detection and report on SSE/AVX/AVX512 support. --- configure | 370 +++++++++++++++++---------------------------------- configure.ac | 8 +- 2 files changed, 126 insertions(+), 252 deletions(-) diff --git a/configure b/configure index 160cfe771..9bc4555e3 100755 --- a/configure +++ b/configure @@ -775,7 +775,6 @@ ac_ct_AR AR DLLTOOL OBJDUMP -FILECMD LN_S NM ac_ct_DUMPBIN @@ -3345,8 +3344,8 @@ esac -macro_version='2.4.7' -macro_revision='2.4.7' +macro_version='2.4.6' +macro_revision='2.4.6' @@ -4969,13 +4968,13 @@ else mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac - case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) - case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 @@ -5113,7 +5112,7 @@ esac fi fi - case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; @@ -5217,7 +5216,7 @@ else $as_nop lt_cv_sys_max_cmd_len=8192; ;; - bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -5260,7 +5259,7 @@ else $as_nop sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[ ]//'` + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi @@ -5465,114 +5464,6 @@ esac -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}file", so it can be a program name with args. -set dummy ${ac_tool_prefix}file; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_FILECMD+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test -n "$FILECMD"; then - ac_cv_prog_FILECMD="$FILECMD" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_FILECMD="${ac_tool_prefix}file" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -FILECMD=$ac_cv_prog_FILECMD -if test -n "$FILECMD"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FILECMD" >&5 -printf "%s\n" "$FILECMD" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_FILECMD"; then - ac_ct_FILECMD=$FILECMD - # Extract the first word of "file", so it can be a program name with args. -set dummy file; ac_word=$2 -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -printf %s "checking for $ac_word... " >&6; } -if test ${ac_cv_prog_ac_ct_FILECMD+y} -then : - printf %s "(cached) " >&6 -else $as_nop - if test -n "$ac_ct_FILECMD"; then - ac_cv_prog_ac_ct_FILECMD="$ac_ct_FILECMD" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - case $as_dir in #((( - '') as_dir=./ ;; - */) ;; - *) as_dir=$as_dir/ ;; - esac - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_FILECMD="file" - printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_FILECMD=$ac_cv_prog_ac_ct_FILECMD -if test -n "$ac_ct_FILECMD"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_FILECMD" >&5 -printf "%s\n" "$ac_ct_FILECMD" >&6; } -else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -fi - - if test "x$ac_ct_FILECMD" = x; then - FILECMD=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - FILECMD=$ac_ct_FILECMD - fi -else - FILECMD="$ac_cv_prog_FILECMD" -fi - - - - - - - if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 @@ -5716,7 +5607,7 @@ beos*) bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' - lt_cv_file_magic_cmd='$FILECMD -L' + lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; @@ -5750,14 +5641,14 @@ darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; -freebsd* | dragonfly* | midnightbsd*) +freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=$FILECMD + lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac @@ -5771,7 +5662,7 @@ haiku*) ;; hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=$FILECMD + lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' @@ -5818,7 +5709,7 @@ netbsd*) newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=$FILECMD + lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; @@ -6567,29 +6458,13 @@ esac fi : ${AR=ar} +: ${AR_FLAGS=cru} -# Use ARFLAGS variable as AR's operation code to sync the variable naming with -# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have -# higher priority because thats what people were doing historically (setting -# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS -# variable obsoleted/removed. - -test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr} -lt_ar_flags=$AR_FLAGS - - - - - - -# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override -# by AR_FLAGS because that was never working and AR_FLAGS is about to die. - @@ -7053,7 +6928,7 @@ esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. - lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'" + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" @@ -7071,20 +6946,20 @@ fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="$SED -n"\ +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\ +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ @@ -7108,7 +6983,7 @@ for ac_symprfx in "" "_"; do if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. - # Also find C++ and __fastcall symbols from MSVC++ or ICC, + # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ @@ -7126,9 +7001,9 @@ for ac_symprfx in "" "_"; do " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else - lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi - lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'" + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -7331,7 +7206,7 @@ case $with_sysroot in #( fi ;; #( /*) - lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"` + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( @@ -7457,7 +7332,7 @@ ia64-*-hpux*) ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; @@ -7478,7 +7353,7 @@ ia64-*-hpux*) printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; @@ -7490,7 +7365,7 @@ ia64-*-hpux*) ;; esac else - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; @@ -7516,7 +7391,7 @@ mips64*-*linux*) printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; @@ -7524,7 +7399,7 @@ mips64*-*linux*) emul="${emul}64" ;; esac - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; @@ -7532,7 +7407,7 @@ mips64*-*linux*) emul="${emul}ltsmip" ;; esac - case `$FILECMD conftest.$ac_objext` in + case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; @@ -7556,14 +7431,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `$FILECMD conftest.o` in + case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - case `$FILECMD conftest.o` in + case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; @@ -7671,7 +7546,7 @@ printf "%s\n" "$lt_cv_cc_needs_belf" >&6; } ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - case `$FILECMD conftest.o` in + case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) @@ -8454,8 +8329,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR $AR_FLAGS libconftest.a conftest.o" >&5 - $AR $AR_FLAGS libconftest.a conftest.o 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF @@ -8483,11 +8358,11 @@ printf "%s\n" "$lt_cv_ld_force_load" >&6; } darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) - case $MACOSX_DEPLOYMENT_TARGET,$host in - 10.[012],*|,*powerpc*-darwin[5-8]*) - _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - *) - _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + case ${MACOSX_DEPLOYMENT_TARGET},$host in + 10.[012],*|,*powerpc*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; + *) + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac @@ -8885,8 +8760,8 @@ esac ofile=libtool can_build_shared=yes -# All known linkers require a '.a' archive for static linking (except MSVC and -# ICC, which need '.lib'). +# All known linkers require a '.a' archive for static linking (except MSVC, +# which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld @@ -9398,7 +9273,7 @@ lt_prog_compiler_static= lt_prog_compiler_static='-qstaticlink' ;; *) - case `$CC -V 2>&1 | $SED 5q` in + case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' @@ -9821,15 +9696,15 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries case $host_os in cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time + # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using - # Microsoft Visual C++ or Intel C++ Compiler. + # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++ or ICC) + # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) @@ -9881,7 +9756,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... @@ -9993,7 +9868,6 @@ _LT_EOF emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes - file_list_spec='@' ;; interix[3-9]*) @@ -10008,7 +9882,7 @@ _LT_EOF # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) @@ -10051,7 +9925,7 @@ _LT_EOF compiler_needs_object=yes ;; esac - case `$CC -V 2>&1 | $SED 5q` in + case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes @@ -10063,7 +9937,7 @@ _LT_EOF if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi @@ -10079,7 +9953,7 @@ _LT_EOF archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi @@ -10211,7 +10085,7 @@ _LT_EOF if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no @@ -10482,12 +10356,12 @@ fi cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using - # Microsoft Visual C++ or Intel C++ Compiler. + # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in - cl* | icl*) - # Native MSVC or ICC + cl*) + # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes @@ -10528,7 +10402,7 @@ fi fi' ;; *) - # Assume MSVC and ICC wrapper + # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. @@ -10569,8 +10443,8 @@ fi output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -10604,7 +10478,7 @@ fi ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly* | midnightbsd*) + freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes @@ -10855,7 +10729,6 @@ printf "%s\n" "$lt_cv_irix_exported_symbol" >&6; } emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes - file_list_spec='@' ;; osf3*) @@ -11548,7 +11421,7 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; @@ -11558,14 +11431,14 @@ cygwin* | mingw* | pw32* | cegcc*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl* | *,icl*) - # Native MSVC or ICC + *,cl*) + # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' @@ -11584,7 +11457,7 @@ cygwin* | mingw* | pw32* | cegcc*) done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -11621,7 +11494,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) - # Assume MSVC and ICC wrapper + # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; @@ -11654,7 +11527,7 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly* | midnightbsd*) +freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -12807,41 +12680,30 @@ striplib= old_striplib= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 printf %s "checking whether stripping libraries is possible... " >&6; } -if test -z "$STRIP"; then - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -else - if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - old_striplib="$STRIP --strip-debug" - striplib="$STRIP --strip-unneeded" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - else - case $host_os in - darwin*) - # FIXME - insert some real tests, host_os isn't really good enough +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } - ;; - freebsd*) - if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then - old_striplib="$STRIP --strip-debug" - striplib="$STRIP --strip-unneeded" - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - fi - ;; - *) + else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } - ;; - esac - fi + fi + ;; + *) + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + ;; + esac fi @@ -13611,8 +13473,8 @@ fi cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in - ,cl* | no,cl* | ,icl* | no,icl*) - # Native MSVC or ICC + ,cl* | no,cl*) + # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_CXX=' ' @@ -13703,11 +13565,11 @@ fi output_verbose_link_cmd=func_echo_all archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" - archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" - module_expsym_cmds_CXX="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds_CXX="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" if test yes != "$lt_cv_apple_cc_single_mod"; then archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" - archive_expsym_cmds_CXX="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" + archive_expsym_cmds_CXX="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi else @@ -13742,7 +13604,6 @@ fi emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds_CXX='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes_CXX=yes - file_list_spec_CXX='@' ;; dgux*) @@ -13773,7 +13634,7 @@ fi archive_cmds_need_lc_CXX=no ;; - freebsd* | dragonfly* | midnightbsd*) + freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes @@ -13910,7 +13771,7 @@ fi # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds_CXX='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in @@ -14050,13 +13911,13 @@ fi archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) - case `$CC -V 2>&1 | $SED 5q` in + case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 no_undefined_flag_CXX=' -zdefs' @@ -14713,7 +14574,7 @@ lt_prog_compiler_static_CXX= ;; esac ;; - freebsd* | dragonfly* | midnightbsd*) + freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) @@ -14796,7 +14657,7 @@ lt_prog_compiler_static_CXX= lt_prog_compiler_static_CXX='-qstaticlink' ;; *) - case `$CC -V 2>&1 | $SED 5q` in + case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 lt_prog_compiler_pic_CXX='-KPIC' @@ -15183,7 +15044,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' + export_symbols_cmds_CXX='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) @@ -15191,7 +15052,7 @@ printf %s "checking whether the $compiler linker ($LD) supports shared libraries ;; cygwin* | mingw* | cegcc*) case $cc_basename in - cl* | icl*) + cl*) exclude_expsyms_CXX='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) @@ -15539,7 +15400,7 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; mingw* | cegcc*) @@ -15548,14 +15409,14 @@ cygwin* | mingw* | pw32* | cegcc*) ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; - *,cl* | *,icl*) - # Native MSVC or ICC + *,cl*) + # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' @@ -15574,7 +15435,7 @@ cygwin* | mingw* | pw32* | cegcc*) done IFS=$lt_save_ifs # Convert to MSYS style. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form @@ -15611,7 +15472,7 @@ cygwin* | mingw* | pw32* | cegcc*) ;; *) - # Assume MSVC and ICC wrapper + # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; @@ -15643,7 +15504,7 @@ dgux*) shlibpath_var=LD_LIBRARY_PATH ;; -freebsd* | dragonfly* | midnightbsd*) +freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then @@ -21241,7 +21102,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # -HAVE_AVX512=1 +HAVE_AVX512=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX-512 support" >&5 @@ -25772,7 +25633,6 @@ lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_q lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' -FILECMD='`$ECHO "$FILECMD" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' @@ -25781,7 +25641,6 @@ want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' -lt_ar_flags='`$ECHO "$lt_ar_flags" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' @@ -25956,7 +25815,6 @@ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ -FILECMD \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ @@ -25965,6 +25823,7 @@ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ +AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ @@ -26686,9 +26545,6 @@ to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd -# A file(cmd) program that detects file types. -FILECMD=$lt_FILECMD - # An object symbol dumper. OBJDUMP=$lt_OBJDUMP @@ -26713,11 +26569,8 @@ sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR -# Flags to create an archive (by configure). -lt_ar_flags=$lt_ar_flags - # Flags to create an archive. -AR_FLAGS=\${ARFLAGS-"\$lt_ar_flags"} +AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec @@ -27107,7 +26960,7 @@ ltmain=$ac_aux_dir/ltmain.sh # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - $SED '$q' "$ltmain" >> "$cfgfile" \ + sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || @@ -27397,6 +27250,21 @@ if test x$enable_native_arch != xno then : OPTIONS="$OPTIONS native" +fi +if test x$HAVE_SSE != x0 +then : + OPTIONS="$OPTIONS sse" + +fi +if test x$HAVE_AVX != x0 +then : + OPTIONS="$OPTIONS avx" + +fi +if test x$HAVE_AVX512 != x0 +then : + OPTIONS="$OPTIONS avx512" + fi if test x$HAVE_FLOAT128 != x0 then : diff --git a/configure.ac b/configure.ac index cd7bf0bc9..46ada4dc1 100644 --- a/configure.ac +++ b/configure.ac @@ -166,7 +166,7 @@ AC_DEFUN([AC_CHECK_AVX512], [ AC_MSG_RESULT([no]) ]) ]) -AC_SUBST([HAVE_AVX512], [1]) +AC_SUBST([HAVE_AVX512], [0]) AC_CHECK_AVX512 # @@ -502,6 +502,12 @@ AS_IF([test x$enable_cuda_debug != xno], [AC_SUBST([OPTIONS], ["$OPTIONS cuda_debug"])]) AS_IF([test x$enable_native_arch != xno], [AC_SUBST([OPTIONS], ["$OPTIONS native"])]) +AS_IF([test x$HAVE_SSE != x0], + [AC_SUBST([OPTIONS], ["$OPTIONS sse"])]) +AS_IF([test x$HAVE_AVX != x0], + [AC_SUBST([OPTIONS], ["$OPTIONS avx"])]) +AS_IF([test x$HAVE_AVX512 != x0], + [AC_SUBST([OPTIONS], ["$OPTIONS avx512"])]) AS_IF([test x$HAVE_FLOAT128 != x0], [AC_SUBST([OPTIONS], ["$OPTIONS float128"])]) AS_IF([test x$enable_map_cache != xno], From 9a628e76e865e895c9a54df63d1793d9d10d57c6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 31 May 2023 09:53:51 -0600 Subject: [PATCH 251/424] More explicit. --- configure | 6 ++++++ configure.ac | 3 +++ 2 files changed, 9 insertions(+) diff --git a/configure b/configure index 9bc4555e3..8f307530d 100755 --- a/configure +++ b/configure @@ -21049,6 +21049,8 @@ printf "%s\n" "yes" >&6; } else $as_nop + HAVE_SSE=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -21090,6 +21092,8 @@ printf "%s\n" "yes" >&6; } else $as_nop + HAVE_AVX=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } @@ -21131,6 +21135,8 @@ printf "%s\n" "yes" >&6; } else $as_nop + HAVE_AVX512=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } diff --git a/configure.ac b/configure.ac index 46ada4dc1..c727be91c 100644 --- a/configure.ac +++ b/configure.ac @@ -111,6 +111,7 @@ AC_DEFUN([AC_CHECK_SSE], [ AC_SUBST([HAVE_SSE], [1]) AC_MSG_RESULT([yes]) ], [ + AC_SUBST([HAVE_SSE], [0]) AC_MSG_RESULT([no]) ]) ]) @@ -137,6 +138,7 @@ AC_DEFUN([AC_CHECK_AVX], [ AC_SUBST([HAVE_AVX], [1]) AC_MSG_RESULT([yes]) ], [ + AC_SUBST([HAVE_AVX], [0]) AC_MSG_RESULT([no]) ]) ]) @@ -163,6 +165,7 @@ AC_DEFUN([AC_CHECK_AVX512], [ AC_SUBST([HAVE_AVX512], [1]) AC_MSG_RESULT([yes]) ], [ + AC_SUBST([HAVE_AVX512], [0]) AC_MSG_RESULT([no]) ]) ]) From 8a953cc54e5c3c4182bd60f719e18e5079262d3d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 09:22:42 -0600 Subject: [PATCH 252/424] Need to actually save files... --- python/bifrost/ring.py | 8 ------ src/Makefile.in | 61 ------------------------------------------ 2 files changed, 69 deletions(-) diff --git a/python/bifrost/ring.py b/python/bifrost/ring.py index e1d7342e1..e4335e1f6 100644 --- a/python/bifrost/ring.py +++ b/python/bifrost/ring.py @@ -118,11 +118,7 @@ def read(self, whence='earliest', guarantee=True): try: yield cur_seq cur_seq.increment() -<<<<<<< HEAD - except StopIteration: -======= except EndOfDataStop: ->>>>>>> 9a628e76e865e895c9a54df63d1793d9d10d57c6 return #def _data(self): # data_ptr = _get(self.lib.bfRingLockedGetData, self.obj) @@ -287,11 +283,7 @@ def read(self, span_size, stride=None, begin=0): with self.acquire(offset, span_size) as ispan: yield ispan offset += stride -<<<<<<< HEAD - except StopIteration: -======= except EndOfDataStop: ->>>>>>> 9a628e76e865e895c9a54df63d1793d9d10d57c6 return class SpanBase(object): diff --git a/src/Makefile.in b/src/Makefile.in index d89cd783c..8c4e09740 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -107,67 +107,6 @@ NVCCFLAGS += $(NVCC_GENCODE) #NVCCFLAGS += -Xcudafe "--diag_suppress=unrecognized_gcc_pragma" #NVCCFLAGS += --expt-relaxed-constexpr -<<<<<<< HEAD:src/Makefile -ifndef NODEBUG - CPPFLAGS += -DBF_DEBUG=1 - CXXFLAGS += -g - NVCCFLAGS += -g -endif - -LIB += -lgomp - -ifdef TRACE - CPPFLAGS += -DBF_TRACE_ENABLED=1 -endif - -ifdef NUMA - # Requires libnuma-dev to be installed - LIB += -lnuma - CPPFLAGS += -DBF_NUMA_ENABLED=1 -endif - -ifdef HWLOC - # Requires libhwloc-dev to be installed - LIB += -lhwloc - CPPFLAGS += -DBF_HWLOC_ENABLED=1 -endif - -ifdef VMA - # Requires Mellanox libvma to be installed - LIB += -lvma - CPPFLAGS += -DBF_VMA_ENABLED=1 -endif - -ifdef VERBS - # Requires Mellanox libvma to be installed - LIB += -libverbs - CPPFLAGS += -DBF_VERBS_ENABLED=1 -endif - -ifdef ALIGNMENT - CPPFLAGS += -DBF_ALIGNMENT=$(ALIGNMENT) -endif - -ifdef CUDA_DEBUG - NVCCFLAGS += -G -endif - -ifndef NOCUDA - CPPFLAGS += -DBF_CUDA_ENABLED=1 - LIB += -L$(CUDA_LIBDIR64) -L$(CUDA_LIBDIR) -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt -ifdef XGPU - CPPFLAGS += -DBF_XGPU_ENABLED=1 - LIB += -lxgpu -endif -endif - -ifndef ANY_ARCH - CXXFLAGS += -march=native - NVCCFLAGS += -Xcompiler "-march=native" -endif - -======= ->>>>>>> 9a628e76e865e895c9a54df63d1793d9d10d57c6:src/Makefile.in LIB_DIR = ../lib INC_DIR = . CPPFLAGS += -I. -I$(INC_DIR) -I$(CUDA_INCDIR) From 90886715fbb4dc0a1c97202909be158a776dd171 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 09:23:47 -0600 Subject: [PATCH 253/424] Revert to the ibverb-support version. --- tools/like_top.py | 12 +++++------- tools/pipeline2dot.py | 1 + 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tools/like_top.py b/tools/like_top.py index c4ad90ed9..89ca700dd 100755 --- a/tools/like_top.py +++ b/tools/like_top.py @@ -341,11 +341,10 @@ def main(args): ac = max([0.0, log['acquire_time']]) pr = max([0.0, log['process_time']]) re = max([0.0, log['reserve_time']]) - gb = max([0.0, log.get('gbps', 0.0)]) except KeyError: - ac, pr, re, gb = 0.0, 0.0, 0.0, 0.0 + ac, pr, re = 0.0, 0.0, 0.0 - blockList['%i-%s' % (pid, block)] = {'pid': pid, 'name':block, 'cmd': cmd, 'core': cr, 'acquire': ac, 'process': pr, 'reserve': re, 'total':ac+pr+re, 'gbps':gb} + blockList['%i-%s' % (pid, block)] = {'pid': pid, 'name':block, 'cmd': cmd, 'core': cr, 'acquire': ac, 'process': pr, 'reserve': re, 'total':ac+pr+re} ## Sort order = sorted(blockList, key=lambda x: blockList[x][sort_key], reverse=sort_rev) @@ -383,7 +382,7 @@ def main(args): k = _add_line(scr, k, 0, output, std) ### Header k = _add_line(scr, k, 0, ' ', std) - output = '%6s %15s %4s %5s %7s %7s %7s %7s %7s Cmd' % ('PID', 'Block', 'Core', '%CPU', 'Total', 'Acquire', 'Process', 'Reserve', 'Gbits/s') + output = '%6s %15s %4s %5s %7s %7s %7s %7s Cmd' % ('PID', 'Block', 'Core', '%CPU', 'Total', 'Acquire', 'Process', 'Reserve') csize = size[1]-len(output) if csize < 0: csize = 0 @@ -398,7 +397,7 @@ def main(args): c = '%5.1f' % c except KeyError: c = '%5s' % ' ' - output = '%6i %15s %4i %5s %7.3f %7.3f %7.3f %7.3f %7.3f %s' % (d['pid'], d['name'][:15], d['core'], c, d['total'], d['acquire'], d['process'], d['reserve'], d['gbps'], d['cmd'][:csize+3]) + output = '%6i %15s %4i %5s %7.3f %7.3f %7.3f %7.3f %s' % (d['pid'], d['name'][:15], d['core'], c, d['total'], d['acquire'], d['process'], d['reserve'], d['cmd'][:csize+3]) k = _add_line(scr, k, 0, output, std) if k >= size[0] - 1: break @@ -413,8 +412,7 @@ def main(args): except KeyboardInterrupt: pass - except Exception as err: - error = err + except Exception as error: exc_type, exc_value, exc_traceback = sys.exc_info() fileObject = StringIO() traceback.print_tb(exc_traceback, file=fileObject) diff --git a/tools/pipeline2dot.py b/tools/pipeline2dot.py index d2c772bd8..b6f20f640 100755 --- a/tools/pipeline2dot.py +++ b/tools/pipeline2dot.py @@ -353,3 +353,4 @@ def main(args): help='exclude associated blocks') args = parser.parse_args() main(args) + From aa064b1524a3f0b9407646bec4d69edf3922fec9 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 09:26:00 -0600 Subject: [PATCH 254/424] Focus on packet formats for now. --- src/Makefile.in | 8 +- src/beamform.cpp | 87 ---------- src/bf_xgpu.cpp | 284 ------------------------------ src/bifrost/beamform.h | 73 -------- src/bifrost/bf_xgpu.h | 25 --- src/cublas_beamform.cu | 373 ---------------------------------------- src/cublas_beamform.cuh | 37 ---- 7 files changed, 1 insertion(+), 886 deletions(-) delete mode 100644 src/beamform.cpp delete mode 100644 src/bf_xgpu.cpp delete mode 100644 src/bifrost/beamform.h delete mode 100644 src/bifrost/bf_xgpu.h delete mode 100644 src/cublas_beamform.cu delete mode 100644 src/cublas_beamform.cuh diff --git a/src/Makefile.in b/src/Makefile.in index 8c4e09740..360859f60 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -69,13 +69,7 @@ ifeq ($(HAVE_CUDA),1) reduce.o \ fir.o \ guantize.o \ - gunpack.o \ - beamform.o \ - cublas_beamform.o -ifdef XGPU - LIBBIFROST_OBJS += \ - bf_xgpu.o -endif + gunpack.o endif JIT_SOURCES ?= \ diff --git a/src/beamform.cpp b/src/beamform.cpp deleted file mode 100644 index 16d874222..000000000 --- a/src/beamform.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "cublas_beamform.cuh" - -extern "C" { - - -/* - * Initialize the beamformer library - */ - -BFstatus bfBeamformInitialize( - int gpudev, - int ninputs, - int nchans, - int ntimes, - int nbeams, - int ntime_blocks -) { - // TODO: array size checking - // TODO: use complex data types - cublas_beamform_init( - gpudev, - ninputs, - nchans, - ntimes, - nbeams, - ntime_blocks - ); - return BF_STATUS_SUCCESS; -} - -BFstatus bfBeamformRun(BFarray *in, BFarray *out, BFarray *weights) { - if (in->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - if (out->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - if (weights->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer weights buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - cublas_beamform((unsigned char *)in->data, (float *)out->data, (float *)weights->data); - return BF_STATUS_SUCCESS; -} - -BFstatus bfBeamformIntegrate(BFarray *in, BFarray *out, int ntimes_sum) { - if (in->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - if (out->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - cublas_beamform_integrate((float *)in->data, (float *)out->data, ntimes_sum); - return BF_STATUS_SUCCESS; -} - -BFstatus bfBeamformIntegrateSingleBeam(BFarray *in, BFarray *out, int ntimes_sum, int beam_index) { - if (in->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer input buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - if (out->space != BF_SPACE_CUDA) { - fprintf(stderr, "Beamformer output buffer must be in CUDA space\n"); - return BF_STATUS_INVALID_SPACE; - } - cublas_beamform_integrate_single_beam((float *)in->data, (float *)out->data, ntimes_sum, beam_index); - return BF_STATUS_SUCCESS; -} -} // C diff --git a/src/bf_xgpu.cpp b/src/bf_xgpu.cpp deleted file mode 100644 index 5a340247d..000000000 --- a/src/bf_xgpu.cpp +++ /dev/null @@ -1,284 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -extern "C" { - -static XGPUContext context; -static XGPUInfo info; - -/* - * Initialize the xGPU library by providing - * a pointer to the input and output data (on the host), - * and a GPU device ID - */ -BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev) { - int xgpu_error; - xgpuInfo(&info); - // Don't bother checking sizes if the input space is CUDA. - // We're not going to use these arrays anyway - if (in->space != BF_SPACE_CUDA) { - if (num_contiguous_elements(in) != info.vecLength) { - fprintf(stderr, "ERROR: xgpuInitialize: number of elements in != vecLength\n"); - fprintf(stderr, "number of elements in: %lu\n", num_contiguous_elements(in)); - fprintf(stderr, "vecLength: %llu\n", info.vecLength); - return BF_STATUS_INVALID_SHAPE; - } - if (num_contiguous_elements(out) != info.matLength) { - fprintf(stderr, "ERROR: xgpuInitialize: number of elements out != matLength\n"); - fprintf(stderr, "number of elements out: %lu\n", num_contiguous_elements(out)); - fprintf(stderr, "matLength: %llu\n", info.matLength); - return BF_STATUS_INVALID_SHAPE; - } - } - context.array_h = (SwizzleInput *)in->data; - context.array_len = info.vecLength; - context.matrix_h = (Complex *)out->data; - context.matrix_len = info.matLength; - if (in->space == BF_SPACE_CUDA) { - xgpu_error = xgpuInit(&context, gpu_dev | XGPU_DONT_REGISTER | XGPU_DONT_MALLOC_GPU); - } else { - xgpu_error = xgpuInit(&context, gpu_dev); - } - if (xgpu_error != XGPU_OK) { - fprintf(stderr, "ERROR: xgpuInitialize: call returned %d\n", xgpu_error); - return BF_STATUS_INTERNAL_ERROR; - } else { - return BF_STATUS_SUCCESS; - } -} - -/* - * Call the xGPU kernel. - * in : pointer to input data array on host - * out: pointer to output data array on host - * doDump : if 1, this is the last call in an integration, and results - * will be copied to the host. - */ -BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump) { - if (in->space == BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (out->space == BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - int xgpu_error; - context.array_h = (SwizzleInput *)in->data; - context.array_len = info.vecLength; - context.matrix_h = (Complex *)out->data; - context.matrix_len = info.matLength; - xgpu_error = xgpuCudaXengineSwizzle(&context, doDump ? SYNCOP_DUMP : SYNCOP_SYNC_TRANSFER); - if (doDump) { - xgpuClearDeviceIntegrationBuffer(&context); - } - if (xgpu_error != XGPU_OK) { - return BF_STATUS_INTERNAL_ERROR; - } else { - return BF_STATUS_SUCCESS; - } -} - -/* - * Call the xGPU kernel having pre-copied data to device memory. - * Note that this means xGPU can't take advantage of its inbuild - * copy/compute pipelining. - * in : pointer to input data array on device - * out: pointer to output data array on device - * doDump : if 1, this is the last call in an integration, and results - * will be copied to the host. - */ -static int newAcc = 1; // flush vacc on the first call -BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump) { - if (in->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (out->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - int xgpu_error; - context.array_h = (ComplexInput *)in->data; - context.array_len = info.vecLength; - context.matrix_h = (Complex *)out->data; - context.matrix_len = info.matLength; - xgpu_error = xgpuCudaXengineSwizzleKernel(&context, doDump ? SYNCOP_DUMP : 0, newAcc, - (SwizzleInput *)in->data, (Complex *)out->data); - - if (newAcc) { - newAcc = 0; - } - if (doDump) { - newAcc = 1; - } - if (xgpu_error != XGPU_OK) { - fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); - return BF_STATUS_INTERNAL_ERROR; - } else { - return BF_STATUS_SUCCESS; - } -} - -/* - * Given an xGPU accumulation buffer, grab a subset of visibilities from - * and gather them in a new buffer, in order - * chan x visibility x complexity [int32] (if transpose=0) - * or - * visibility x chan * complexity [int32] (if transpose!=0) - * BFarray *in : Pointer to a BFarray with storage in device memory, where xGPU results reside - * BFarray *in : Pointer to a BFarray with storage in device memory where collated visibilities should be written. - * BFarray *vismap : array of visibilities in [[polA, polB], [polC, polD], ... ] form. - * int nchan_sum: The number of frequency channels to sum over - */ -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum, int transpose) { - long long unsigned nvis = num_contiguous_elements(vismap); - int xgpu_error; - if (in->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (out->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (vismap->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (conj->space != BF_SPACE_CUDA) { - return BF_STATUS_UNSUPPORTED_SPACE; - } - if (num_contiguous_elements(conj) != nvis) { - return BF_STATUS_INVALID_SHAPE; - } - xgpu_error = xgpuCudaSubSelect(&context, (Complex *)in->data, (Complex *)out->data, (int *)vismap->data, (int *)conj->data, nvis, nchan_sum, transpose); - if (xgpu_error != XGPU_OK) { - fprintf(stderr, "ERROR: xgpuKernel: kernel call returned %d\n", xgpu_error); - return BF_STATUS_INTERNAL_ERROR; - } else { - return BF_STATUS_SUCCESS; - } -} - -/* Computes the triangular index of an (i,j) pair as shown here... - * NB: Output is valid only if i >= j. - * - * i=0 1 2 3 4.. - * +--------------- - * j=0 | 00 01 03 06 10 - * 1 | 02 04 07 11 - * 2 | 05 08 12 - * 3 | 09 13 - * 4 | 14 - * : - */ -int tri_index(int i, int j){ - return (i * (i+1))/2 + j; - } - -/* Returns index into the GPU's register tile ordered output buffer for the - * real component of the cross product of inputs in0 and in1. Note that in0 - * and in1 are input indexes (i.e. 0 based) and often represent antenna and - * polarization by passing (2*ant_idx+pol_idx) as the input number (NB: ant_idx - * and pol_idx are also 0 based). Return value is valid if in1 >= in0. The - * corresponding imaginary component is located xgpu_info.matLength words after - * the real component. - */ -int regtile_index(int in0, int in1, int nstand) { - int a0, a1, p0, p1; - int num_words_per_cell=4; - int quadrant, quadrant_index, quadrant_size, cell_index, pol_offset, index; - a0 = in0 >> 1; - a1 = in1 >> 1; - p0 = in0 & 1; - p1 = in1 & 1; - - // Index within a quadrant - quadrant_index = tri_index(a1/2, a0/2); - // Quadrant for this input pair - quadrant = 2*(a0&1) + (a1&1); - // Size of quadrant - quadrant_size = (nstand/2 + 1) * nstand/4; - // Index of cell (in units of cells) - cell_index = quadrant*quadrant_size + quadrant_index; - // Pol offset - pol_offset = 2*p1 + p0; - // Word index (in units of words (i.e. floats) of real component - index = (cell_index * num_words_per_cell) + pol_offset; - return index; - } - -BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj) { - int *ip_map = (int *)antpol_to_input->data; // indexed by stand, pol - int *bl_map = (int *)antpol_to_bl->data; // indexed by stand0, stand1, pol0, pol1 - int *conj_map = (int *)is_conj->data; // indexed by stand0, stand1, pol0, pol1 - int s0, s1, p0, p1, i0, i1; - int nstand, npol; - XGPUInfo xgpu_info; - xgpuInfo(&xgpu_info); - nstand = xgpu_info.nstation; - npol = xgpu_info.npol; - for (s0=0; s0 i0) { - bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i0, i1, nstand); - conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 1; - } else { - bl_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = regtile_index(i1, i0, nstand); - conj_map[s0*nstand*npol*npol + s1*npol*npol + p0*npol + p1] = 0; - } - } - } - } - } - return BF_STATUS_SUCCESS; -} - -/* - * Reorder a DP4A xGPU spec output into something more sane, throwing - * away unwanted baselines and re-concatenating real and imag parts in - * a reasonable way. - * Also remove conjugation weirdness so baselines a,b has conjugation a*conj(b) - */ -BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated) { - XGPUInfo xgpu_info; - xgpuInfo(&xgpu_info); - - int *output = (int *)reordered->data; - int *input_r = (int *)xgpu_output->data; - int *input_i = input_r + xgpu_info.matLength; - int *bl = (int *)baselines->data; - int *conj = (int *)is_conjugated->data; - int n_bl = num_contiguous_elements(baselines); - int xgpu_n_input = xgpu_info.nstation * xgpu_info.npol; - int n_chan = xgpu_info.nfrequency; - int i, c; - // number of entries per channel - size_t regtile_chan_len = 4 * 4 * xgpu_n_input/4 * (xgpu_n_input/4+1) / 2; - for (i=0; i -#include - -/* - * gpudev: GPU device ID to use - * ninputs: Number of inputs (single-polarization) to the beamformer - * nchans: Number of frequency channels - * ntimes: Number of time samples per beamforming call - * nbeams: Number of beams to generate. If using ntime_blocks > 0, beams=N will deliver N/2 beams. - * (See bfBeamformRun) - * ntime_blocks: Number of time blocks to output. Eg. if ntimes=1000 and ntime_blocks=10, the beamformer - will integrate over 100 samples per call. Set to 0 for no accumulation, in which case - raw beam voltages are output. - */ -BFstatus bfBeamformInitialize( - int gpudev, - int ninputs, - int nchans, - int ntimes, - int nbeams, - int ntime_blocks -); - -/* - * in: Pointer to ntime x nchan x ninputs x 4+4 bit data block - * out: Pointer to output data. - * If ntime_blocks > 0: !!!!UNTESTED, probably broken!!!! - * For the purposes of generating dynamic spectra, beam 2n and 2n+1 are considered - * to be two pols of the same pointing, and are cross-multipled and summed over - * ntimes/ntime_blocks to form the output array: - * nbeam/2 x ntime_blocks x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) - * Note that this means for N dual-pol beam pointings, the beamformer should be - * constructed with nbeams=2N. This isn't very efficient, but makes it easy to deal - * with arbitrary polarization orderings in the input buffer (suitable beamforming - * coefficients can make appropriate single-pol beam pairs). - * If ntime_blocks = 0: - * Data are returned as voltages, in order: - * nchan x nbeam x ntime x complex64 beamformer block - * - * weights -- pointer to nbeams x nchans x ninputs x complex64 weights - */ -BFstatus bfBeamformRun( - BFarray *in, - BFarray *out, - BFarray *weights -); - -/* - * Take the output of bfBeamformRun with ntime_blocks = 0, and perform transposing and integration - * of data, to deliver a time integrated dual-pol dynamic spectra of the form: - * nbeam/2 x ntime/ntimes_sum x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) - * I.e., the format which would be returned by bfBeamformRun if ntime_blocks > 0 - */ -BFstatus bfBeamformIntegrate( - BFarray *in, - BFarray *out, - int ntimes_sum -); - -/* - * Take the output of bfBeamformRun with ntime_blocks = 0, and - * deliver a time integrated dual-pol dynamic spectra for a single beam of the form: - * ntime/ntimes_sum x nchan x 4 x float32 (powers, XX, YY, re(XY, im(XY)) - * - * ntime_sum: the number of times to integrate - * beam_index: The beam to select (if beam_index=N, beams N and N+1 will be used as a polarization pair) - */ -BFstatus bfBeamformIntegrateSingleBeam( - BFarray *in, - BFarray *out, - int ntimes_sum, - int beam_index -); diff --git a/src/bifrost/bf_xgpu.h b/src/bifrost/bf_xgpu.h deleted file mode 100644 index b8f21b783..000000000 --- a/src/bifrost/bf_xgpu.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BF_XGPU_H_INCLUDE_GUARD_ -#define BF_XGPU_H_INCLUDE_GUARD_ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -//TODO: figure out how to make ctypesgen to the right thing with python generation -//#if(BF_XGPU_ENABLED) -BFstatus bfXgpuInitialize(BFarray *in, BFarray *out, int gpu_dev); -BFstatus bfXgpuCorrelate(BFarray *in, BFarray *out, int doDump); -BFstatus bfXgpuKernel(BFarray *in, BFarray *out, int doDump); -BFstatus bfXgpuSubSelect(BFarray *in, BFarray *out, BFarray *vismap, BFarray *conj, int nchan_sum, int transpose); -BFstatus bfXgpuGetOrder(BFarray *antpol_to_input, BFarray *antpol_to_bl, BFarray *is_conj); -BFstatus bfXgpuReorder(BFarray *xgpu_output, BFarray *reordered, BFarray *baselines, BFarray *is_conjugated); -//#endif // BF_XGPU_ENABLED - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // BF_XGPU_H_INCLUDE_GUARD diff --git a/src/cublas_beamform.cu b/src/cublas_beamform.cu deleted file mode 100644 index 7e2b7bdbb..000000000 --- a/src/cublas_beamform.cu +++ /dev/null @@ -1,373 +0,0 @@ -#include -#include -#include - -#include "cublas_beamform.cuh" - -__constant__ float lut[16] = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, -8.0, -7.0, -6.0, -5.0, -4.0, -3.0, -2.0, -1.0}; - -// Transpose time x chan x pol x 4+4 bit to -// chan x pol x time x 32+32 bit float -__global__ void trans_4bit_to_float(unsigned char *in, - float *out, - int n_pol, - int n_chan, - int n_time - ) { - //long long int tid = blockDim.y*blockDim.x*blockIdx.y + blockDim.x*blockIdx.x + threadIdx.x; - //int pol = tid % n_pol; - //int chan = (tid / n_pol) % n_chan; - //int time = (tid / (n_pol * n_chan)); - int time = blockIdx.x; - int chan = blockIdx.y; - int pol = TRANSPOSE_POL_BLOCK_SIZE*threadIdx.x; - unsigned char *in_off = in + time*n_chan*n_pol + chan*n_pol + pol; // 4+4 bit - float *out_off = out + 2*( chan*n_pol*n_time + pol*n_time + time); // 32+32 bit - //long long int old_index = time*n_chan*n_pol + chan*n_pol + pol; - //long long int new_index = chan*n_pol*n_time + pol*n_time + time; - float real, imag; - unsigned char temp; - #pragma unroll - for (int i=0; i> 4]; - //imag = lut[in[old_index+i] & 0b1111]; - //out[2*(new_index+i)] = real; - //out[2*(new_index+i)+1] = imag; - real = lut[(temp >> 4) & 0b1111]; - imag = lut[temp & 0b1111]; - out_off[0] = real; - out_off[1] = imag; - out_off += 2*n_time; - } -} - -// Transpose chan x beam x pol x time x 32+32 float to -// beam x time[part-summed] x chan x [XX,YY,XY*_r,XY*_i] x 32 float -// Each thread deals with two pols of a beam, and sums over n_time_sum time samples -// n_beam is the _output_ number of beams. I.e., the number of dual-pol beams -__global__ void trans_output_and_sum(float *in, - float *out, - int n_chan, - int n_beam, - int n_time, - int n_time_sum - ) { - int chan = blockIdx.x; - int beam = blockIdx.y; - int time = threadIdx.x; - // n_beam here is a dual pol beam - // input is: chan x beam x pol [2] x time x complexity - long long int old_index = 2*(chan*n_beam*2*n_time + beam*2*n_time + time*n_time_sum); // start index for n_time/n_time_sum samples - // output is: beam x time x chan x pol-products [4] - long long int new_index = 4*(beam*(n_time / n_time_sum)*n_chan + time*n_chan + chan); - float xx=0., yy=0., xy_r=0., xy_i=0.; // accumulator registers - float x_r, x_i, y_r, y_i; - int t; - for (t=0; t 0 - int ninputs; // Number of inputs (ants * pols) - int npols; // Number of polarizations per antenna - int nchans; // Number of channels input - int ntimes; // Number of time samples input - int nbeams; // Number of beams output - int ntimeblocks; // Number of time samples to keep after summation -}; - -static struct beamform_context context; - -void cublas_beamform_destroy(){ - cudaFree(context.in32_d); - if (context.ntimeblocks > 0) { - cudaFree(context.out_d); - } -} - -void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks) { - context.gpu_device = device; - gpuErrchk( cudaSetDevice(context.gpu_device) ); - gpuErrchk(cudaStreamCreate(&(context.stream))); - gpuBLASchk(cublasCreate(&(context.handle))); - gpuBLASchk(cublasSetStream(context.handle, context.stream)); - gpuBLASchk(cublasSetPointerMode(context.handle, CUBLAS_POINTER_MODE_HOST)); - //gpuBLASchk(cublasSetPointerMode(context.handle, CUBLAS_POINTER_MODE_DEVICE)); - gpuBLASchk(cublasSetMathMode(context.handle, CUBLAS_TENSOR_OP_MATH)); - - context.ninputs = ninputs; - context.nchans = nchans; - context.ntimes = ntimes; - context.nbeams = nbeams; - context.ntimeblocks = ntimeblocks; - - // Internally allocate intermediate buffers - gpuErrchk( cudaMalloc(&context.in32_d, ninputs * nchans * ntimes * 2 * sizeof(float)) ); - //gpuErrchk( cudaMemcpy(context.in32_d, in32_h, ninputs * nchans * ntimes * 2 * sizeof(float), cudaMemcpyHostToDevice) ); - // If the context is initialized with ntimeblocks=0, then we do no summing so don't - // need the intermediate buffer allocated internally. - if (ntimeblocks > 0) { - gpuErrchk( cudaMalloc(&context.out_d, ntimes * nchans * nbeams * 2 * sizeof(float)) ); - } -} - -void cublas_beamform(unsigned char *in4_d, float *out_d, float *weights_d) { - // Transpose input data and promote to float. - // CUBLAS doesn't support float coeffs with int8 data - dim3 transBlockGrid(context.ntimes, context.nchans); - dim3 transThreadGrid(context.ninputs / TRANSPOSE_POL_BLOCK_SIZE); - trans_4bit_to_float<<>>( - in4_d, - context.in32_d, - context.ninputs, - context.nchans, - context.ntimes - ); - cudaStreamSynchronize(context.stream); - - // If we are integrating beam powers, put the - // GEM output in the internal intermediate - // buffer. If not, then write beamformer output - // to the address given by the user. - float *gem_out_d; - if (context.ntimeblocks > 0) { - gem_out_d = context.out_d; - } else { - gem_out_d = out_d; - } - - // Beamform using GEMM - float alpha = 1.0; - float beta = 0.0; - // GEMM: - // C <= alpha*AB + beta*C - // alpha = 1.0 - // beta = 0.0 - // A matrix: beamforming coeffs (NBEAMS * NANTS) - // B matrix: data matrix (NANTS * NTIMES) - - /* - gpuBLASchk(cublasGemmStridedBatchedEx( - context.handle, - CUBLAS_OP_T, // transpose A? - CUBLAS_OP_T, // transpose B? - context.nbeams, // m - context.ntimes, // n - context.ninputs, // k - // Coeffs: [nchans x] nbeams x ninputs (m x k) - &alpha, // alpha - weights_d, // A - CUDA_C_32F, // A type - context.ninputs, // Lda - context.nbeams*context.ninputs,// strideA : stride size - // Data: [nchans x] ninputs x ntimes (k x n) - context.in32_d, // B - CUDA_C_32F, // B type - context.ntimes, // Ldb - context.ninputs*context.ntimes,// strideB : stride size - &beta, // beta - // Results - gem_out_d, // C - CUDA_C_32F, // Ctype - context.nbeams, // Ldc - context.nbeams*context.ntimes,// Stride C - context.nchans, // batchCount - CUDA_C_32F, // compute type - CUBLAS_GEMM_DEFAULT_TENSOR_OP // algo - )); - */ - - gpuBLASchk(cublasGemmStridedBatchedEx( - context.handle, - CUBLAS_OP_N, // transpose A? - CUBLAS_OP_N, // transpose B? - context.ntimes, // n - context.nbeams, // m - context.ninputs, // k - &alpha, // alpha - // - // Data: [nchans x] ninputs x ntimes (k x n) - context.in32_d, // B - CUDA_C_32F, // B type - context.ntimes, // Ldb - context.ninputs*context.ntimes,// strideB : stride size - // - // Coeffs: [nchans x] nbeams x ninputs (m x k) - weights_d, // A - CUDA_C_32F, // A type - context.ninputs, // Lda - context.nbeams*context.ninputs,// strideA : stride size - // - &beta, // beta - // Results - gem_out_d, // C - CUDA_C_32F, // Ctype - context.ntimes, // Ldc - context.nbeams*context.ntimes,// Stride C - context.nchans, // batchCount - CUDA_C_32F, // compute type - CUBLAS_GEMM_DEFAULT_TENSOR_OP // algo - )); - cudaStreamSynchronize(context.stream); - - // Optionally: - if (context.ntimeblocks > 0) { - // Create XX, YY, XY beam powers. - // Sum over `ntimes_sum` samples - // Write to the user-provided output buffer - int ntimes_sum = context.ntimes / context.ntimeblocks; - dim3 sumBlockGrid(context.nchans, context.nbeams/2); - dim3 sumThreadGrid(context.ntimes / ntimes_sum); - trans_output_and_sum<<>>( - gem_out_d, - out_d, - context.nchans, - context.nbeams/2, - context.ntimes, - ntimes_sum - ); - cudaStreamSynchronize(context.stream); - } -} - -/* Take input data of form - nchan x nbeam x time x complex64 [i.e. the output of cublas_beamform], - sum over ``ntimes_sum``, interpret beams `2n` and `2n+1` as a dual pol pair, - and generate an output array of form - nbeam x ntime / ntime_sum x nchan x nbeam / 2 x 4 x complex64. - The last 4-element axis holds XX, YY, Re(XY), Im(XY -*/ -void cublas_beamform_integrate(float *in_d, float *out_d, int ntimes_sum) { - // Create XX, YY, XY beam powers. - // Sum over `ntimes_sum` samples - dim3 sumBlockGrid(context.nchans, context.nbeams/2); - dim3 sumThreadGrid(context.ntimes / ntimes_sum); - trans_output_and_sum<<>>( - in_d, - out_d, - context.nchans, - context.nbeams/2, - context.ntimes, - ntimes_sum - ); -} - -void cublas_beamform_integrate_single_beam(float *in_d, float *out_d, int ntimes_sum, int beam_index) { - // Create XX, YY, XY beam powers. - // Sum over `ntimes_sum` samples - dim3 sumBlockGrid(context.nchans); - dim3 sumThreadGrid(context.ntimes / ntimes_sum); - trans_output_and_sum_single_beam<<>>( - in_d, - out_d, - context.nchans, - context.nbeams/2, - context.ntimes, - ntimes_sum, - beam_index - ); -} diff --git a/src/cublas_beamform.cuh b/src/cublas_beamform.cuh deleted file mode 100644 index a33919e3b..000000000 --- a/src/cublas_beamform.cuh +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _CUBLAS_BEAMFORM_H -#define _CUBLAS_BEAMFORM_H - -#include -#include -#include - -// Transpose time x chan x pol x 4+4 bit to -#define TRANSPOSE_POL_BLOCK_SIZE 8 -// chan x pol x time x 32+32 bit float -__global__ void trans_4bit_to_float(unsigned char *in, - float *out, - int n_pol, - int n_chan, - int n_time - ); - -// Transpose chan x beam x pol x pol x 32+32 float to -// beam x time[part-summed] x chan x [XX,YY,XY*_r,XY*_i] x 32 float -// Each thread deals with two pols of a beam, and sums over n_time_sum time samples -__global__ void trans_output_and_sum(float *in, - float *out, - int n_chan, - int n_beam, - int n_time, - int n_time_sum - ); - -__global__ void complex2pow(float *in, float *out, int N); - -void cublas_beamform_destroy(); -void cublas_beamform(unsigned char *in4_d, float *sum_out_d, float *weights_d); -void cublas_beamform_integrate(float *in_d, float *sum_out_d, int ntimes_sum); -void cublas_beamform_integrate_single_beam(float *in_d, float *sum_out_d, int ntimes_sum, int beam_index); -void cublas_beamform_init(int device, int ninputs, int nchans, int ntimes, int nbeams, int ntimeblocks); - -#endif From 4e1d3180175f4f13fd86d17259ac03c478a33dc5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 09:31:56 -0600 Subject: [PATCH 255/424] Focus on packet formats for now. --- .gitignore | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index 31f0cd390..65ddc68fe 100644 --- a/.gitignore +++ b/.gitignore @@ -109,9 +109,3 @@ target/ # Benchmarking files test/benchmarks/development_vs_gpuspec/with_bifrost/ test/benchmarks/development_vs_gpuspec/without_bifrost/ - -# ctags files -python/bifrost/tags -python/tags -src/tags -tags From 49722302b0b39858d6899de4892cee06f1bcbec1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 09:39:38 -0600 Subject: [PATCH 256/424] Move verbs buffer control into configure. --- configure.ac | 7 +++++++ src/bifrost/config.h.in | 1 + src/ib_verbs.hpp | 6 ++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c727be91c..588ae1baa 100644 --- a/configure.ac +++ b/configure.ac @@ -220,6 +220,13 @@ AS_IF([test x$enable_verbs != xno], [AC_SUBST([HAVE_VERBS], [1]) LIBS="$LIBS -libverbs"])]) +AC_ARG_WITH([verbs_npktbuf], + [AS_HELP_STRING([--with-verbs-npktbuf=N], + [default Infiniband verbs buffer size in packets (default=8192)])], + [], + [with_verbs_npktbuf=8192]) +AC_SUBST([VERBS_NPKTBUF], [$with_verbs_npktbuf]) + # # RDMA # diff --git a/src/bifrost/config.h.in b/src/bifrost/config.h.in index c20559a15..1e3e52ed4 100644 --- a/src/bifrost/config.h.in +++ b/src/bifrost/config.h.in @@ -63,6 +63,7 @@ extern "C" { #define BF_HWLOC_ENABLED @HAVE_HWLOC@ #define BF_VMA_ENABLED @HAVE_VMA@ #define BF_VERBS_ENABLED @HAVE_VERBS@ +#define BF_VERBS_NPKTBUF @VERBS_NPKTBUF@ #define BF_RDMA_ENABLED @HAVE_RDMA@ #define BF_RDMA_MAXMEM @RDMA_MAXMEM@ diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 2d4176e30..2c3fab598 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -28,6 +28,8 @@ #pragma once +#include + #include #include #include @@ -58,10 +60,6 @@ #define BF_VERBS_NQP 1 #endif -#ifndef BF_VERBS_NPKTBUF -#define BF_VERBS_NPKTBUF 32768 -#endif - #ifndef BF_VERBS_WCBATCH #define BF_VERBS_WCBATCH 16 #endif From d07b153f019068568ff14c74f2e2685ddc8179dc Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:24:30 -0600 Subject: [PATCH 257/424] lwa352_vbeam_* -> vbeam_* --- src/formats/formats.hpp | 2 +- src/formats/{lwa352_vbeam.hpp => vbeam.hpp} | 10 +++++----- src/packet_writer.hpp | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) rename src/formats/{lwa352_vbeam.hpp => vbeam.hpp} (86%) diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 225811895..e52aefd39 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -37,4 +37,4 @@ #include "ibeam.hpp" #include "snap2.hpp" #include "pbeam.hpp" -#include "lwa352_vbeam.hpp" +#include "vbeam.hpp" diff --git a/src/formats/lwa352_vbeam.hpp b/src/formats/vbeam.hpp similarity index 86% rename from src/formats/lwa352_vbeam.hpp rename to src/formats/vbeam.hpp index e7c7fe402..29f98d749 100644 --- a/src/formats/lwa352_vbeam.hpp +++ b/src/formats/vbeam.hpp @@ -30,7 +30,7 @@ #include "base.hpp" -struct __attribute__((packed)) lwa352_vbeam_hdr_type { +struct __attribute__((packed)) vbeam_hdr_type { uint64_t sync_word; uint64_t sync_time; uint64_t time_tag; @@ -41,14 +41,14 @@ struct __attribute__((packed)) lwa352_vbeam_hdr_type { uint32_t npol; }; -class LWA352VBeamHeaderFiller : virtual public PacketHeaderFiller { +class VBeamHeaderFiller : virtual public PacketHeaderFiller { public: - inline int get_size() { return sizeof(lwa352_vbeam_hdr_type); } + inline int get_size() { return sizeof(vbeam_hdr_type); } inline void operator()(const PacketDesc* hdr_base, BFoffset framecount, char* hdr) { - lwa352_vbeam_hdr_type* header = reinterpret_cast(hdr); - memset(header, 0, sizeof(lwa352_vbeam_hdr_type)); + vbeam_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(vbeam_hdr_type)); header->sync_word = 0xAABBCCDD00000000L; header->time_tag = htobe64(hdr_base->seq); diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index b1272f5fb..acab4d31c 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -485,14 +485,14 @@ class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { } }; -class BFpacketwriter_lwa352_vbeam_impl : public BFpacketwriter_impl { +class BFpacketwriter_vbeam_impl : public BFpacketwriter_impl { ProcLog _type_log; public: - inline BFpacketwriter_lwa352_vbeam_impl(PacketWriterThread* writer, + inline BFpacketwriter_vbeam_impl(PacketWriterThread* writer, int nsamples) : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CF32), _type_log((std::string(writer->get_name())+"/type").c_str()) { - _filler = new LWA352VBeamHeaderFiller(); + _filler = new VBeamHeaderFiller(); _type_log.update("type : %s\n", "tbf"); } }; @@ -526,8 +526,8 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, nsamples = 4096; } else if( format == std::string("tbf") ) { nsamples = 6144; - } else if( std::string(format).substr(0, 13) == std::string("lwa352_vbeam_") ) { - // e.g. "lwa352_vbeam_184" is a 184-channel voltage beam" + } else if( std::string(format).substr(0, 6) == std::string("vbeam_") ) { + // e.g. "vbeam_184" is a 184-channel voltage beam" int nchan = std::atoi((std::string(format).substr(13, std::string(format).length())).c_str()); nsamples = 2*nchan; // 2 polarizations. Natively 32-bit floating complex (see implementation class) } @@ -579,8 +579,8 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( format == std::string("tbf") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), *obj = 0); - } else if( std::string(format).substr(0, 13) == std::string("lwa352_vbeam_") ) { - BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_lwa352_vbeam_impl(writer, nsamples), + } else if( std::string(format).substr(0, 6) == std::string("vbeam_") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_vbeam_impl(writer, nsamples), *obj = 0); } else { return BF_STATUS_UNSUPPORTED; From b37bf9bdc44225dba45eea6f74397fef6cfb1bc5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:33:31 -0600 Subject: [PATCH 258/424] Remove some debugging. --- src/packet_capture.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 115d72505..454e610a4 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -268,12 +268,9 @@ BFpacketcapture_status BFpacketcapture_impl::recv() { ret = BF_CAPTURE_CONTINUED; } } - BF_PRINTD("_bufs.size(): " << _bufs.size()); if( _bufs.size() == 2 ) { - BF_PRINTD("Committing buffer"); this->commit_buf(); } - BF_PRINTD("Rseerving buffer"); this->reserve_buf(); } else { From 9d67edb1f8feeaed91799cb60181a852b42bfbb8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:34:27 -0600 Subject: [PATCH 259/424] Catch here as well. --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 2c3fab598..fb5b0b5ea 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -430,7 +430,7 @@ class Verbs { _verbs.send_mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; _verbs.send_mr_buf = (uint8_t *) ::mmap(NULL, _verbs.send_mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - check_error(_verbs.send_mr_buf == MAP_FAILED, + check_error(_verbs.send_mr_buf == MAP_FAILED ? -1 : 0, "allocate memory region buffer"); check_error(::mlock(_verbs.send_mr_buf, _verbs.send_mr_size), "lock memory region buffer"); From bc6add7cb1e72432b37c4e548dcccf5e22e53d65 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:40:42 -0600 Subject: [PATCH 260/424] Attempt to add a non-AVX version of the snap2 packet processor. --- src/formats/snap2.hpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index ea93244b3..228405b93 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -163,21 +163,28 @@ class SNAP2Processor : virtual public PacketProcessor { // Output buffer order is chans * npol_total * complexity // Spacing with which channel chunks are copied depends // on the total number of channels/pols in the system + int c=0; +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED __m256i *dest_p; __m256i vecbuf[2]; uint64_t *in64 = (uint64_t *)in; - int c; dest_p = (__m256i *)(out + (words_per_chan_out * (pkt_chan)) + pol_offset_out); +#endif //if((pol_offset_out == 0) && (pkt_chan==0) && ((pkt->seq % 120)==0) ){ // fprintf(stderr, "nsrc: %d seq: %d, dest_p: %p obuf idx %d, obuf offset %lu, nseq_per_obuf %d, seq0 %d, nbuf: %d\n", pkt->nsrc, pkt->seq, dest_p, obuf_idx, obuf_offset, nseq_per_obuf, seq0, nbuf); //} for(c=0; cnchan; c++) { +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED vecbuf[0] = _mm256_set_epi64x(in64[3], in64[2], in64[1], in64[0]); vecbuf[1] = _mm256_set_epi64x(in64[7], in64[6], in64[5], in64[4]); _mm256_stream_si256(dest_p, vecbuf[0]); _mm256_stream_si256(dest_p+1, vecbuf[1]); in64 += 8; dest_p += words_per_chan_out; +#else + ::memcpy(&out[pkt->src + pkt->nsrc*chan], + &in[c], sizeof(otype)); +#endif } } From 74320677fb1e07fc2e0b6d77d941e463b8218c82 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:42:47 -0600 Subject: [PATCH 261/424] Now in formats/base.hpp. --- src/formats/snap2.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 228405b93..f34a82c4f 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -30,9 +30,6 @@ #include "base.hpp" -#include // SSE -#include - // TODO: parameterize somewhere. This isn't // related to the packet formatting #define PIPELINE_NPOL 704 From d9736b400336ab5560ea6141eee0c233da5be129 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:43:47 -0600 Subject: [PATCH 262/424] Revert to the ibverb-support version. --- src/formats/cor.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/cor.hpp b/src/formats/cor.hpp index c7c7b0787..bf1660ded 100644 --- a/src/formats/cor.hpp +++ b/src/formats/cor.hpp @@ -72,7 +72,7 @@ class CORDecoder : virtual public PacketDecoder { pkt->sync = pkt_hdr->sync_word; pkt->time_tag = be64toh(pkt_hdr->time_tag); pkt->decimation = be32toh(pkt_hdr->navg); - pkt->seq = pkt->time_tag / pkt->decimation; + pkt->seq = pkt->time_tag / 196000000 / (pkt->decimation / 100); pkt->nsrc = _nsrc; pkt->src = (stand0*(2*(nstand-1)+1-stand0)/2 + stand1 + 1 - _src0)*nserver \ + (server - 1); From 70bf2918ddfb2c5ae0989bf699f3b1ec08c7152f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:45:37 -0600 Subject: [PATCH 263/424] Ugh. --- src/formats/snap2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index f34a82c4f..2e5672853 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -179,7 +179,7 @@ class SNAP2Processor : virtual public PacketProcessor { in64 += 8; dest_p += words_per_chan_out; #else - ::memcpy(&out[pkt->src + pkt->nsrc*chan], + ::memcpy(&out[pkt->src + pkt->nsrc*c], &in[c], sizeof(otype)); #endif } From 21210ba5d4ba44ddb03533939c1a3e3a8bea7875 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 1 Jun 2023 13:48:47 -0600 Subject: [PATCH 264/424] This block seems to be causing problems in CI. --- src/packet_capture.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 454e610a4..60d3c3bf7 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -91,15 +91,6 @@ int PacketCaptureThread::run(uint64_t seq_beg, BF_PRINTD("HERE" << " " << _pkt.seq << " < " << seq_beg); _have_pkt = false; if( less_than(_pkt.seq, seq_beg) ) { - // If lots [TODO: what is lots] of packets are late - // return. Otherwise a seq reset can lead to being stuck - // here endlessly counting late packets. - if( less_than(_pkt.seq + 1000*nseq_per_obuf, seq_beg) ) { - fprintf(stderr, "Breaking from packet receive because of so many late packets\n"); - _have_pkt = true; - ret = CAPTURE_SUCCESS; - break; - } ++_stats.nlate; _stats.nlate_bytes += _pkt.payload_size; ++_src_stats[_pkt.src].nlate; From 08e947bc98e8df25857707f3a65e3664be7b0f92 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 18 Jul 2023 16:46:03 -0600 Subject: [PATCH 265/424] Add in writer support for 8+8-bit complex DRX8. --- src/formats/drx8.hpp | 159 ++++++++++++++++++++++++++++++++++++++++ src/formats/formats.hpp | 3 +- src/packet_writer.hpp | 7 +- 3 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 src/formats/drx8.hpp diff --git a/src/formats/drx8.hpp b/src/formats/drx8.hpp new file mode 100644 index 000000000..c39fac09b --- /dev/null +++ b/src/formats/drx8.hpp @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2023, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +#define DRX8_FRAME_SIZE 8224 + +struct __attribute__((packed)) drx8_hdr_type { + uint32_t sync_word; + uint32_t frame_count_word; + uint32_t seconds_count; + uint16_t decimation; + uint16_t time_offset; + uint64_t time_tag; + uint32_t tuning_word; + uint32_t flags; +}; + +class DRX8Decoder : virtual public PacketDecoder { + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->sync == 0x5CDEC0DE && + pkt->src >= 0 && + pkt->src < _nsrc && + pkt->time_tag >= 0 && + (((_nsrc == 4) && + (pkt->tuning > 0 && + pkt->tuning1 > 0)) || + (_nsrc == 2 && + (pkt->tuning > 0 || + pkt->tuning1 > 0))) && + pkt->valid_mode == 0); + } +public: + DRX8Decoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size != DRX_FRAME_SIZE ) { + return false; + } + const drx8_hdr_type* pkt_hdr = (drx8_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(drx8_hdr_type); + int pld_size = pkt_size - sizeof(drx8_hdr_type); + int pkt_id = pkt_hdr->frame_count_word & 0xFF; + pkt->beam = (pkt_id & 0x7) - 1; + int pkt_tune = ((pkt_id >> 3) & 0x7) - 1; + int pkt_pol = ((pkt_id >> 7) & 0x1); + pkt_id = (pkt_tune << 1) | pkt_pol; + pkt->sync = pkt_hdr->sync_word; + pkt->time_tag = be64toh(pkt_hdr->time_tag) - be16toh(pkt_hdr->time_offset); + pkt->seq = pkt->time_tag / be16toh(pkt_hdr->decimation) / 4096; + pkt->nsrc = _nsrc; + pkt->src = pkt_id - _src0; + if( pkt->src / 2 == 0 ) { + pkt->tuning = be32toh(pkt_hdr->tuning_word); + } else { + pkt->tuning1 = be32toh(pkt_hdr->tuning_word); + } + pkt->decimation = be16toh(pkt_hdr->decimation); + pkt->valid_mode = ((pkt_id >> 6) & 0x1); + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + return this->valid_packet(pkt); + } +}; + + +class DRX8Processor : virtual public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][pkt->src] += nbyte; + int payload_size = pkt->payload_size; + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + uint16_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; + uint16_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + + for( int samp=0; samp<4096; ++samp ) { // HACK TESTING + *(out + pkt->src) = *in; + in++; + out += pkt->nsrc; + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + uint16_t* __restrict__ aligned_data = (uint16_t*) data; + for( int t=0; t(hdr); + memset(header, 0, sizeof(drx8_hdr_type)); + + header->sync_word = 0x5CDEC0DE; + // ID is stored in the lowest 8 bits; bit 2 is reserved for DRX8 vs DRX + header->frame_count_word = htobe32((uint32_t) ((hdr_base->src & 0xBF) | 0x40) << 24); + header->decimation = htobe16((uint16_t) hdr_base->decimation); + header->time_offset = 0; + header->time_tag = htobe64(hdr_base->seq); + header->tuning_word = htobe32(hdr_base->tuning); + } +}; diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 28d24e221..14ed3ad9e 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,6 +32,7 @@ #include "cor.hpp" #include "vdif.hpp" #include "drx.hpp" +#include "drx8.hpp" #include "tbn.hpp" #include "tbf.hpp" #include "ibeam.hpp" diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 7b977b416..55c904852 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -512,6 +512,8 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, nsamples = 512; } else if( format == std::string("drx") ) { nsamples = 4096; + } else if( format == std::string("drx8") ) { + nsamples = 4096; } else if( format == std::string("tbf") ) { nsamples = 6144; } @@ -560,6 +562,9 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( format == std::string("drx") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_drx_impl(writer, nsamples), *obj = 0); + } else if( format == std::string("drx8") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_drx8_impl(writer, nsamples), + *obj = 0); } else if( format == std::string("tbf") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), *obj = 0); From e9a9a4bab80a2d0e9420e169a1ba84ec6f873885 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 18 Jul 2023 16:55:49 -0600 Subject: [PATCH 266/424] Missed a couple of declaration changes. --- src/formats/drx8.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/formats/drx8.hpp b/src/formats/drx8.hpp index c39fac09b..cf1f38289 100644 --- a/src/formats/drx8.hpp +++ b/src/formats/drx8.hpp @@ -113,8 +113,8 @@ class DRX8Processor : virtual public PacketProcessor { // Note: Using these SSE types allows the compiler to use SSE instructions // However, they require aligned memory (otherwise segfault) - uint16_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; - uint16_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + uint16_t const* __restrict__ in = (uint16_t const*)pkt->payload_ptr; + uint16_t* __restrict__ out = (uint16_t* )&obufs[obuf_idx][obuf_offset]; for( int samp=0; samp<4096; ++samp ) { // HACK TESTING *(out + pkt->src) = *in; From 516b9d0a543191a7c84e3034baa6a3d50f2718e7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 18 Jul 2023 20:10:46 -0600 Subject: [PATCH 267/424] Add BFpacketwriter_drx8_impl. --- src/packet_writer.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 55c904852..4b774661b 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -473,6 +473,18 @@ class BFpacketwriter_drx_impl : public BFpacketwriter_impl { } }; +class BFpacketwriter_drx8_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_drx8_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI8), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new DRX8HeaderFiller(); + _type_log.update("type : %s\n", "drx8"); + } +}; + class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { ProcLog _type_log; public: From f9223b88a846be2b182e548fb0ec44438fc38af0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 19 Jul 2023 07:20:12 -0600 Subject: [PATCH 268/424] Add in support for DRX8 capture. --- python/bifrost/packet_capture.py | 6 +- src/bifrost/packet_capture.h | 6 +- src/packet_capture.cpp | 9 ++- src/packet_capture.hpp | 98 +++++++++++++++++++++++++++++++- 4 files changed, 114 insertions(+), 5 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 36ef53ad3..760debd98 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -66,6 +66,10 @@ def set_drx(self, fnc): self._ref_cache['drx'] = _bf.BFpacketcapture_drx_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetDRX( self.obj, self._ref_cache['drx'])) + def set_drx8(self, fnc): + self._ref_cache['drx8'] = _bf.BFpacketcapture_drx8_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetDRX8( + self.obj, self._ref_cache['drx8'])) class _CaptureBase(BifrostObject): @staticmethod diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index 06a9b70e1..f599824fc 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -52,6 +52,8 @@ typedef int (*BFpacketcapture_tbn_sequence_callback)(BFoffset, BFoffset, int, in int, void const**, size_t*); typedef int (*BFpacketcapture_drx_sequence_callback)(BFoffset, BFoffset, int, int, int, int, void const**, size_t*); +typedef int (*BFpacketcapture_drx8_sequence_callback)(BFoffset, BFoffset, int, int, int, + int, void const**, size_t*); typedef struct BFpacketcapture_callback_impl* BFpacketcapture_callback; @@ -71,6 +73,8 @@ BFstatus bfPacketCaptureCallbackSetTBN(BFpacketcapture_callback obj, BFpacketcapture_tbn_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, BFpacketcapture_drx_sequence_callback callback); +BFstatus bfPacketCaptureCallbackSetDRX8(BFpacketcapture_callback obj, + BFpacketcapture_drx8_sequence_callback callback); // Capture setup diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 0e5b7af2c..bbe8526a1 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -174,6 +174,13 @@ BFstatus bfPacketCaptureCallbackSetDRX(BFpacketcapture_callback obj, return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetDRX8(BFpacketcapture_callback obj, + BFpacketcapture_drx8_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_drx8(callback); + return BF_STATUS_SUCCESS; +} + BFpacketcapture_status BFpacketcapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index d74a9997b..7f648c9ae 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2020, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -379,11 +379,12 @@ class BFpacketcapture_callback_impl { BFpacketcapture_vdif_sequence_callback _vdif_callback; BFpacketcapture_tbn_sequence_callback _tbn_callback; BFpacketcapture_drx_sequence_callback _drx_callback; + BFpacketcapture_drx8_sequence_callback _drx8_callback; public: BFpacketcapture_callback_impl() : _chips_callback(NULL), _ibeam_callback(NULL), _pbeam_callback(NULL), _cor_callback(NULL), _vdif_callback(NULL), _tbn_callback(NULL), - _drx_callback(NULL) {} + _drx_callback(NULL), _drx8_callback(NULL) {} inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } @@ -425,6 +426,9 @@ class BFpacketcapture_callback_impl { } inline BFpacketcapture_drx_sequence_callback get_drx() { return _drx_callback; + } + inline BFpacketcapture_drx8_sequence_callback get_drx8() { + return _drx8_callback; } }; @@ -1131,6 +1135,89 @@ class BFpacketcapture_drx_impl : public BFpacketcapture_impl { } }; +class BFpacketcapture_drx8_impl : public BFpacketcapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_drx8_sequence_callback _sequence_callback; + + BFoffset _time_tag; + uint16_t _decim; + int _chan1; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + _seq = round_nearest(pkt->seq, _nseq_per_buf); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return ( (pkt->tuning != _chan0) + || (pkt->tuning1 != _chan1) + || (pkt->decimation != _decim) ); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + *time_tag = pkt->time_tag; + _time_tag = pkt->time_tag; + _chan0 = pkt->tuning; + _chan1 = pkt->tuning1; + if( _nsrc == 2 ) { + _chan0 = std::max(_chan0, _chan1); + _chan1 = 0; + } + _decim = pkt->decimation; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + *time_tag, + _decim, + _chan0, + _chan1, + _nsrc, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "chan1 : " << _chan1 << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFpacketcapture_drx8_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_drx8()), + _decim(0), _chan1(0) { + _decoder = new DRX8Decoder(nsrc, src0); + _processor = new DRX8Processor(); + _type_log.update("type : %s\n", "drx8"); + } +}; + BFstatus BFpacketcapture_create(BFpacketcapture* obj, const char* format, int fd, @@ -1180,6 +1267,8 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, max_payload_size = TBN_FRAME_SIZE; } else if( format == std::string("drx") ) { max_payload_size = DRX_FRAME_SIZE; + } else if( format == std::string("drx8") ) { + max_payload_size = DRX8_FRAME_SIZE; } PacketCaptureMethod* method; @@ -1239,6 +1328,11 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, buffer_ntime, slot_ntime, sequence_callback), *obj = 0); + } else if( format == std::string("drx8") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_drx8_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); } else { return BF_STATUS_UNSUPPORTED; } From 8859ca44cbbba726d86c23b75bcc8d93a90d2536 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 19 Jul 2023 07:27:46 -0600 Subject: [PATCH 269/424] Add missing set_drx8 method. --- src/packet_capture.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 7f648c9ae..a2551c3d7 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -426,6 +426,9 @@ class BFpacketcapture_callback_impl { } inline BFpacketcapture_drx_sequence_callback get_drx() { return _drx_callback; + } + inline void set_drx8(BFpacketcapture_drx8_sequence_callback callback) { + _drx8_callback = callback; } inline BFpacketcapture_drx8_sequence_callback get_drx8() { return _drx8_callback; From 02e2e941d4337973e192e7d28f0eca645f78e717 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 20 Jul 2023 15:19:30 -0600 Subject: [PATCH 270/424] Clean up header filler. --- src/formats/snap2.hpp | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 2e5672853..c1a17b600 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,11 +30,6 @@ #include "base.hpp" -// TODO: parameterize somewhere. This isn't -// related to the packet formatting -#define PIPELINE_NPOL 704 -#define PIPELINE_NCHAN 32 - // All entries are network (i.e. big) endian struct __attribute__((packed)) snap2_hdr_type { uint64_t seq; // Spectra counter == packet counter @@ -122,8 +117,6 @@ class SNAP2Decoder : virtual public PacketDecoder { }; class SNAP2Processor : virtual public PacketProcessor { -protected: - int _pipeline_nchan = PIPELINE_NCHAN; public: inline void operator()(const PacketDesc* pkt, uint64_t seq0, @@ -205,20 +198,21 @@ class SNAP2Processor : virtual public PacketProcessor { class SNAP2HeaderFiller : virtual public PacketHeaderFiller { public: - inline int get_size() { return sizeof(chips_hdr_type); } + inline int get_size() { return sizeof(snap2_hdr_type); } inline void operator()(const PacketDesc* hdr_base, BFoffset framecount, char* hdr) { - chips_hdr_type* header = reinterpret_cast(hdr); - memset(header, 0, sizeof(chips_hdr_type)); + snap2_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(snap2_hdr_type)); + + header->seq = htobe64(hdr_base->seq); + header->npol = 2; + header->npol_tot = 2; + header->nchan = hdr_base->nchan; + header->nchan_tot = hdr_base->nchan * hdr_base->nsrc; + header->chan_block_id = hdr-base->src; + header->chan0 = htons(hdr_base->chan0); + header->pol0 = 0; - header->roach = hdr_base->src + 1; - header->gbe = hdr_base->tuning; - header->nchan = hdr_base->nchan; - header->nsubband = 1; // Should be changable? - header->subband = 0; // Should be changable? - header->nroach = hdr_base->nsrc; - header->chan0 = htons(hdr_base->chan0); - header->seq = htobe64(hdr_base->seq); } }; From e783a2463b8be3f0b698beecefee0d765a45e723 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 20 Jul 2023 15:21:43 -0600 Subject: [PATCH 271/424] Re-enable missing source blanking. --- src/formats/snap2.hpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index c1a17b600..10aee3788 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -179,20 +179,18 @@ class SNAP2Processor : virtual public PacketProcessor { } inline void blank_out_source(uint8_t* data, - int src, - int nsrc, - int nchan, - int nseq) { - //fprintf(stderr, "TRYING TO BLANK OUT A SOURCE WITH MISSING PACKETS. BUT BLANKING NOT IMPLEMENTED\n"); - //typedef aligned256_type otype; - //fprintf(stderr, "You really better not be here\n"); - //otype* __restrict__ aligned_data = (otype*)data; - //for( int t=0; t Date: Thu, 20 Jul 2023 15:33:34 -0600 Subject: [PATCH 272/424] Ugh. --- src/formats/snap2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 10aee3788..2b9a85322 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -208,7 +208,7 @@ class SNAP2HeaderFiller : virtual public PacketHeaderFiller { header->npol_tot = 2; header->nchan = hdr_base->nchan; header->nchan_tot = hdr_base->nchan * hdr_base->nsrc; - header->chan_block_id = hdr-base->src; + header->chan_block_id = hdr_base->src; header->chan0 = htons(hdr_base->chan0); header->pol0 = 0; From a5cb91d6f8dcf98c171dcd0fd0033603ffabd989 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 25 Aug 2023 08:12:57 -0600 Subject: [PATCH 273/424] Use the TBF "unassigned" field to hold the number of stands. --- src/formats/tbf.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/formats/tbf.hpp b/src/formats/tbf.hpp index 289eda2b4..2c73b699d 100644 --- a/src/formats/tbf.hpp +++ b/src/formats/tbf.hpp @@ -37,7 +37,7 @@ struct __attribute__((packed)) tbf_hdr_type { uint32_t frame_count_word; uint32_t seconds_count; uint16_t first_chan; - uint16_t unassinged; + uint16_t nstand; uint64_t time_tag; }; @@ -55,6 +55,7 @@ class TBFHeaderFiller : virtual public PacketHeaderFiller { header->frame_count_word = htobe32((framecount & 0xFFFFFF) \ | ((uint32_t) 0x01 << 24)); header->first_chan = htons(hdr_base->src); + header->nstand = htobe16(hdr_base->nsrc); header->time_tag = htobe64(hdr_base->seq); } }; From c8c99b14c60300e8161572776d909b4619c31d9b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 25 Aug 2023 08:19:44 -0600 Subject: [PATCH 274/424] Update the TBF format to take the number of stands in after an underscore. --- src/packet_writer.hpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 4b774661b..b2806b7fb 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -486,14 +486,16 @@ class BFpacketwriter_drx8_impl : public BFpacketwriter_impl { }; class BFpacketwriter_tbf_impl : public BFpacketwriter_impl { + int16_t _nstand; ProcLog _type_log; public: inline BFpacketwriter_tbf_impl(PacketWriterThread* writer, int nsamples) : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI4), - _type_log((std::string(writer->get_name())+"/type").c_str()) { + _nstand(0), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new TBFHeaderFiller(); - _type_log.update("type : %s\n", "tbf"); + _nstand = nsamples / 2 / 12; + _type_log.update("type : %s%i\n", "tbf", _nstand); } }; @@ -517,7 +519,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( std::string(format).substr(0, 5) == std::string("pbeam") ) { int nchan = std::atoi((std::string(format).substr(7, std::string(format).length())).c_str()); nsamples = 4*nchan; - } else if(std::string(format).substr(0, 4) == std::string("cor_") ) { + } else if( std::string(format).substr(0, 4) == std::string("cor_") ) { int nchan = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); nsamples = 4*nchan; } else if( format == std::string("tbn") ) { @@ -526,8 +528,9 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, nsamples = 4096; } else if( format == std::string("drx8") ) { nsamples = 4096; - } else if( format == std::string("tbf") ) { - nsamples = 6144; + } else if( std::string(format).substr(0, 4) == std::string("tbf_") ) { + int nstand = std::atoi((std::string(format).substr(4, std::string(format).length())).c_str()); + nsamples = nstand*2*12; } PacketWriterMethod* method; @@ -577,7 +580,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else if( format == std::string("drx8") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_drx8_impl(writer, nsamples), *obj = 0); - } else if( format == std::string("tbf") ) { + } else if( std::string(format).substr(0, 4) == std::string("tbf_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_tbf_impl(writer, nsamples), *obj = 0); } else { From cf4dbc469b3a6d9c444d8305e053efc92e1cce81 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 28 Aug 2023 10:40:27 -0600 Subject: [PATCH 275/424] Drop the frame size since it is now variable. --- src/formats/tbf.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/formats/tbf.hpp b/src/formats/tbf.hpp index 2c73b699d..af90066ce 100644 --- a/src/formats/tbf.hpp +++ b/src/formats/tbf.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,8 +30,6 @@ #include "base.hpp" -#define TBF_FRAME_SIZE 6168 - struct __attribute__((packed)) tbf_hdr_type { uint32_t sync_word; uint32_t frame_count_word; From c9665032f79977f35024ef2cd9c77c1657f13b1b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 5 Sep 2023 10:50:48 -0600 Subject: [PATCH 276/424] Add a helpful message for https://github.com/ledatelescope/bifrost/issues/196. --- src/ib_verbs.hpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 84bf0bc25..d30ef67a1 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -553,8 +553,8 @@ class Verbs { qp_init.send_cq = _verbs.send_cq[i]; qp_init.recv_cq = _verbs.cq[i]; _verbs.qp[i] = ibv_create_qp(_verbs.pd, &qp_init); - check_null(_verbs.qp[i], - "create queue pair"); + check_null_qp(_verbs.qp[i], + "create queue pair"); // Transition queue pair to INIT state ibv_qp_attr qp_attr; @@ -961,6 +961,23 @@ class Verbs { throw Verbs::Error(ss.str()); } } + inline void check_null_qp(void* ptr, std::string what) { + if( ptr == NULL ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + if( errno == EPERM ) { + ss << " Do you need to set 'options ibverbs disable_raw_qp_enforcement=1' " + << "or add the CAP_NET_RAW capability?"; + } + throw Verbs::Error(ss.str()); + } + } public: class Error : public std::runtime_error { typedef std::runtime_error super_t; From 3d24679dcaeadef0db5db9d35c89359b424b6955 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 10:30:26 -0600 Subject: [PATCH 277/424] Protect 192.168.1.100 from matching 192.168.1.10. --- src/ib_verbs.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index d30ef67a1..457e3e8fe 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -237,7 +237,7 @@ class Verbs { char* end; sprintf(cmd, "ping -c 1 %s", ip_str); FILE* fp = popen(cmd, "r"); - sprintf(cmd, "ip neigh | grep %s | awk '{print $5}'", ip_str); + sprintf(cmd, "ip neigh | grep -e \"%s \" | awk '{print $5}'", ip_str); fp = popen(cmd, "r"); if( fgets(line, sizeof(line), fp) != NULL) { if( line[strlen(line)-1] == '\n' ) { From 00c65eeee713591b9d31d4cb33fa166f2690689c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 10:31:15 -0600 Subject: [PATCH 278/424] Cleanup send flags. --- src/ib_verbs.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 457e3e8fe..b76f835fa 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -664,10 +664,10 @@ class Verbs { } // Link the work requests to send queue - uint32_t send_flags = 0; + uint32_t send_flags = IBV_SEND_SIGNALED; #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD if( _verbs.offload_csum ) { - send_flags = IBV_SEND_IP_CSUM; + send_flags |= IBV_SEND_IP_CSUM; } #endif From d294fade84caeb18dca8015f8c11e06fe91d95e3 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 10:33:59 -0600 Subject: [PATCH 279/424] Cleanup send work request linking. --- src/ib_verbs.hpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index b76f835fa..b00d47307 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -671,17 +671,14 @@ class Verbs { } #endif - for(i=0; i Date: Thu, 14 Sep 2023 14:33:24 -0600 Subject: [PATCH 280/424] Work on splitting Verbs into a send side and a receive side. --- src/ib_verbs.hpp | 381 +-------------------- src/ib_verbs_send.hpp | 772 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 776 insertions(+), 377 deletions(-) create mode 100644 src/ib_verbs_send.hpp diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index b00d47307..506be63d9 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2020-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -46,14 +46,6 @@ #include -// Catch for older InfiniBand verbs installs that do not have the -// IBV_RAW_PACKET_CAP_IP_CSUM feature check. -#ifndef IBV_RAW_PACKET_CAP_IP_CSUM -#define BF_ENABLE_VERBS_OFFLOAD 0 -#else -#define BF_ENABLE_VERBS_OFFLOAD 1 -#endif - #ifndef BF_VERBS_NQP #define BF_VERBS_NQP 1 #endif @@ -74,11 +66,6 @@ struct bf_ibv_recv_pkt{ uint32_t length; }; -struct bf_ibv_send_pkt{ - ibv_send_wr wr; - ibv_sge sg; -}; - struct bf_ibv_flow { ibv_flow_attr attr; ibv_flow_spec_eth eth; @@ -102,65 +89,6 @@ struct bf_ibv { bf_ibv_recv_pkt* pkt_buf; bf_ibv_recv_pkt* pkt; bf_ibv_recv_pkt* pkt_batch; - - // Send - ibv_cq** send_cq; - - uint8_t* send_mr_buf; - size_t send_mr_size; - ibv_mr* send_mr; - - bf_ibv_send_pkt* send_pkt_buf; - bf_ibv_send_pkt* send_pkt_head; - - uint8_t offload_csum; - uint8_t hardware_pacing; -}; - -struct __attribute__((packed)) bf_ethernet_hdr { - uint8_t dst_mac[6]; - uint8_t src_mac[6]; - uint16_t type; -}; - -struct __attribute__((packed)) bf_ipv4_hdr { - uint8_t version_ihl; - uint8_t tos; - uint16_t length; - uint16_t id; - uint16_t flags_frag; - uint8_t ttl; - uint8_t proto; - uint16_t checksum; - uint32_t src_addr; - uint32_t dst_addr; -}; - -inline void bf_ipv4_update_checksum(bf_ipv4_hdr* hdr) { - hdr->checksum = 0; - uint16_t *block = reinterpret_cast(hdr); - - uint32_t checksum = 0; - for(uint32_t i=0; i 0xFFFF ) { - checksum = (checksum & 0xFFFF) + (checksum >> 16); - } - hdr->checksum = ~htons((uint16_t) checksum); -} - -struct __attribute__((packed)) bf_udp_hdr { - uint16_t src_port; - uint16_t dst_port; - uint16_t length; - uint16_t checksum; -}; - -struct __attribute__((packed)) bf_comb_udp_hdr { - bf_ethernet_hdr ethernet; - bf_ipv4_hdr ipv4; - bf_udp_hdr udp; }; @@ -222,40 +150,6 @@ class Verbs { ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); } - void get_remote_mac_address(uint8_t* mac) { - uint32_t ip; - char ip_str[INET_ADDRSTRLEN]; - this->get_remote_ip_address(&(ip_str[0])); - inet_pton(AF_INET, &(ip_str[0]), &ip); - - if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { - ETHER_MAP_IP_MULTICAST(&ip, mac); - } else { - int ret = -1; - char cmd[256] = {'\0'}; - char line[256] = {'\0'}; - char* end; - sprintf(cmd, "ping -c 1 %s", ip_str); - FILE* fp = popen(cmd, "r"); - sprintf(cmd, "ip neigh | grep -e \"%s \" | awk '{print $5}'", ip_str); - fp = popen(cmd, "r"); - if( fgets(line, sizeof(line), fp) != NULL) { - if( line[strlen(line)-1] == '\n' ) { - line[strlen(line)-1] = '\0'; - } - if( strncmp(&(line[2]), ":", 1) == 0 ) { - ret = 0; - mac[0] = (uint8_t) strtol(&line[0], &end, 16); - mac[1] = (uint8_t) strtol(&line[3], &end, 16); - mac[2] = (uint8_t) strtol(&line[6], &end, 16); - mac[3] = (uint8_t) strtol(&line[9], &end, 16); - mac[4] = (uint8_t) strtol(&line[12], &end, 16); - mac[5] = (uint8_t) strtol(&line[15], &end, 16); - } - } - check_error(ret, "determine remote hardware address"); - } - } void get_ip_address(char* ip) { sockaddr_in sin; socklen_t len = sizeof(sin); @@ -263,13 +157,6 @@ class Verbs { "query socket name"); inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); } - void get_remote_ip_address(char* ip) { - sockaddr_in sin; - socklen_t len = sizeof(sin); - check_error(::getpeername(_fd, (sockaddr *)&sin, &len), - "query peer name"); - inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); - } uint16_t get_port() { sockaddr_in sin; socklen_t len = sizeof(sin); @@ -277,20 +164,6 @@ class Verbs { "query socket name"); return ntohs(sin.sin_port); } - uint16_t get_remote_port() { - sockaddr_in sin; - socklen_t len = sizeof(sin); - check_error(::getpeername(_fd, (sockaddr *)&sin, &len), - "query peer name"); - return ntohs(sin.sin_port); - } - uint8_t get_ttl() { - uint8_t ttl; - socklen_t len = sizeof(ttl); - check_error(::getsockopt(_fd, IPPROTO_IP, IP_TTL, &ttl, &len), - "determine TTL"); - return ttl; - } int get_timeout_ms() { timeval value; socklen_t size = sizeof(value); @@ -422,25 +295,6 @@ class Verbs { _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, "register memory region"); - - // Start Send - - _verbs.send_pkt_buf = (bf_ibv_send_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); - check_null(_verbs.send_pkt_buf, - "allocate send packet buffer"); - ::memset(_verbs.send_pkt_buf, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); - _verbs.send_mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; - _verbs.send_mr_buf = (uint8_t *) ::mmap(NULL, _verbs.send_mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - - check_error(_verbs.send_mr_buf == MAP_FAILED, - "allocate memory region buffer"); - check_error(::mlock(_verbs.send_mr_buf, _verbs.send_mr_size), - "lock memory region buffer"); - _verbs.send_mr = ibv_reg_mr(_verbs.pd, _verbs.send_mr_buf, _verbs.send_mr_size, IBV_ACCESS_LOCAL_WRITE); - check_null(_verbs.send_mr, - "register memory region"); - - // End Send } void destroy_buffers() { int failures = 0; @@ -460,26 +314,6 @@ class Verbs { free(_verbs.pkt_buf); } - // Start Send - - if( _verbs.send_mr ) { - if( ibv_dereg_mr(_verbs.send_mr) ) { - failures += 1; - } - } - - if( _verbs.send_mr_buf ) { - if( ::munmap(_verbs.send_mr_buf, _verbs.send_mr_size) ) { - failures += 1; - } - } - - if( _verbs.send_pkt_buf ) { - free(_verbs.send_pkt_buf); - } - - // End Send - if( _verbs.pd ) { if( ibv_dealloc_pd(_verbs.pd) ) { failures += 1; @@ -517,29 +351,14 @@ class Verbs { "change completion queue request notifications"); } - // Start Send - - // Setup the completion queues - _verbs.send_cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); - check_null(_verbs.send_cq, - "allocate send completion queues"); - ::memset(_verbs.send_cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); - for(i=0; ilkey; - } - } - - // Link the work requests to send queue - uint32_t send_flags = IBV_SEND_SIGNALED; - #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD - if( _verbs.offload_csum ) { - send_flags |= IBV_SEND_IP_CSUM; - } - #endif - - for(i=0; istate) { - case IBV_QPS_RESET: // Unexpected, but maybe user reset it - qp_attr.qp_state = IBV_QPS_INIT; - qp_attr.port_num = _verbs.port_num; - if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { - return NULL; - } - case IBV_QPS_INIT: - qp_attr.qp_state = IBV_QPS_RTR; - qp_attr.port_num = _verbs.port_num; - if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { - return NULL; - } - case IBV_QPS_RTR: - qp_attr.qp_state = IBV_QPS_RTS; - if(ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE)) { - return NULL; - } - break; - case IBV_QPS_RTS: - break; - default: - return NULL; - } - } - - for(i=0; iwr.next = &(_verbs.send_pkt_head->wr); - _verbs.send_pkt_head = send_pkt; - } // for each work completion - } while(num_wce); - } - - if( npackets == 0 || !_verbs.send_pkt_head ) { - return NULL; - } - - send_head = _verbs.send_pkt_head; - send_tail = _verbs.send_pkt_head; - for(i=0; iwr.next; i++) { - send_tail = (bf_ibv_send_pkt*) send_tail->wr.next; - } - - _verbs.send_pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; - send_tail->wr.next = NULL; - - return send_head; - } inline void check_error(int retval, std::string what) { if( retval < 0 ) { destroy_flows(); @@ -1032,78 +733,4 @@ class Verbs { *pkt_ptr = (uint8_t *) _verbs.pkt->wr.sg_list->addr + BF_VERBS_PAYLOAD_OFFSET; return _verbs.pkt->length - BF_VERBS_PAYLOAD_OFFSET; } - inline void get_ethernet_header(bf_ethernet_hdr* hdr) { - uint8_t src_mac[6], dst_mac[6]; - this->get_mac_address(&(src_mac[0])); - this->get_remote_mac_address(&(dst_mac[0])); - - ::memset(hdr, 0, sizeof(bf_ethernet_hdr)); - ::memcpy(hdr->dst_mac, dst_mac, 6); - ::memcpy(hdr->src_mac, src_mac, 6); - hdr->type = htons(0x0800); // IPv4 - } - inline void get_ipv4_header(bf_ipv4_hdr* hdr, size_t udp_length=0) { - uint8_t ttl = this->get_ttl(); - uint32_t src_ip, dst_ip; - char src_ip_str[INET_ADDRSTRLEN], dst_ip_str[INET_ADDRSTRLEN]; - this->get_ip_address(&(src_ip_str[0])); - inet_pton(AF_INET, &(src_ip_str[0]), &src_ip); - this->get_remote_ip_address(&(dst_ip_str[0])); - inet_pton(AF_INET, &(dst_ip_str[0]), &dst_ip); - - ::memset(hdr, 0, sizeof(bf_ipv4_hdr)); - hdr->version_ihl = htons(0x4500); // v4 + 20-byte header - hdr->length = htons((uint16_t) (20 + 8 + udp_length)); - hdr->flags_frag = htons(1<<14); // don't fragment - hdr->ttl = ttl; - hdr->proto = 0x11; // UDP - hdr->src_addr = src_ip; - hdr->dst_addr = dst_ip; - if( !_verbs.offload_csum ) { - bf_ipv4_update_checksum(hdr); - } - } - inline void get_udp_header(bf_udp_hdr* hdr, size_t udp_length=0) { - uint16_t src_port, dst_port; - src_port = this->get_port(); - dst_port = this->get_remote_port(); - - ::memset(hdr, 0, sizeof(bf_udp_hdr)); - hdr->src_port = htons(src_port); - hdr->dst_port = htons(dst_port); - hdr->length = htons((uint16_t) (8 + udp_length)); - } - inline int sendmmsg(mmsghdr *mmsg, int npackets, int flags=0) { - int ret; - bf_ibv_send_pkt* head; - ibv_send_wr *s; - - int i; - uint64_t offset; - for(i=0; iqueue(npackets); - ret = ibv_post_send(_verbs.qp[0], &(head->wr), &s); - if( ret ) { - ret = -1; - } else { - ret = npackets; - } - return ret; - } }; diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp new file mode 100644 index 000000000..cbc2bff33 --- /dev/null +++ b/src/ib_verbs_send.hpp @@ -0,0 +1,772 @@ +/* + * Copyright (c) 2020-2023, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// Catch for older InfiniBand verbs installs that do not have the +// IBV_RAW_PACKET_CAP_IP_CSUM feature check. +#ifndef IBV_RAW_PACKET_CAP_IP_CSUM +#define BF_ENABLE_VERBS_OFFLOAD 0 +#else +#define BF_ENABLE_VERBS_OFFLOAD 1 +#endif + +#ifndef BF_VERBS_SEND_NQP +#define BF_VERBS_SEND_NQP 1 +#endif + +#ifndef BF_VERBS_SEND_NPKTBUF +#define BF_VERBS_SEND_NPKTBUF 1024 +#endif + +#ifndef BF_VERBS_SEND_WCBATCH +#define BF_VERBS_SEND_WCBATCH 16 +#endif + +struct bf_ibv_send_pkt{ + ibv_send_wr wr; + ibv_sge sg; +}; + +struct bf_ibv_send { + ibv_context* ctx; + uint8_t port_num; + ibv_pd* pd; + ibv_comp_channel* cc; + ibv_cq** cq; + ibv_qp** qp; + + uint8_t* mr_buf; + size_t mr_size; + ibv_mr* mr; + + ibv_cq** send_cq; + + uint8_t* send_mr_buf; + size_t send_mr_size; + ibv_mr* send_mr; + + bf_ibv_send_pkt* send_pkt_buf; + bf_ibv_send_pkt* send_pkt_head; + + uint8_t offload_csum; + uint8_t hardware_pacing; +}; + +struct __attribute__((packed)) bf_ethernet_hdr { + uint8_t dst_mac[6]; + uint8_t src_mac[6]; + uint16_t type; +}; + +struct __attribute__((packed)) bf_ipv4_hdr { + uint8_t version_ihl; + uint8_t tos; + uint16_t length; + uint16_t id; + uint16_t flags_frag; + uint8_t ttl; + uint8_t proto; + uint16_t checksum; + uint32_t src_addr; + uint32_t dst_addr; +}; + +inline void bf_ipv4_update_checksum(bf_ipv4_hdr* hdr) { + hdr->checksum = 0; + uint16_t *block = reinterpret_cast(hdr); + + uint32_t checksum = 0; + for(uint32_t i=0; i 0xFFFF ) { + checksum = (checksum & 0xFFFF) + (checksum >> 16); + } + hdr->checksum = ~htons((uint16_t) checksum); +} + +struct __attribute__((packed)) bf_udp_hdr { + uint16_t src_port; + uint16_t dst_port; + uint16_t length; + uint16_t checksum; +}; + +struct __attribute__((packed)) bf_comb_udp_hdr { + bf_ethernet_hdr ethernet; + bf_ipv4_hdr ipv4; + bf_udp_hdr udp; +}; + + +class VerbsSend { + int _fd; + size_t _pkt_size_max; + int _timeout; + bf_ibv_send _verbs; + + void get_interface_name(char* name) { + sockaddr_in sin; + char ip[INET_ADDRSTRLEN]; + socklen_t len = sizeof(sin); + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + + // TODO: Is there a better way to find this? + char cmd[256] = {'\0'}; + char line[256] = {'\0'}; + int is_lo = 0; + sprintf(cmd, "ip route get to %s | grep dev | awk '{print $4}'", ip); + FILE* fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + if( strncmp(&(line[0]), "lo", 2) == 0 ) { + is_lo = 1; + } + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-truncation" + strncpy(name, &(line[0]), IFNAMSIZ); + #pragma GCC diagnostic pop + } + pclose(fp); + + if( is_lo ) { + // TODO: Is there a way to avoid having to do this? + sprintf(cmd, "ip route show | grep %s | grep -v default | awk '{print $3}'", ip); + fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-truncation" + strncpy(name, &(line[0]), IFNAMSIZ); + #pragma GCC diagnostic pop + } + pclose(fp); + } + } + void get_mac_address(uint8_t* mac) { + ifreq ethreq; + this->get_interface_name(&(ethreq.ifr_name[0])); + check_error(::ioctl(_fd, SIOCGIFHWADDR, ðreq), + "query interface hardware address"); + + ::memcpy(mac, (uint8_t*) ethreq.ifr_hwaddr.sa_data, 6); + } + void get_remote_mac_address(uint8_t* mac) { + uint32_t ip; + char ip_str[INET_ADDRSTRLEN]; + this->get_remote_ip_address(&(ip_str[0])); + inet_pton(AF_INET, &(ip_str[0]), &ip); + + if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { + ETHER_MAP_IP_MULTICAST(&ip, mac); + } else { + int ret = -1; + char cmd[256] = {'\0'}; + char line[256] = {'\0'}; + char* end; + sprintf(cmd, "ping -c 1 %s", ip_str); + FILE* fp = popen(cmd, "r"); + sprintf(cmd, "ip neigh | grep -e \"%s \" | awk '{print $5}'", ip_str); + fp = popen(cmd, "r"); + if( fgets(line, sizeof(line), fp) != NULL) { + if( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; + } + if( strncmp(&(line[2]), ":", 1) == 0 ) { + ret = 0; + mac[0] = (uint8_t) strtol(&line[0], &end, 16); + mac[1] = (uint8_t) strtol(&line[3], &end, 16); + mac[2] = (uint8_t) strtol(&line[6], &end, 16); + mac[3] = (uint8_t) strtol(&line[9], &end, 16); + mac[4] = (uint8_t) strtol(&line[12], &end, 16); + mac[5] = (uint8_t) strtol(&line[15], &end, 16); + } + } + check_error(ret, "determine remote hardware address"); + } + } + void get_ip_address(char* ip) { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + } + void get_remote_ip_address(char* ip) { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); + } + uint16_t get_port() { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getsockname(_fd, (sockaddr *)&sin, &len), + "query socket name"); + return ntohs(sin.sin_port); + } + uint16_t get_remote_port() { + sockaddr_in sin; + socklen_t len = sizeof(sin); + check_error(::getpeername(_fd, (sockaddr *)&sin, &len), + "query peer name"); + return ntohs(sin.sin_port); + } + uint8_t get_ttl() { + uint8_t ttl; + socklen_t len = sizeof(ttl); + check_error(::getsockopt(_fd, IPPROTO_IP, IP_TTL, &ttl, &len), + "determine TTL"); + return ttl; + } + int get_timeout_ms() { + timeval value; + socklen_t size = sizeof(value); + check_error(::getsockopt(_fd, SOL_SOCKET, SO_RCVTIMEO, &value, &size), + "query socket timeout"); + return int(value.tv_sec*1000) + int(value.tv_usec/1000); + } + uint64_t get_interface_gid() { + uint64_t id; + uint8_t mac[6] = {0}; + uint8_t buf[8] = {0}; + this->get_mac_address(&(mac[0])); + + ::memcpy(buf, (unsigned char*) &(mac[0]), 3); + buf[0] ^= 2; // Toggle G/L bit per modified EUI-64 spec + buf[3] = 0xff; + buf[4] = 0xfe; + ::memcpy(buf+5, (unsigned char*) &(mac[3]), 3); + ::memcpy(&id, buf, 8); + return id; + } + void create_context() { + int d, p, g; + int ndev, found; + ibv_device** ibv_dev_list = NULL; + ibv_context* ibv_ctx = NULL; + ibv_device_attr_ex ibv_dev_attr; + ibv_port_attr ibv_port_attr; + union ibv_gid ibv_gid; + + // Get the interface MAC address and GID + found = 0; + uint8_t mac[6] = {0}; + this->get_mac_address(&(mac[0])); + uint64_t gid = this->get_interface_gid(); + + // Find the right device + /* Query all devices */ + ibv_dev_list = ibv_get_device_list(&ndev); + check_null(ibv_dev_list, + "ibv_get_device_list"); + + /* Interogate */ + for(d=0; dfd, F_GETFL); + check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), + "set completion channel to non-blocking"); + flags = ::fcntl(_verbs.cc->fd, F_GETFD); + check_error(::fcntl(_verbs.cc->fd, F_SETFD, flags | O_CLOEXEC), + "set completion channel to non-blocking"); + ::madvise(_verbs.cc, sizeof(ibv_pd), MADV_DONTFORK); + + // Setup the completion queues + _verbs.send_cq = (ibv_cq**) ::malloc(BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); + check_null(_verbs.send_cq, + "allocate send completion queues"); + ::memset(_verbs.send_cq, 0, BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); + for(i=0; ilkey; + } + } + + // Link the work requests to send queue + uint32_t send_flags = IBV_SEND_SIGNALED; + #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD + if( _verbs.offload_csum ) { + send_flags |= IBV_SEND_IP_CSUM; + } + #endif + + for(i=0; istate) { + case IBV_QPS_RESET: // Unexpected, but maybe user reset it + qp_attr.qp_state = IBV_QPS_INIT; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE|IBV_QP_PORT) ) { + return NULL; + } + case IBV_QPS_INIT: + qp_attr.qp_state = IBV_QPS_RTR; + qp_attr.port_num = _verbs.port_num; + if( ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE) ) { + return NULL; + } + case IBV_QPS_RTR: + qp_attr.qp_state = IBV_QPS_RTS; + if(ibv_modify_qp(_verbs.qp[i], &qp_attr, IBV_QP_STATE)) { + return NULL; + } + break; + case IBV_QPS_RTS: + break; + default: + return NULL; + } + } + + for(i=0; iwr.next = &(_verbs.send_pkt_head->wr); + _verbs.send_pkt_head = send_pkt; + } // for each work completion + } while(num_wce); + } + + if( npackets == 0 || !_verbs.send_pkt_head ) { + return NULL; + } + + send_head = _verbs.send_pkt_head; + send_tail = _verbs.send_pkt_head; + for(i=0; iwr.next; i++) { + send_tail = (bf_ibv_send_pkt*) send_tail->wr.next; + } + + _verbs.send_pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; + send_tail->wr.next = NULL; + + return send_head; + } + inline void check_error(int retval, std::string what) { + if( retval < 0 ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw Verbs::Error(ss.str()); + } + } + inline void check_null(void* ptr, std::string what) { + if( ptr == NULL ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + throw Verbs::Error(ss.str()); + } + } + inline void check_null_qp(void* ptr, std::string what) { + if( ptr == NULL ) { + destroy_flows(); + destroy_queues(); + destroy_buffers(); + destroy_context(); + + std::stringstream ss; + ss << "Failed to " << what << ": (" << errno << ") " + << strerror(errno); + if( errno == EPERM ) { + ss << " Do you need to set 'options ibverbs disable_raw_qp_enforcement=1' " + << "or add the CAP_NET_RAW capability?"; + } + throw Verbs::Error(ss.str()); + } + } +public: + class Error : public std::runtime_error { + typedef std::runtime_error super_t; + protected: + virtual const char* what() const throw() { + return super_t::what(); + } + public: + Error(const std::string& what_arg) + : super_t(what_arg) {} + }; + + VerbsSend(int fd, size_t pkt_size_max) + : _fd(fd), _pkt_size_max(pkt_size_max), _timeout(1) { + _timeout = get_timeout_ms(); + + ::memset(&_verbs, 0, sizeof(_verbs)); + check_error(ibv_fork_init(), + "make verbs fork safe"); + create_context(); + create_buffers(); + create_queues(); + link_work_requests(); + } + ~VerbsSend() { + destroy_queues(); + destroy_buffers(); + destroy_context(); + } + inline void get_ethernet_header(bf_ethernet_hdr* hdr) { + uint8_t src_mac[6], dst_mac[6]; + this->get_mac_address(&(src_mac[0])); + this->get_remote_mac_address(&(dst_mac[0])); + + ::memset(hdr, 0, sizeof(bf_ethernet_hdr)); + ::memcpy(hdr->dst_mac, dst_mac, 6); + ::memcpy(hdr->src_mac, src_mac, 6); + hdr->type = htons(0x0800); // IPv4 + } + inline void get_ipv4_header(bf_ipv4_hdr* hdr, size_t udp_length=0) { + uint8_t ttl = this->get_ttl(); + uint32_t src_ip, dst_ip; + char src_ip_str[INET_ADDRSTRLEN], dst_ip_str[INET_ADDRSTRLEN]; + this->get_ip_address(&(src_ip_str[0])); + inet_pton(AF_INET, &(src_ip_str[0]), &src_ip); + this->get_remote_ip_address(&(dst_ip_str[0])); + inet_pton(AF_INET, &(dst_ip_str[0]), &dst_ip); + + ::memset(hdr, 0, sizeof(bf_ipv4_hdr)); + hdr->version_ihl = htons(0x4500); // v4 + 20-byte header + hdr->length = htons((uint16_t) (20 + 8 + udp_length)); + hdr->flags_frag = htons(1<<14); // don't fragment + hdr->ttl = ttl; + hdr->proto = 0x11; // UDP + hdr->src_addr = src_ip; + hdr->dst_addr = dst_ip; + if( !_verbs.offload_csum ) { + bf_ipv4_update_checksum(hdr); + } + } + inline void get_udp_header(bf_udp_hdr* hdr, size_t udp_length=0) { + uint16_t src_port, dst_port; + src_port = this->get_port(); + dst_port = this->get_remote_port(); + + ::memset(hdr, 0, sizeof(bf_udp_hdr)); + hdr->src_port = htons(src_port); + hdr->dst_port = htons(dst_port); + hdr->length = htons((uint16_t) (8 + udp_length)); + } + inline int sendmmsg(mmsghdr *mmsg, int npackets, int flags=0) { + int ret; + bf_ibv_send_pkt* head; + ibv_send_wr *s; + + int i; + uint64_t offset; + for(i=0; iqueue(npackets); + ret = ibv_post_send(_verbs.qp[0], &(head->wr), &s); + if( ret ) { + ret = -1; + } else { + ret = npackets; + } + return ret; + } +}; From 0b8bdcfda46c2b7b6e912694956977a5e1529e9a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 14:34:58 -0600 Subject: [PATCH 281/424] Verbs -> VerbsSend --- src/packet_writer.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index b2806b7fb..0051e88bb 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -120,7 +120,7 @@ class DiskPacketWriter : public PacketWriterMethod { status = ::write(_fd, hdrs+hdr_size*i, hdr_size); if( status != hdr_size ) continue; status = ::write(_fd, data+data_size*i, data_size); - if( status != data_size) continue; + if( status != data_size ) continue; nsent += 1; } return nsent; @@ -187,10 +187,10 @@ class UDPPacketSender : public PacketWriterMethod { }; #if defined BF_VERBS_ENABLED && BF_VERBS_ENABLED -#include "ib_verbs.hpp" +#include "ib_verbs_send.hpp" class UDPVerbsSender : public PacketWriterMethod { - Verbs _ibv; + VerbsSend _ibv; bf_comb_udp_hdr _udp_hdr; int _last_size; int _last_count; From 927b897177a8154d4a40e9cc19d35eadda969b42 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 14:48:44 -0600 Subject: [PATCH 282/424] Checksum offloading is only for send. --- src/ib_verbs.hpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 506be63d9..ac77fe348 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -229,16 +229,6 @@ class Verbs { if( (ibv_gid.global.subnet_prefix == 0x80feUL) \ && (ibv_gid.global.interface_id == gid) ) { found = 1; - #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD - if( ibv_dev_attr.raw_packet_caps & IBV_RAW_PACKET_CAP_IP_CSUM ) { - _verbs.offload_csum = 1; - } else { - _verbs.offload_csum = 0; - } - #else - _verbs.offload_csum = 0; - #endif - std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; break; } } From c4bf808f3645422f2e9301eae578219a8b928e8f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 14:49:46 -0600 Subject: [PATCH 283/424] More Verbs -> VerbsSend. --- src/ib_verbs_send.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index cbc2bff33..9bc392371 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -371,7 +371,7 @@ class VerbsSend { // Done if( !found ) { destroy_context(); - throw Verbs::Error("specified device not found"); + throw VerbsSend::Error("specified device not found"); } } void destroy_context() { @@ -633,7 +633,7 @@ class VerbsSend { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw Verbs::Error(ss.str()); + throw VerbsSend::Error(ss.str()); } } inline void check_null(void* ptr, std::string what) { @@ -646,7 +646,7 @@ class VerbsSend { std::stringstream ss; ss << "Failed to " << what << ": (" << errno << ") " << strerror(errno); - throw Verbs::Error(ss.str()); + throw VerbsSend::Error(ss.str()); } } inline void check_null_qp(void* ptr, std::string what) { @@ -663,7 +663,7 @@ class VerbsSend { ss << " Do you need to set 'options ibverbs disable_raw_qp_enforcement=1' " << "or add the CAP_NET_RAW capability?"; } - throw Verbs::Error(ss.str()); + throw VerbsSend::Error(ss.str()); } } public: From 89bcba12c7262cec97c5a7dd8f4da3ff3a40b1e7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 14:52:45 -0600 Subject: [PATCH 284/424] A few more things related to the split. --- src/ib_verbs_send.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 9bc392371..841be430b 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -518,7 +518,7 @@ class VerbsSend { } void link_work_requests() { // Make sure we are ready to go - check_null(_verbs.pkt_buf, + check_null(_verbs.send_pkt_buf, "find existing packet buffer"); check_null(_verbs.qp, "find existing queue pairs"); @@ -625,7 +625,6 @@ class VerbsSend { } inline void check_error(int retval, std::string what) { if( retval < 0 ) { - destroy_flows(); destroy_queues(); destroy_buffers(); destroy_context(); @@ -638,7 +637,6 @@ class VerbsSend { } inline void check_null(void* ptr, std::string what) { if( ptr == NULL ) { - destroy_flows(); destroy_queues(); destroy_buffers(); destroy_context(); @@ -651,7 +649,6 @@ class VerbsSend { } inline void check_null_qp(void* ptr, std::string what) { if( ptr == NULL ) { - destroy_flows(); destroy_queues(); destroy_buffers(); destroy_context(); From 58e234b239d0db2529808cf6058092e4df9b11d2 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 15:16:46 -0600 Subject: [PATCH 285/424] Tweak the AVX/AVX512 tests. --- configure | 6 ++++-- configure.ac | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 8f307530d..7907179e1 100755 --- a/configure +++ b/configure @@ -21077,7 +21077,8 @@ printf %s "checking for AVX support... " >&6; } int main() { __m256d x = _mm256_set1_pd(1.0); x = _mm256_add_pd(x, x); - return _mm256_cvtsd_f64(x) != 2.0; + double f = _mm256_cvtsd_f64(x); + return f != 2.0; } @@ -21120,7 +21121,8 @@ printf %s "checking for AVX-512 support... " >&6; } int main() { __m512d x = _mm512_set1_pd(1.0); x = _mm512_add_pd(x, x); - return _mm512_cvtsd_f64(x) != 2.0; + double f = _mm512_cvtsd_f64(x); + return f != 2.0; } diff --git a/configure.ac b/configure.ac index c727be91c..0fecdd21d 100644 --- a/configure.ac +++ b/configure.ac @@ -131,7 +131,8 @@ AC_DEFUN([AC_CHECK_AVX], [ int main() { __m256d x = _mm256_set1_pd(1.0); x = _mm256_add_pd(x, x); - return _mm256_cvtsd_f64(x) != 2.0; + double f = _mm256_cvtsd_f64(x); + return f != 2.0; } ]]) ], [ @@ -158,7 +159,8 @@ AC_DEFUN([AC_CHECK_AVX512], [ int main() { __m512d x = _mm512_set1_pd(1.0); x = _mm512_add_pd(x, x); - return _mm512_cvtsd_f64(x) != 2.0; + double f = _mm512_cvtsd_f64(x); + return f != 2.0; } ]]) ], [ From 6f456a8b702fb3a1187c09ed3c68cd1692227839 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 14 Sep 2023 16:53:26 -0600 Subject: [PATCH 286/424] A few more things. --- src/ib_verbs_send.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 841be430b..3dbdba453 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -448,7 +448,7 @@ class VerbsSend { ::memset(_verbs.send_cq, 0, BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); for(i=0; i Date: Thu, 14 Sep 2023 17:10:15 -0600 Subject: [PATCH 287/424] Error message cleanup now that there is send and receive. --- src/ib_verbs.hpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index ac77fe348..37b559068 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -279,12 +279,12 @@ class Verbs { _verbs.mr_buf = (uint8_t *) ::mmap(NULL, _verbs.mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); check_error(_verbs.mr_buf == MAP_FAILED, - "allocate memory region buffer"); + "allocate receive memory region buffer"); check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), - "lock memory region buffer"); + "lock receive memory region buffer"); _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, - "register memory region"); + "register receive memory region"); } void destroy_buffers() { int failures = 0; @@ -316,29 +316,29 @@ class Verbs { // Setup the completion channel and make it non-blocking _verbs.cc = ibv_create_comp_channel(_verbs.ctx); check_null(_verbs.cc, - "create completion channel"); + "create receive completion channel"); int flags = ::fcntl(_verbs.cc->fd, F_GETFL); check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); + "set receive completion channel to non-blocking"); flags = ::fcntl(_verbs.cc->fd, F_GETFD); check_error(::fcntl(_verbs.cc->fd, F_SETFD, flags | O_CLOEXEC), - "set completion channel to non-blocking"); + "set receive completion channel to non-blocking"); ::madvise(_verbs.cc, sizeof(ibv_pd), MADV_DONTFORK); // Setup the completion queues _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_NQP * sizeof(ibv_cq*)); check_null(_verbs.cq, - "allocate completion queues"); + "allocate receive completion queues"); ::memset(_verbs.cq, 0, BF_VERBS_NQP * sizeof(ibv_cq*)); for(i=0; i Date: Fri, 15 Sep 2023 13:00:11 -0600 Subject: [PATCH 288/424] Cleanup naming. --- src/ib_verbs_send.hpp | 143 +++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 3dbdba453..9db1a9e97 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -83,14 +83,14 @@ struct bf_ibv_send { size_t mr_size; ibv_mr* mr; - ibv_cq** send_cq; + ibv_cq** cq; - uint8_t* send_mr_buf; - size_t send_mr_size; - ibv_mr* send_mr; + uint8_t* mr_buf; + size_t mr_size; + ibv_mr* mr; - bf_ibv_send_pkt* send_pkt_buf; - bf_ibv_send_pkt* send_pkt_head; + bf_ibv_send_pkt* pkt_buf; + bf_ibv_send_pkt* pkt_head; uint8_t offload_csum; uint8_t hardware_pacing; @@ -387,37 +387,37 @@ class VerbsSend { _verbs.pd = ibv_alloc_pd(_verbs.ctx); // Create the buffers and the memory region - _verbs.send_pkt_buf = (bf_ibv_send_pkt*) ::malloc(BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * sizeof(struct bf_ibv_send_pkt)); - check_null(_verbs.send_pkt_buf, + _verbs.pkt_buf = (bf_ibv_send_pkt*) ::malloc(BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * sizeof(struct bf_ibv_send_pkt)); + check_null(_verbs.pkt_buf, "allocate send packet buffer"); - ::memset(_verbs.send_pkt_buf, 0, BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * sizeof(struct bf_ibv_send_pkt)); - _verbs.send_mr_size = (size_t) BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * _pkt_size_max; - _verbs.send_mr_buf = (uint8_t *) ::mmap(NULL, _verbs.send_mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); + ::memset(_verbs.pkt_buf, 0, BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * sizeof(struct bf_ibv_send_pkt)); + _verbs.mr_size = (size_t) BF_VERBS_SEND_NPKTBUF*BF_VERBS_SEND_NQP * _pkt_size_max; + _verbs.mr_buf = (uint8_t *) ::mmap(NULL, _verbs.mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - check_error(_verbs.send_mr_buf == MAP_FAILED, - "allocate memory region buffer"); - check_error(::mlock(_verbs.send_mr_buf, _verbs.send_mr_size), - "lock memory region buffer"); - _verbs.send_mr = ibv_reg_mr(_verbs.pd, _verbs.send_mr_buf, _verbs.send_mr_size, IBV_ACCESS_LOCAL_WRITE); - check_null(_verbs.send_mr, - "register memory region"); + check_error(_verbs.mr_buf == MAP_FAILED, + "allocate send memory region buffer"); + check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), + "lock send memory region buffer"); + _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); + check_null(_verbs.mr, + "register send memory region"); } void destroy_buffers() { int failures = 0; - if( _verbs.send_mr ) { - if( ibv_dereg_mr(_verbs.send_mr) ) { + if( _verbs.mr ) { + if( ibv_dereg_mr(_verbs.mr) ) { failures += 1; } } - if( _verbs.send_mr_buf ) { - if( ::munmap(_verbs.send_mr_buf, _verbs.send_mr_size) ) { + if( _verbs.mr_buf ) { + if( ::munmap(_verbs.mr_buf, _verbs.mr_size) ) { failures += 1; } } - if( _verbs.send_pkt_buf ) { - free(_verbs.send_pkt_buf); + if( _verbs.pkt_buf ) { + free(_verbs.pkt_buf); } if( _verbs.pd ) { @@ -432,23 +432,23 @@ class VerbsSend { // Setup the completion channel and make it non-blocking _verbs.cc = ibv_create_comp_channel(_verbs.ctx); check_null(_verbs.cc, - "create completion channel"); + "create send completion channel"); int flags = ::fcntl(_verbs.cc->fd, F_GETFL); check_error(::fcntl(_verbs.cc->fd, F_SETFL, flags | O_NONBLOCK), - "set completion channel to non-blocking"); + "set send completion channel to non-blocking"); flags = ::fcntl(_verbs.cc->fd, F_GETFD); check_error(::fcntl(_verbs.cc->fd, F_SETFD, flags | O_CLOEXEC), - "set completion channel to non-blocking"); + "set send completion channel to non-blocking"); ::madvise(_verbs.cc, sizeof(ibv_pd), MADV_DONTFORK); // Setup the completion queues - _verbs.send_cq = (ibv_cq**) ::malloc(BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); - check_null(_verbs.send_cq, + _verbs.cq = (ibv_cq**) ::malloc(BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); + check_null(_verbs.cq, "allocate send completion queues"); - ::memset(_verbs.send_cq, 0, BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); + ::memset(_verbs.cq, 0, BF_VERBS_SEND_NQP * sizeof(ibv_cq*)); for(i=0; ilkey; + _verbs.pkt_buf[i].wr.sg_list = &(_verbs.pkt_buf[i].sg); + for(j=0; j<_verbs.pkt_buf[i].wr.num_sge; j++) { + _verbs.pkt_buf[i].wr.sg_list[j].lkey = _verbs.mr->lkey; } } @@ -547,16 +547,15 @@ class VerbsSend { #endif for(i=0; iwr.next = &(_verbs.send_pkt_head->wr); - _verbs.send_pkt_head = send_pkt; + send_pkt = &(_verbs.pkt_buf[wc[j].wr_id]); + send_pkt->wr.next = &(_verbs.pkt_head->wr); + _verbs.pkt_head = send_pkt; } // for each work completion } while(num_wce); } - if( npackets == 0 || !_verbs.send_pkt_head ) { + if( npackets == 0 || !_verbs.pkt_head ) { return NULL; } - send_head = _verbs.send_pkt_head; - send_tail = _verbs.send_pkt_head; + send_head = _verbs.pkt_head; + send_tail = _verbs.pkt_head; for(i=0; iwr.next; i++) { send_tail = (bf_ibv_send_pkt*) send_tail->wr.next; } - _verbs.send_pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; + _verbs.pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; send_tail->wr.next = NULL; return send_head; @@ -744,19 +743,19 @@ class VerbsSend { uint64_t offset; for(i=0; iqueue(npackets); From 6268a3a9d5ca5a34187b55fc52f99b61f62cba23 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Sep 2023 13:00:58 -0600 Subject: [PATCH 289/424] Bad rename. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 9db1a9e97..fc2f65035 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -549,7 +549,7 @@ class VerbsSend { for(i=0; i Date: Fri, 15 Sep 2023 13:08:02 -0600 Subject: [PATCH 290/424] Remove duplicate declarations and add in a place to store a rate limit. --- src/ib_verbs_send.hpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index fc2f65035..129306c79 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -83,12 +83,6 @@ struct bf_ibv_send { size_t mr_size; ibv_mr* mr; - ibv_cq** cq; - - uint8_t* mr_buf; - size_t mr_size; - ibv_mr* mr; - bf_ibv_send_pkt* pkt_buf; bf_ibv_send_pkt* pkt_head; @@ -147,6 +141,7 @@ class VerbsSend { int _fd; size_t _pkt_size_max; int _timeout; + uint32_t _rate_limit; bf_ibv_send _verbs; void get_interface_name(char* name) { @@ -677,7 +672,7 @@ class VerbsSend { }; VerbsSend(int fd, size_t pkt_size_max) - : _fd(fd), _pkt_size_max(pkt_size_max), _timeout(1) { + : _fd(fd), _pkt_size_max(pkt_size_max), _timeout(1), _rate_limit(0) { _timeout = get_timeout_ms(); ::memset(&_verbs, 0, sizeof(_verbs)); From 0ec345220dd135579cfe8009be3cc3b4860e32de Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Sep 2023 13:31:31 -0600 Subject: [PATCH 291/424] More work on hardware packet pacing. --- src/ib_verbs_send.hpp | 44 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 129306c79..f4b5f5073 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -47,12 +47,7 @@ #include // Catch for older InfiniBand verbs installs that do not have the -// IBV_RAW_PACKET_CAP_IP_CSUM feature check. -#ifndef IBV_RAW_PACKET_CAP_IP_CSUM -#define BF_ENABLE_VERBS_OFFLOAD 0 -#else -#define BF_ENABLE_VERBS_OFFLOAD 1 -#endif +//#define BF_ENABLE_VERBS_OFFLOAD 0 #ifndef BF_VERBS_SEND_NQP #define BF_VERBS_SEND_NQP 1 @@ -66,6 +61,8 @@ #define BF_VERBS_SEND_WCBATCH 16 #endif +#define BF_VERBS_SEND_PAYLOAD_OFFSET 42 + struct bf_ibv_send_pkt{ ibv_send_wr wr; ibv_sge sg; @@ -87,7 +84,7 @@ struct bf_ibv_send { bf_ibv_send_pkt* pkt_head; uint8_t offload_csum; - uint8_t hardware_pacing; + uint32_t hardware_pacing; }; struct __attribute__((packed)) bf_ethernet_hdr { @@ -330,6 +327,7 @@ class VerbsSend { if( (ibv_gid.global.subnet_prefix == 0x80feUL) \ && (ibv_gid.global.interface_id == gid) ) { found = 1; + #if defined BF_ENABLE_VERBS_OFFLOAD && BF_ENABLE_VERBS_OFFLOAD if( ibv_dev_attr.raw_packet_caps & IBV_RAW_PACKET_CAP_IP_CSUM ) { _verbs.offload_csum = 1; @@ -340,6 +338,13 @@ class VerbsSend { _verbs.offload_csum = 0; #endif std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; + + _verbs.hardware_pacing = 0; + if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) == 0 ) { + _verbs.hardware_pacing = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_max; + } + std::cout << "_verbs.hardware_pacing: " << (int) _verbs.hardware_pacing << std::endl; + break; } } @@ -688,6 +693,31 @@ class VerbsSend { destroy_buffers(); destroy_context(); } + inline void set_rate_limit(uint32_t rate_limit, size_t udp_length=1) { + int i; + + // Converts to B/s to kb/s assuming a packet size + size_t pkt_size = udp_length + BF_VERBS_SEND_PAYLOAD_OFFSET; + rate_limit = ((float) rate_limit) / udp_length * pkt_size / 8 / 1000; + + // Verify that this rate limit is valid + if( rate_limit > _verbs.hardware_pacing ) { + throw VerbsSend::Error("Failed to set rate limit, specified rate limit is out of range"); + } + + // Apply the rate limit + ibv_qp_rate_limit_attr qp_attr; + ::memset(&qp_attr, 0, sizeof(ibv_qp_rate_limit_attr)); + attr.rate_limit = rate_limit; + attr.typical_pkt_sz = pkt_size; + attr.max_burst_sz = 0; + for(i=0; iget_mac_address(&(src_mac[0])); From 97483f431b942cb0cc5ef65e91dfca3c8fabddf0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Sep 2023 13:33:27 -0600 Subject: [PATCH 292/424] Fix and rename. --- src/ib_verbs_send.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index f4b5f5073..be359948e 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -706,13 +706,13 @@ class VerbsSend { } // Apply the rate limit - ibv_qp_rate_limit_attr qp_attr; - ::memset(&qp_attr, 0, sizeof(ibv_qp_rate_limit_attr)); - attr.rate_limit = rate_limit; - attr.typical_pkt_sz = pkt_size; - attr.max_burst_sz = 0; + ibv_qp_rate_limit_attr rl_attr; + ::memset(&rl_attr, 0, sizeof(ibv_qp_rate_limit_attr)); + rl_attr.rate_limit = rate_limit; + rl_attr.typical_pkt_sz = pkt_size; + rl_attr.max_burst_sz = 0; for(i=0; i Date: Fri, 15 Sep 2023 13:48:37 -0600 Subject: [PATCH 293/424] Inverted logic. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index be359948e..766f6daf6 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -340,7 +340,7 @@ class VerbsSend { std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; _verbs.hardware_pacing = 0; - if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) == 0 ) { + if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) ) { _verbs.hardware_pacing = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_max; } std::cout << "_verbs.hardware_pacing: " << (int) _verbs.hardware_pacing << std::endl; From 9e4c0549e4f89c3acbb76f619cf2c94276e84023 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Sep 2023 13:58:09 -0600 Subject: [PATCH 294/424] Bits not bytes. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 766f6daf6..66fb1b54c 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -698,7 +698,7 @@ class VerbsSend { // Converts to B/s to kb/s assuming a packet size size_t pkt_size = udp_length + BF_VERBS_SEND_PAYLOAD_OFFSET; - rate_limit = ((float) rate_limit) / udp_length * pkt_size / 8 / 1000; + rate_limit = ((float) rate_limit) / udp_length * pkt_size * 8 / 1000; // Verify that this rate limit is valid if( rate_limit > _verbs.hardware_pacing ) { From 35d75bece4e5631c18ab2ea8ba4e1a1c8c069188 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 07:52:12 -0600 Subject: [PATCH 295/424] Fix SSE/AVX/AVX512 support detection. --- config/cuda.m4 | 32 ++-- config/intrinsics.m4 | 121 ++++++++++++++ configure | 386 ++++++++++++++++++++++++++----------------- configure.ac | 90 +--------- src/Makefile.in | 2 +- 5 files changed, 382 insertions(+), 249 deletions(-) create mode 100644 config/intrinsics.m4 diff --git a/config/cuda.m4 b/config/cuda.m4 index 2d34c6036..2500ef55f 100644 --- a/config/cuda.m4 +++ b/config/cuda.m4 @@ -14,6 +14,11 @@ AC_DEFUN([AX_CHECK_CUDA], [enable_cuda=no], [enable_cuda=yes]) + NVCCLIBS="$LIBS" + ac_compile_save="$ac_compile" + ac_link_save="$ac_link" + ac_run_save="$ac_run" + AC_SUBST([HAVE_CUDA], [0]) AC_SUBST([CUDA_VERSION], [0]) AC_SUBST([CUDA_HAVE_CXX20], [0]) @@ -48,9 +53,9 @@ AC_DEFUN([AX_CHECK_CUDA], if test "$HAVE_CUDA" = "1"; then LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart" + NVCCLIBS="$NVCCLIBS -lcuda -lcudart" - ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS conftest.$ac_ext >&5' + ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $NVCCLIBS conftest.$ac_ext >&5' AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -67,7 +72,7 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" fi if test "$HAVE_CUDA" = "1"; then @@ -136,7 +141,7 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS="$CXXFLAGS -DBF_CUDA_ENABLED=1" NVCCFLAGS="$NVCCFLAGS -DBF_CUDA_ENABLED=1" LDFLAGS="$LDFLAGS -L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt" + NVCCLIBS="$NVCCLIBS -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt" fi AC_ARG_WITH([gpu_archs], @@ -155,11 +160,11 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' + NVCCLIBS="-lcuda -lcudart" + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -209,7 +214,7 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" else AC_SUBST([GPU_ARCHS], [$with_gpu_archs]) fi @@ -242,11 +247,11 @@ AC_DEFUN([AX_CHECK_CUDA], AC_MSG_CHECKING([for thrust pinned allocated support]) CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -260,10 +265,13 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" - + NVCCLIBS="$NVCCLIBS_save" else AC_SUBST([GPU_PASCAL_MANAGEDMEM], [0]) AC_SUBST([GPU_EXP_PINNED_ALLOC], [1]) fi + + ac_compile="$ac_compile_save" + ac_link="$ac_link_save" + ac_run="$ac_run_save" ]) diff --git a/config/intrinsics.m4 b/config/intrinsics.m4 new file mode 100644 index 000000000..2f99a93de --- /dev/null +++ b/config/intrinsics.m4 @@ -0,0 +1,121 @@ +# +# SSE +# + +AC_DEFUN([AX_CHECK_SSE], +[ + AC_PROVIDE([AX_CHECK_SSE]) + AC_ARG_ENABLE([sse], + [AS_HELP_STRING([--disable-sse], + [disable SSE support (default=no)])], + [enable_sse=no], + [enable_sse=yes]) + + AC_SUBST([HAVE_SSE], [0]) + + if test "$enable_sse" = "yes"; then + AC_MSG_CHECKING([for SSE support via '-msse']) + + CXXFLAGS_temp="$CXXFLAGS -msse" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ + #include ]], + [[ + __m128 x = _mm_set1_ps(1.0f); + x = _mm_add_ps(x, x); + return _mm_cvtss_f32(x) != 2.0f;]])], + [ + CXXFLAGS="$CXXFLAGS -msse" + AC_SUBST([HAVE_SSE], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + fi +]) + + + +# +# AVX +# + +AC_DEFUN([AX_CHECK_AVX], +[ + AC_PROVIDE([AX_CHECK_AVX]) + AC_ARG_ENABLE([avx], + [AS_HELP_STRING([--disable-avx], + [disable AVX support (default=no)])], + [enable_avx=no], + [enable_avx=yes]) + + AC_SUBST([HAVE_AVX], [0]) + + if test "$enable_avx" = "yes"; then + AC_MSG_CHECKING([for AVX support via '-mavx']) + + CXXFLAGS_temp="$CXXFLAGS -mavx" + ac_run_save="$ac_run" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ + #include ]], + [[ + __m256d x = _mm256_set1_pd(1.0); + x = _mm256_add_pd(x, x); + return _mm256_cvtsd_f64(x) != 2.0;]])], + [ + CXXFLAGS="$CXXFLAGS -mavx" + AC_SUBST([HAVE_AVX], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + ac_run="$ac_run_save" + fi +]) + +# +# AVX512 +# + +AC_DEFUN([AX_CHECK_AVX512], +[ + AC_PROVIDE([AX_CHECK_AVX512]) + AC_ARG_ENABLE([avx512], + [AS_HELP_STRING([--disable-avx512], + [disable AVX512 support (default=no)])], + [enable_avx512=no], + [enable_avx512=yes]) + + AC_SUBST([HAVE_AVX512], [0]) + + if test "$enable_avx512" = "yes"; then + AC_MSG_CHECKING([for AVX-512 support via '-mavx512f']) + + CXXFLAGS_temp="$CXXFLAGS -mavx512f" + ac_run_save="$ac_run" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + AC_RUN_IFELSE([ + AC_LANG_PROGRAM([[ + #include ]], + [[ + __m512d x = _mm512_set1_pd(1.0); + x = _mm512_add_pd(x, x); + return _mm512_cvtsd_f64(x) != 2.0;]])], + [ + CXXFLAGS="$CXXFLAGS -mavx512f" + AC_SUBST([HAVE_AVX512], [1]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + ac_run="$ac_run_save" + fi +]) diff --git a/configure b/configure index 7907179e1..0d6140a84 100755 --- a/configure +++ b/configure @@ -712,6 +712,9 @@ HAVE_PYTHON HAVE_MAP_CACHE HAVE_CUDA_DEBUG enable_native_arch +HAVE_AVX512 +HAVE_AVX +HAVE_SSE HAVE_TRACE HAVE_DEBUG HAVE_TMPFS @@ -738,9 +741,6 @@ HAVE_RDMA HAVE_VERBS HAVE_VMA HAVE_HWLOC -HAVE_AVX512 -HAVE_AVX -HAVE_SSE HAVE_FLOAT128 HAVE_OPENMP LIBOBJS @@ -867,6 +867,9 @@ with_alignment with_logging_dir enable_debug enable_trace +enable_sse +enable_avx +enable_avx512 enable_native_arch enable_cuda_debug enable_map_cache @@ -1537,6 +1540,9 @@ Optional Features: --disable-cuda disable cuda support (default=no) --enable-debug enable debugging mode (default=no) --enable-trace enable tracing mode for nvprof/nvvp (default=no) + --disable-sse disable SSE support (default=no) + --disable-avx disable AVX support (default=no) + --disable-avx512 disable AVX512 support (default=no) --disable-native-arch disable native architecture compilation (default=no) --enable-cuda-debug enable CUDA debugging (nvcc -G; default=no) --disable-map-cache disable caching bifrost.map kernels (default=no) @@ -21015,137 +21021,6 @@ then : fi -# -# SSE -# - - -HAVE_SSE=0 - - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSE support" >&5 -printf %s "checking for SSE support... " >&6; } - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - - #include - int main() { - __m128 x = _mm_set1_ps(1.0f); - x = _mm_add_ps(x, x); - return _mm_cvtss_f32(x) != 2.0f; - } - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO" -then : - - HAVE_SSE=1 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -else $as_nop - - HAVE_SSE=0 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - - -# -# AVX -# - - -HAVE_AVX=0 - - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX support" >&5 -printf %s "checking for AVX support... " >&6; } - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - - #include - int main() { - __m256d x = _mm256_set1_pd(1.0); - x = _mm256_add_pd(x, x); - double f = _mm256_cvtsd_f64(x); - return f != 2.0; - } - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO" -then : - - HAVE_AVX=1 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -else $as_nop - - HAVE_AVX=0 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - - -# -# AVX512 -# - - -HAVE_AVX512=0 - - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX-512 support" >&5 -printf %s "checking for AVX-512 support... " >&6; } - - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - - #include - int main() { - __m512d x = _mm512_set1_pd(1.0); - x = _mm512_add_pd(x, x); - double f = _mm512_cvtsd_f64(x); - return f != 2.0; - } - - -_ACEOF -if ac_fn_cxx_try_compile "$LINENO" -then : - - HAVE_AVX512=1 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -else $as_nop - - HAVE_AVX512=0 - - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - -fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext - - # # HWLOC # @@ -21475,6 +21350,11 @@ else $as_nop fi + NVCCLIBS="$LIBS" + ac_compile_save="$ac_compile" + ac_link_save="$ac_link" + ac_run_save="$ac_run" + HAVE_CUDA=0 CUDA_VERSION=0 @@ -21672,9 +21552,9 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test "$HAVE_CUDA" = "1"; then LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart" + NVCCLIBS="$NVCCLIBS -lcuda -lcudart" - ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS conftest.$ac_ext >&5' + ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $NVCCLIBS conftest.$ac_ext >&5' cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21711,7 +21591,7 @@ printf "%s\n" "no" >&6; } CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" fi if test "$HAVE_CUDA" = "1"; then @@ -21802,7 +21682,7 @@ printf "%s\n" "no, only the 'legacy' stream model is supported" >&6; } CXXFLAGS="$CXXFLAGS -DBF_CUDA_ENABLED=1" NVCCFLAGS="$NVCCFLAGS -DBF_CUDA_ENABLED=1" LDFLAGS="$LDFLAGS -L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt" + NVCCLIBS="$NVCCLIBS -lcuda -lcudart -lnvrtc -lcublas -lcudadevrt -L. -lcufft_static_pruned -lculibos -lnvToolsExt" fi @@ -21828,11 +21708,11 @@ printf %s "checking which CUDA architectures to target... " >&6; } CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' + NVCCLIBS="-lcuda -lcudart" + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 @@ -21909,7 +21789,7 @@ fi CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" else GPU_ARCHS=$with_gpu_archs @@ -21953,11 +21833,11 @@ printf "%s\n" "no" >&6; } printf %s "checking for thrust pinned allocated support... " >&6; } CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 @@ -21999,8 +21879,7 @@ fi CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" - + NVCCLIBS="$NVCCLIBS_save" else GPU_PASCAL_MANAGEDMEM=0 @@ -22008,6 +21887,10 @@ fi fi + ac_compile="$ac_compile_save" + ac_link="$ac_link_save" + ac_run="$ac_run_save" + # Check whether --with-shared_mem was given. @@ -22181,6 +22064,207 @@ fi + # Check whether --enable-sse was given. +if test ${enable_sse+y} +then : + enableval=$enable_sse; enable_sse=no +else $as_nop + enable_sse=yes +fi + + + HAVE_SSE=0 + + + if test "$enable_sse" = "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SSE support via '-msse'" >&5 +printf %s "checking for SSE support via '-msse'... " >&6; } + + CXXFLAGS_temp="$CXXFLAGS -msse" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + if test "$cross_compiling" = yes +then : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include +int +main (void) +{ + + __m128 x = _mm_set1_ps(1.0f); + x = _mm_add_ps(x, x); + return _mm_cvtss_f32(x) != 2.0f; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO" +then : + + CXXFLAGS="$CXXFLAGS -msse" + HAVE_SSE=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + + + + # Check whether --enable-avx was given. +if test ${enable_avx+y} +then : + enableval=$enable_avx; enable_avx=no +else $as_nop + enable_avx=yes +fi + + + HAVE_AVX=0 + + + if test "$enable_avx" = "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX support via '-mavx'" >&5 +printf %s "checking for AVX support via '-mavx'... " >&6; } + + CXXFLAGS_temp="$CXXFLAGS -mavx" + ac_run_save="$ac_run" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + if test "$cross_compiling" = yes +then : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include +int +main (void) +{ + + __m256d x = _mm256_set1_pd(1.0); + x = _mm256_add_pd(x, x); + return _mm256_cvtsd_f64(x) != 2.0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO" +then : + + CXXFLAGS="$CXXFLAGS -mavx" + HAVE_AVX=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + ac_run="$ac_run_save" + fi + + + + # Check whether --enable-avx512 was given. +if test ${enable_avx512+y} +then : + enableval=$enable_avx512; enable_avx512=no +else $as_nop + enable_avx512=yes +fi + + + HAVE_AVX512=0 + + + if test "$enable_avx512" = "yes"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for AVX-512 support via '-mavx512f'" >&5 +printf %s "checking for AVX-512 support via '-mavx512f'... " >&6; } + + CXXFLAGS_temp="$CXXFLAGS -mavx512f" + ac_run_save="$ac_run" + + ac_run="$CXX -o conftest$ac_ext $CXXFLAGS_temp conftest.$ac_ext>&5" + if test "$cross_compiling" = yes +then : + { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run test program while cross compiling +See \`config.log' for more details" "$LINENO" 5; } +else $as_nop + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include +int +main (void) +{ + + __m512d x = _mm512_set1_pd(1.0); + x = _mm512_add_pd(x, x); + return _mm512_cvtsd_f64(x) != 2.0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO" +then : + + CXXFLAGS="$CXXFLAGS -mavx512f" + HAVE_AVX512=1 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + ac_run="$ac_run_save" + fi + + + # Check whether --enable-native_arch was given. if test ${enable_native_arch+y} then : @@ -27253,11 +27337,6 @@ if test x$enable_cuda_debug != xno then : OPTIONS="$OPTIONS cuda_debug" -fi -if test x$enable_native_arch != xno -then : - OPTIONS="$OPTIONS native" - fi if test x$HAVE_SSE != x0 then : @@ -27273,6 +27352,11 @@ if test x$HAVE_AVX512 != x0 then : OPTIONS="$OPTIONS avx512" +fi +if test x$enable_native_arch != xno +then : + OPTIONS="$OPTIONS native" + fi if test x$HAVE_FLOAT128 != x0 then : diff --git a/configure.ac b/configure.ac index 0fecdd21d..f2b92186c 100644 --- a/configure.ac +++ b/configure.ac @@ -91,89 +91,6 @@ AC_SUBST([HAVE_FLOAT128], [0]) AS_IF([test x$HAVE_HAVE_LONG_DOUBLE_WIDER = x1], [AC_SUBST([HAVE_FLOAT128], [0])]) -# -# SSE -# - -AC_DEFUN([AC_CHECK_SSE], [ - AC_MSG_CHECKING([for SSE support]) - - AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ - #include - int main() { - __m128 x = _mm_set1_ps(1.0f); - x = _mm_add_ps(x, x); - return _mm_cvtss_f32(x) != 2.0f; - } - ]]) - ], [ - AC_SUBST([HAVE_SSE], [1]) - AC_MSG_RESULT([yes]) - ], [ - AC_SUBST([HAVE_SSE], [0]) - AC_MSG_RESULT([no]) - ]) -]) -AC_SUBST([HAVE_SSE], [0]) -AC_CHECK_SSE - -# -# AVX -# - -AC_DEFUN([AC_CHECK_AVX], [ - AC_MSG_CHECKING([for AVX support]) - - AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ - #include - int main() { - __m256d x = _mm256_set1_pd(1.0); - x = _mm256_add_pd(x, x); - double f = _mm256_cvtsd_f64(x); - return f != 2.0; - } - ]]) - ], [ - AC_SUBST([HAVE_AVX], [1]) - AC_MSG_RESULT([yes]) - ], [ - AC_SUBST([HAVE_AVX], [0]) - AC_MSG_RESULT([no]) - ]) -]) -AC_SUBST([HAVE_AVX], [0]) -AC_CHECK_AVX - -# -# AVX512 -# - -AC_DEFUN([AC_CHECK_AVX512], [ - AC_MSG_CHECKING([for AVX-512 support]) - - AC_COMPILE_IFELSE([ - AC_LANG_SOURCE([[ - #include - int main() { - __m512d x = _mm512_set1_pd(1.0); - x = _mm512_add_pd(x, x); - double f = _mm512_cvtsd_f64(x); - return f != 2.0; - } - ]]) - ], [ - AC_SUBST([HAVE_AVX512], [1]) - AC_MSG_RESULT([yes]) - ], [ - AC_SUBST([HAVE_AVX512], [0]) - AC_MSG_RESULT([no]) - ]) -]) -AC_SUBST([HAVE_AVX512], [0]) -AC_CHECK_AVX512 - # # HWLOC # @@ -310,6 +227,9 @@ AC_SUBST([HAVE_TRACE], [0]) AS_IF([test x$enable_trace != xno], [AC_SUBST([HAVE_TRACE], [1])]) +AX_CHECK_SSE +AX_CHECK_AVX +AX_CHECK_AVX512 AX_CHECK_NATIVE_ARCH AC_ARG_ENABLE([cuda_debug], @@ -505,14 +425,14 @@ AS_IF([test x$enable_trace != xno], [AC_SUBST([OPTIONS], ["$OPTIONS trace"])]) AS_IF([test x$enable_cuda_debug != xno], [AC_SUBST([OPTIONS], ["$OPTIONS cuda_debug"])]) -AS_IF([test x$enable_native_arch != xno], - [AC_SUBST([OPTIONS], ["$OPTIONS native"])]) AS_IF([test x$HAVE_SSE != x0], [AC_SUBST([OPTIONS], ["$OPTIONS sse"])]) AS_IF([test x$HAVE_AVX != x0], [AC_SUBST([OPTIONS], ["$OPTIONS avx"])]) AS_IF([test x$HAVE_AVX512 != x0], [AC_SUBST([OPTIONS], ["$OPTIONS avx512"])]) +AS_IF([test x$enable_native_arch != xno], + [AC_SUBST([OPTIONS], ["$OPTIONS native"])]) AS_IF([test x$HAVE_FLOAT128 != x0], [AC_SUBST([OPTIONS], ["$OPTIONS float128"])]) AS_IF([test x$enable_map_cache != xno], diff --git a/src/Makefile.in b/src/Makefile.in index 360859f60..d7330eec6 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -9,7 +9,7 @@ LINKER ?= @CXX@ CPPFLAGS ?= @CPPFLAGS@ CXXFLAGS ?= @CXXFLAGS@ NVCCFLAGS ?= @NVCCFLAGS@ -LDFLAGS ?= @LDFLAGS@ @LIBS@ +LDFLAGS ?= @LDFLAGS@ @NVCCLIBS@ DOXYGEN ?= @DX_DOXYGEN@ PYBUILDFLAGS ?= @PYBUILDFLAGS@ PYINSTALLFLAGS ?= @PYINSTALLFLAGS@ From b4d06567c1d9cf5c20a21611c99709c002c76bc7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 08:01:04 -0600 Subject: [PATCH 296/424] Fix the fix. --- configure | 1 + configure.ac | 1 + src/Makefile.in | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 0d6140a84..6d1a1094c 100755 --- a/configure +++ b/configure @@ -24976,6 +24976,7 @@ fi CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" +LIBS="$NVCCLIBS" ac_config_files="$ac_config_files config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h" diff --git a/configure.ac b/configure.ac index f2b92186c..1513aead8 100644 --- a/configure.ac +++ b/configure.ac @@ -375,6 +375,7 @@ AS_IF([test x$STDCXX_IS_SET != x1], CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" +LIBS="$NVCCLIBS" AC_CONFIG_FILES([config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h]) diff --git a/src/Makefile.in b/src/Makefile.in index d7330eec6..360859f60 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -9,7 +9,7 @@ LINKER ?= @CXX@ CPPFLAGS ?= @CPPFLAGS@ CXXFLAGS ?= @CXXFLAGS@ NVCCFLAGS ?= @NVCCFLAGS@ -LDFLAGS ?= @LDFLAGS@ @NVCCLIBS@ +LDFLAGS ?= @LDFLAGS@ @LIBS@ DOXYGEN ?= @DX_DOXYGEN@ PYBUILDFLAGS ?= @PYBUILDFLAGS@ PYINSTALLFLAGS ?= @PYINSTALLFLAGS@ From 74385c86374688066c00a1bd7eb886d0e2c6f108 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 08:06:57 -0600 Subject: [PATCH 297/424] Better? --- config/cuda.m4 | 10 +++++----- configure | 12 ++++++------ configure.ac | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/config/cuda.m4 b/config/cuda.m4 index 2500ef55f..205182530 100644 --- a/config/cuda.m4 +++ b/config/cuda.m4 @@ -14,7 +14,7 @@ AC_DEFUN([AX_CHECK_CUDA], [enable_cuda=no], [enable_cuda=yes]) - NVCCLIBS="$LIBS" + NVCCLIBS="" ac_compile_save="$ac_compile" ac_link_save="$ac_link" ac_run_save="$ac_run" @@ -40,7 +40,7 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" ac_compile='$NVCC -c $NVCCFLAGS conftest.$ac_ext >&5' AC_COMPILE_IFELSE([ @@ -55,7 +55,7 @@ AC_DEFUN([AX_CHECK_CUDA], LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" NVCCLIBS="$NVCCLIBS -lcuda -lcudart" - ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $NVCCLIBS conftest.$ac_ext >&5' + ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext >&5' AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -164,7 +164,7 @@ AC_DEFUN([AX_CHECK_CUDA], LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" NVCCLIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -251,7 +251,7 @@ AC_DEFUN([AX_CHECK_CUDA], LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ #include diff --git a/configure b/configure index 6d1a1094c..cd5ba5996 100755 --- a/configure +++ b/configure @@ -21350,7 +21350,7 @@ else $as_nop fi - NVCCLIBS="$LIBS" + NVCCLIBS="" ac_compile_save="$ac_compile" ac_link_save="$ac_link" ac_run_save="$ac_run" @@ -21524,7 +21524,7 @@ printf %s "checking for a working CUDA installation... " >&6; } CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" ac_compile='$NVCC -c $NVCCFLAGS conftest.$ac_ext >&5' cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -21554,7 +21554,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" NVCCLIBS="$NVCCLIBS -lcuda -lcudart" - ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $NVCCLIBS conftest.$ac_ext >&5' + ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext >&5' cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21712,7 +21712,7 @@ printf %s "checking which CUDA architectures to target... " >&6; } LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" NVCCLIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 @@ -21837,7 +21837,7 @@ printf %s "checking for thrust pinned allocated support... " >&6; } LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" LIBS="-lcuda -lcudart" - ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $NVCCLIBS conftest.$ac_ext>&5' + ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 @@ -24976,7 +24976,7 @@ fi CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" -LIBS="$NVCCLIBS" +LIBS="$LIBS $NVCCLIBS" ac_config_files="$ac_config_files config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h" diff --git a/configure.ac b/configure.ac index 1513aead8..16e0145d5 100644 --- a/configure.ac +++ b/configure.ac @@ -375,7 +375,7 @@ AS_IF([test x$STDCXX_IS_SET != x1], CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" -LIBS="$NVCCLIBS" +LIBS="$LIBS $NVCCLIBS" AC_CONFIG_FILES([config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h]) From 6dd3ac15fce24d171d007e0859bb79a46d3dd91e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 08:14:18 -0600 Subject: [PATCH 298/424] Missed one LIBS -> NVCCLIBS. --- config/cuda.m4 | 2 +- configure | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/cuda.m4 b/config/cuda.m4 index 205182530..b03f84725 100644 --- a/config/cuda.m4 +++ b/config/cuda.m4 @@ -250,7 +250,7 @@ AC_DEFUN([AX_CHECK_CUDA], NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" + NVCCLIBS="-lcuda -lcudart" ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ diff --git a/configure b/configure index cd5ba5996..6ab41d46a 100755 --- a/configure +++ b/configure @@ -21836,7 +21836,7 @@ printf %s "checking for thrust pinned allocated support... " >&6; } NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" + NVCCLIBS="-lcuda -lcudart" ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS $NVCCLIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : From 9cd4056d840ca9636746f9162008869318f886b6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 11:22:57 -0600 Subject: [PATCH 299/424] Move RateLimiter instantiation frinto PacketWriterMethod to make it work with the Verbs hardware packet pacing. --- python/bifrost/packet_writer.py | 6 +++--- src/bifrost/packet_writer.h | 4 ++-- src/ib_verbs_send.hpp | 3 +++ src/packet_writer.cpp | 6 +++--- src/packet_writer.hpp | 38 ++++++++++++++++++++++----------- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 88d503e41..2ae2f7d95 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -52,8 +52,8 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def set_rate_limit(self, rate_limit_Bps): - _check(_bf.bfPacketWriterSetRateLimit(self.obj, rate_limit_Bps)) + def set_rate_limit(self, rate_limit_pps): + _check(_bf.bfPacketWriterSetRateLimit(self.obj, rate_limit_pps)) def reset_counter(self): _check(_bf.bfPacketWriterResetCounter(self.obj)) def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): diff --git a/src/bifrost/packet_writer.h b/src/bifrost/packet_writer.h index 76614c7d1..133a7ac4b 100644 --- a/src/bifrost/packet_writer.h +++ b/src/bifrost/packet_writer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -69,7 +69,7 @@ BFstatus bfUdpVerbsTransmitCreate(BFpacketwriter* obj, BFstatus bfPacketWriterDestroy(BFpacketwriter obj); BFstatus bfPacketWriterSetRateLimit(BFpacketwriter obj, unsigned int rate_limit); -BFstatus bfPacketWriterResetRateLimit(BFpacketwriter obj); +BFstatus bfPacketWriterResetRateLimitCounter(BFpacketwriter obj); BFstatus bfPacketWriterResetCounter(BFpacketwriter obj); BFstatus bfPacketWriterSend(BFpacketwriter obj, BFheaderinfo info, diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 66fb1b54c..775d0aa54 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -701,6 +701,9 @@ class VerbsSend { rate_limit = ((float) rate_limit) / udp_length * pkt_size * 8 / 1000; // Verify that this rate limit is valid + if( rate_limit == 0 ) { + rate_limit = _verbs.hardware_pacing; + } if( rate_limit > _verbs.hardware_pacing ) { throw VerbsSend::Error("Failed to set rate limit, specified rate limit is out of range"); } diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index d89a41823..e358478eb 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. + * Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -172,9 +172,9 @@ BFstatus bfPacketWriterSetRateLimit(BFpacketwriter obj, BF_TRY_RETURN(obj->set_rate_limit(rate_limit)); } -BFstatus bfPacketWriterResetRateLimit(BFpacketwriter obj) { +BFstatus bfPacketWriterResetRateLimitCounter(BFpacketwriter obj) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); - BF_TRY_RETURN(obj->reset_rate_limit()); + BF_TRY_RETURN(obj->reset_rate_limit_counter()); } BFstatus bfPacketWriterResetCounter(BFpacketwriter obj) { diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 0051e88bb..5de858a3d 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -63,7 +63,7 @@ class RateLimiter { : _rate(rate_limit), _counter(0), _first(true) {} inline void set_rate(uint32_t rate_limit) { _rate = rate_limit; } inline uint32_t get_rate() { return _rate; } - inline void reset() { _first = true; _counter = 0; } + inline void reset_counter() { _first = true; _counter = 0; } inline void begin() { if( _first ) { _start = std::chrono::high_resolution_clock::now(); @@ -73,7 +73,7 @@ class RateLimiter { inline void end_and_wait(size_t npackets) { if( _rate > 0 ) { _stop = std::chrono::high_resolution_clock::now(); - _counter += npackets; + _counter += std::max(0, npackets); double elapsed_needed = (double) _counter / _rate; std::chrono::duration elapsed_actual = std::chrono::duration_cast>(_stop-_start); @@ -90,10 +90,11 @@ class RateLimiter { class PacketWriterMethod { protected: - int _fd; + int _fd; + RateLimiter _limiter; public: PacketWriterMethod(int fd) - : _fd(fd) {} + : _fd(fd), _limiter(0) {} virtual ssize_t send_packets(char* hdrs, int hdr_size, char* data, @@ -103,6 +104,9 @@ class PacketWriterMethod { return 0; } virtual const char* get_name() { return "generic_writer"; } + inline void set_rate(uint32_t rate_limit) { _limter.set_rate(rate); } + inline uint32_t get_rate() { return _limiter.get_rate(); } + inline void reset_counter() { _limiter.reset_counter(); } }; class DiskPacketWriter : public PacketWriterMethod { @@ -116,6 +120,7 @@ class DiskPacketWriter : public PacketWriterMethod { int npackets, int flags=0) { ssize_t status, nsent = 0; + _limiter.begin(); for(int i=0; i 0 ) { + _ibv.set_rate_limit(_rate_holder*_last_size); + } } for(int i=0; ireset_stats(); } - inline void set_rate_limit(uint32_t rate_limit) { _limiter.set_rate(rate_limit); } - inline uint32_t get_rate_limit() { return _limiter.get_rate(); } - inline void reset_rate_limit() { _limiter.reset(); } + inline void set_rate_limit(uint32_t rate_limit) { _method.set_rate(rate_limit); } + inline uint32_t get_rate_limit() { return _method.get_rate(); } + inline void reset_rate_limit_counter() { _method.reset_counter(); } inline ssize_t send(char* hdrs, int hdr_size, char* datas, int data_size, int npackets) { - _limiter.begin(); ssize_t nsent = _method->send_packets(hdrs, hdr_size, datas, data_size, npackets); if( nsent == -1 ) { _stats.ninvalid += npackets; @@ -300,7 +313,6 @@ class PacketWriterThread : public BoundThread { _stats.nvalid_bytes += nsent * (hdr_size + data_size); _stats.ninvalid += (npackets - nsent); _stats.ninvalid_bytes += (npackets - nsent) * (hdr_size + data_size); - _limiter.end_and_wait(npackets); } return nsent; } From b2ed5827b7516e3822201ffb666adb2c304f8962 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 18 Sep 2023 11:47:47 -0600 Subject: [PATCH 300/424] Cleanups to get things to compile. --- src/ib_verbs_send.hpp | 2 +- src/packet_writer.hpp | 16 ++++++++-------- src/udp_socket.cpp | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 775d0aa54..b6d3549d9 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -525,7 +525,7 @@ class VerbsSend { "find existing send queue pairs"); // Setup the work requests - int i, j, k; + int i, j; for(i=0; i 0 ) { _stop = std::chrono::high_resolution_clock::now(); - _counter += std::max(0, npackets); + _counter += std::max((size_t) 0, npackets); double elapsed_needed = (double) _counter / _rate; std::chrono::duration elapsed_actual = std::chrono::duration_cast>(_stop-_start); @@ -104,7 +104,7 @@ class PacketWriterMethod { return 0; } virtual const char* get_name() { return "generic_writer"; } - inline void set_rate(uint32_t rate_limit) { _limter.set_rate(rate); } + inline void set_rate(uint32_t rate_limit) { _limiter.set_rate(rate_limit); } inline uint32_t get_rate() { return _limiter.get_rate(); } inline void reset_counter() { _limiter.reset_counter(); } }; @@ -296,9 +296,9 @@ class PacketWriterThread : public BoundThread { : BoundThread(core), _method(method), _core(core) { this->reset_stats(); } - inline void set_rate_limit(uint32_t rate_limit) { _method.set_rate(rate_limit); } - inline uint32_t get_rate_limit() { return _method.get_rate(); } - inline void reset_rate_limit_counter() { _method.reset_counter(); } + inline void set_rate_limit(uint32_t rate_limit) { _method->set_rate(rate_limit); } + inline uint32_t get_rate_limit() { return _method->get_rate(); } + inline void reset_rate_limit_counter() { _method->reset_counter(); } inline ssize_t send(char* hdrs, int hdr_size, char* datas, @@ -387,7 +387,7 @@ class BFpacketwriter_impl { } } inline void set_rate_limit(uint32_t rate_limit) { _writer->set_rate_limit(rate_limit); } - inline void reset_rate_limit() { _writer->reset_rate_limit(); } + inline void reset_rate_limit_counter() { _writer->reset_rate_limit_counter(); } inline void reset_counter() { _framecount = 0; } BFstatus send(BFheaderinfo info, BFoffset seq, @@ -557,7 +557,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, } else { return BF_STATUS_UNSUPPORTED; } - PacketWriterThread* writer = new PacketWriterThread(method, 0, core); + PacketWriterThread* writer = new PacketWriterThread(method, core); if( std::string(format).substr(0, 8) == std::string("generic_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_generic_impl(writer, nsamples), diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 5bd694aaa..bd2cd10b4 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2021, The Bifrost Authors. All rights reserved. + * Copyright (c) 2016-2023, The Bifrost Authors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -101,7 +101,7 @@ BFstatus bfUdpSocketGetPromiscuous(BFudpsocket obj, int* promisc) { try { *promisc = obj->get_promiscuous(); } - catch( Socket::Error ) { + catch( Socket::Error& ) { *promisc = 0; return BF_STATUS_INVALID_STATE; } From 5c265ede0d88d6846f14260baa17257e13a539d7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 19 Sep 2023 18:04:30 -0600 Subject: [PATCH 301/424] Extra _CPU_STATE. --- tools/like_top.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/like_top.py b/tools/like_top.py index 89ca700dd..b22d43a90 100755 --- a/tools/like_top.py +++ b/tools/like_top.py @@ -81,7 +81,6 @@ def get_load_average(): data['lastPID'] = fields[4] return data -_CPU_STATE _CPU_STATE = {} def get_processor_usage(): """ From e7edee8c1c37c9b49c371bdd8dad3e0242da8443 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 25 Sep 2023 07:52:23 -0600 Subject: [PATCH 302/424] Move CUDA gencode options into configure. --- configure | 11 +++++++++++ configure.ac | 9 +++++++++ src/Makefile.in | 18 +----------------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/configure b/configure index 6ab41d46a..fefa29a36 100755 --- a/configure +++ b/configure @@ -24978,6 +24978,17 @@ CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" LIBS="$LIBS $NVCCLIBS" +# +# Additional CUDA flags +# +if test x$HAVE_CUDA != x0 +then : + NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([0-9]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}-gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" + +fi + ac_config_files="$ac_config_files config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h" diff --git a/configure.ac b/configure.ac index 16e0145d5..3f4ec4fd7 100644 --- a/configure.ac +++ b/configure.ac @@ -377,6 +377,15 @@ CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" LIBS="$LIBS $NVCCLIBS" +# +# Additional CUDA flags +# +AS_IF([test x$HAVE_CUDA != x0], + [NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([[0-9]]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}-gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" + ]) + AC_CONFIG_FILES([config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h]) AC_OUTPUT diff --git a/src/Makefile.in b/src/Makefile.in index 360859f60..6a4a5c8b7 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,28 +82,12 @@ JIT_SOURCES ?= \ MAKEFILES = ../config.mk Makefile -ifeq ($(HAVE_CUDA),1) -# All CUDA archs supported by this version of nvcc -GPU_ARCHS_SUPPORTED := $(shell $(NVCC) -h | grep -Po "compute_[0-9]{2}" | cut -d_ -f2 | sort | uniq) -# Intersection of user-specified archs and supported archs -GPU_ARCHS_VALID := $(shell echo $(GPU_ARCHS) $(GPU_ARCHS_SUPPORTED) | xargs -n1 | sort | uniq -d | xargs) -# Latest valid arch -GPU_ARCH_LATEST := $(shell echo $(GPU_ARCHS_VALID) | rev | cut -d' ' -f1 | rev) - -# This creates SASS for all valid requested archs, and PTX for the latest one -NVCC_GENCODE ?= $(foreach arch, $(GPU_ARCHS_VALID), \ - -gencode arch=compute_$(arch),\"code=sm_$(arch)\") \ - -gencode arch=compute_$(GPU_ARCH_LATEST),\"code=compute_$(GPU_ARCH_LATEST)\" -endif - -NVCCFLAGS += $(NVCC_GENCODE) - #NVCCFLAGS += -Xcudafe "--diag_suppress=unrecognized_gcc_pragma" #NVCCFLAGS += --expt-relaxed-constexpr LIB_DIR = ../lib INC_DIR = . -CPPFLAGS += -I. -I$(INC_DIR) -I$(CUDA_INCDIR) +CPPFLAGS += -I. -I$(INC_DIR) LIBBIFROST_VERSION_FILE = $(LIBBIFROST_NAME).version LIBBIFROST_SO_STEM = $(LIB_DIR)/$(LIBBIFROST_NAME)$(SO_EXT) From ebe95b7dbe2553a527cae89de96294d637146ad7 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 25 Sep 2023 08:39:11 -0600 Subject: [PATCH 303/424] Missing space. --- configure | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index fefa29a36..7a07367bc 100755 --- a/configure +++ b/configure @@ -24984,7 +24984,7 @@ LIBS="$LIBS $NVCCLIBS" if test x$HAVE_CUDA != x0 then : NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([0-9]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}-gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" fi diff --git a/configure.ac b/configure.ac index 3f4ec4fd7..ec49f83bd 100644 --- a/configure.ac +++ b/configure.ac @@ -382,7 +382,7 @@ LIBS="$LIBS $NVCCLIBS" # AS_IF([test x$HAVE_CUDA != x0], [NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([[0-9]]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}-gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" ]) From f5f604b809a219ed49f69368640203d53b2c3963 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 25 Sep 2023 17:16:12 -0600 Subject: [PATCH 304/424] We still need NVCC_GENCODE for the cuFFT library. --- configure | 5 ++++- configure.ac | 4 +++- src/Makefile.in | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 7a07367bc..e96cbdc04 100755 --- a/configure +++ b/configure @@ -658,6 +658,7 @@ ac_includes_default="\ ac_header_c_list= ac_subst_vars='OPTIONS LTLIBOBJS +NVCC_GENCODE STDCXX_IS_SET MAP_KERNEL_STDCXX PACKAGE_VERSION_MICRO @@ -24981,10 +24982,12 @@ LIBS="$LIBS $NVCCLIBS" # # Additional CUDA flags # + if test x$HAVE_CUDA != x0 then : NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([0-9]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCC_GENCODE="$NVCC_GENCODE -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" fi diff --git a/configure.ac b/configure.ac index ec49f83bd..cbce8980a 100644 --- a/configure.ac +++ b/configure.ac @@ -380,9 +380,11 @@ LIBS="$LIBS $NVCCLIBS" # # Additional CUDA flags # +AC_SUBST([NVCC_GENCODE], []) AS_IF([test x$HAVE_CUDA != x0], [NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([[0-9]]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCC_GENCODE="$NVCC_GENCODE -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" ]) diff --git a/src/Makefile.in b/src/Makefile.in index 6a4a5c8b7..ca576c6fa 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -26,6 +26,8 @@ CUDA_LIBDIR ?= $(CUDA_HOME)/lib CUDA_LIBDIR64 ?= $(CUDA_HOME)/lib64 CUDA_INCDIR ?= $(CUDA_HOME)/include +NVCC_GENCODE ?= @NVCC_GENCODE@ + LIBBIFROST_OBJS = \ common.o \ memory.o \ From 5d2e720142b84a54343bf58696c24d633e0181fc Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 25 Sep 2023 17:17:39 -0600 Subject: [PATCH 305/424] Ugh, typo. --- configure | 2 +- configure.ac | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index e96cbdc04..845803bfe 100755 --- a/configure +++ b/configure @@ -24987,7 +24987,7 @@ if test x$HAVE_CUDA != x0 then : NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([0-9]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') NVCC_GENCODE="$NVCC_GENCODE -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}" CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" fi diff --git a/configure.ac b/configure.ac index cbce8980a..249ed1568 100644 --- a/configure.ac +++ b/configure.ac @@ -384,7 +384,7 @@ AC_SUBST([NVCC_GENCODE], []) AS_IF([test x$HAVE_CUDA != x0], [NVCC_GENCODE=$(echo $GPU_ARCHS | ${SED} -e 's/\([[0-9]]\{2,3\}\)/-gencode arch=compute_\1,\\"code=sm_\1\\"/g;') NVCC_GENCODE="$NVCC_GENCODE -gencode arch=compute_${GPU_MAX_ARCH},\\\"code=compute_${GPU_MAX_ARCH}\\\"" - NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE} + NVCCFLAGS="$NVCCFLAGS ${NVCC_GENCODE}" CPPFLAGS="$CPPFLAGS -I$CUDA_HOME/include" ]) From 9465265fbc1026665b0906ce84c20ffd3969c753 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 4 Oct 2023 15:02:05 -0600 Subject: [PATCH 306/424] Set a burst size for rate limiting and add a mechanism to wait for the buffers to be free before queuing new packets. --- src/ib_verbs_send.hpp | 44 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index b6d3549d9..56e7346e3 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -54,13 +54,17 @@ #endif #ifndef BF_VERBS_SEND_NPKTBUF -#define BF_VERBS_SEND_NPKTBUF 1024 +#define BF_VERBS_SEND_NPKTBUF 512 #endif #ifndef BF_VERBS_SEND_WCBATCH #define BF_VERBS_SEND_WCBATCH 16 #endif +#ifndef BF_VERBS_SEND_NPKTBURST +#define BF_VERBS_SEND_NPKTBURST 16 +#endif + #define BF_VERBS_SEND_PAYLOAD_OFFSET 42 struct bf_ibv_send_pkt{ @@ -463,7 +467,7 @@ class VerbsSend { qp_init.cap.max_recv_sge = 0; qp_init.cap.max_inline_data = 0; qp_init.qp_type = IBV_QPT_RAW_PACKET; - qp_init.sq_sig_all = 0; + qp_init.sq_sig_all = 1; _verbs.qp = (ibv_qp**) ::malloc(BF_VERBS_SEND_NQP*sizeof(ibv_qp*)); check_null(_verbs.qp, @@ -556,6 +560,34 @@ class VerbsSend { _verbs.pkt_buf[BF_VERBS_SEND_NQP*BF_VERBS_SEND_NPKTBUF-1].wr.send_flags = send_flags; _verbs.pkt_head = _verbs.pkt_buf; } + inline void wait_for_buffers() { + int i; + pollfd pfd; + ibv_cq *ev_cq; + intptr_t ev_cq_ctx; + + // Setup for poll + pfd.fd = _verbs.cc->fd; + pfd.events = POLLIN; + pfd.revents = 0; + + // poll completion channel's fd with given timeout + int rc = ::poll(&pfd, 1, _timeout); + if( rc < 0) { + // Error + throw VerbsSend::Error("error"); + } + + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + ibv_req_notify_cq(_verbs.cq[0], 0); + + // Get the completion event(s) + while( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) == 0 ) { + // Ack the event + ibv_ack_cq_events(_verbs.cq[0], 1); + } + } inline bf_ibv_send_pkt* queue(int npackets) { int i, j; int num_wce; @@ -713,7 +745,7 @@ class VerbsSend { ::memset(&rl_attr, 0, sizeof(ibv_qp_rate_limit_attr)); rl_attr.rate_limit = rate_limit; rl_attr.typical_pkt_sz = pkt_size; - rl_attr.max_burst_sz = 0; + rl_attr.max_burst_sz = BF_VERBS_SEND_NPKTBURST*pkt_size; for(i=0; i BF_VERBS_SEND_NPKTBUF ) { + throw VerbsSend::Error(std::string("Too many packets for the current buffer size")); + } + + this->wait_for_buffers(); + int i; uint64_t offset; for(i=0; i Date: Wed, 4 Oct 2023 15:08:07 -0600 Subject: [PATCH 307/424] Unused variable. --- src/ib_verbs_send.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 56e7346e3..3f1f8f095 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -561,7 +561,6 @@ class VerbsSend { _verbs.pkt_head = _verbs.pkt_buf; } inline void wait_for_buffers() { - int i; pollfd pfd; ibv_cq *ev_cq; intptr_t ev_cq_ctx; From 6f21a1c9a091988b3b570223d03d16f3c7a0d662 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 6 Oct 2023 15:27:42 -0600 Subject: [PATCH 308/424] Remove most of the popen() calls. --- src/ib_verbs_send.hpp | 85 ++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 49 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 3f1f8f095..3b9207c2c 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -147,47 +148,25 @@ class VerbsSend { void get_interface_name(char* name) { sockaddr_in sin; - char ip[INET_ADDRSTRLEN]; socklen_t len = sizeof(sin); check_error(::getsockname(_fd, (sockaddr *)&sin, &len), "query socket name"); - inet_ntop(AF_INET, &(sin.sin_addr), ip, INET_ADDRSTRLEN); - // TODO: Is there a better way to find this? - char cmd[256] = {'\0'}; - char line[256] = {'\0'}; - int is_lo = 0; - sprintf(cmd, "ip route get to %s | grep dev | awk '{print $4}'", ip); - FILE* fp = popen(cmd, "r"); - if( fgets(line, sizeof(line), fp) != NULL) { - if( line[strlen(line)-1] == '\n' ) { - line[strlen(line)-1] = '\0'; - } - if( strncmp(&(line[0]), "lo", 2) == 0 ) { - is_lo = 1; - } - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstringop-truncation" - strncpy(name, &(line[0]), IFNAMSIZ); - #pragma GCC diagnostic pop - } - pclose(fp); - - if( is_lo ) { - // TODO: Is there a way to avoid having to do this? - sprintf(cmd, "ip route show | grep %s | grep -v default | awk '{print $3}'", ip); - fp = popen(cmd, "r"); - if( fgets(line, sizeof(line), fp) != NULL) { - if( line[strlen(line)-1] == '\n' ) { - line[strlen(line)-1] = '\0'; - } - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstringop-truncation" - strncpy(name, &(line[0]), IFNAMSIZ); - #pragma GCC diagnostic pop + ifaddrs *ifaddr; + check_error(::getifaddrs(&ifaddr), + "query interfaces"); + for(ifaddrs *ifa=ifaddr; ifa != NULL; ifa=ifa->ifa_next) { + if( ifa->ifa_addr != NULL) { + if( reinterpret_cast(ifa->ifa_addr)->sin_addr.s_addr == sin.sin_addr.s_addr ) { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-truncation" + ::strncpy(name, ifa->ifa_name, IFNAMSIZ); + #pragma GCC diagnostic pop + break; + } } - pclose(fp); } + ::freeifaddrs(ifaddr); } void get_mac_address(uint8_t* mac) { ifreq ethreq; @@ -201,7 +180,7 @@ class VerbsSend { uint32_t ip; char ip_str[INET_ADDRSTRLEN]; this->get_remote_ip_address(&(ip_str[0])); - inet_pton(AF_INET, &(ip_str[0]), &ip); + ::inet_pton(AF_INET, &(ip_str[0]), &ip); if( ((ip & 0xFF) >= 224) && ((ip & 0xFF) < 240) ) { ETHER_MAP_IP_MULTICAST(&ip, mac); @@ -209,25 +188,33 @@ class VerbsSend { int ret = -1; char cmd[256] = {'\0'}; char line[256] = {'\0'}; + char ip_entry[INET_ADDRSTRLEN]; + unsigned int hw_type, flags; + char mac_str[17]; + char mask[24]; + char dev[IFNAMSIZ]; char* end; + sprintf(cmd, "ping -c 1 %s", ip_str); FILE* fp = popen(cmd, "r"); - sprintf(cmd, "ip neigh | grep -e \"%s \" | awk '{print $5}'", ip_str); - fp = popen(cmd, "r"); - if( fgets(line, sizeof(line), fp) != NULL) { - if( line[strlen(line)-1] == '\n' ) { - line[strlen(line)-1] = '\0'; - } - if( strncmp(&(line[2]), ":", 1) == 0 ) { + + fp = fopen("/proc/net/arp", "r"); + while( ::fgets(line, sizeof(line), fp) != NULL) { + ::sscanf(line, "%s 0x%x 0x%x %s %s %s\n", + ip_entry, &hw_type, &flags, mac_str, mask, dev); + + if( ::strcmp(ip_str, ip_entry) == 0 ) { ret = 0; - mac[0] = (uint8_t) strtol(&line[0], &end, 16); - mac[1] = (uint8_t) strtol(&line[3], &end, 16); - mac[2] = (uint8_t) strtol(&line[6], &end, 16); - mac[3] = (uint8_t) strtol(&line[9], &end, 16); - mac[4] = (uint8_t) strtol(&line[12], &end, 16); - mac[5] = (uint8_t) strtol(&line[15], &end, 16); + mac[0] = (uint8_t) strtol(&mac_str[0], &end, 16); + mac[1] = (uint8_t) strtol(&mac_str[3], &end, 16); + mac[2] = (uint8_t) strtol(&mac_str[6], &end, 16); + mac[3] = (uint8_t) strtol(&mac_str[9], &end, 16); + mac[4] = (uint8_t) strtol(&mac_str[12], &end, 16); + mac[5] = (uint8_t) strtol(&mac_str[15], &end, 16); + break; } } + fclose(fp); check_error(ret, "determine remote hardware address"); } } From 9573c021ca5fe03f3a460ef385e4286a4e6b59d3 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 6 Oct 2023 15:33:21 -0600 Subject: [PATCH 309/424] Bug fix plus try to minimize how much gets reset at each call. --- src/packet_writer.hpp | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index c1a49346c..8b3207582 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -165,15 +165,19 @@ class UDPPacketSender : public PacketWriterMethod { _last_count = npackets; _mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - _iovs = (struct iovec *) malloc(sizeof(struct iovec)*5*npackets); + _iovs = (struct iovec *) malloc(sizeof(struct iovec)2*npackets); ::mlock(_mmsg, sizeof(struct mmsghdr)*npackets); - ::mlock(_iovs, sizeof(struct iovec)*5*npackets); + ::mlock(_iovs, sizeof(struct iovec)*2*npackets); + + ::memset(_mmsg, 0, sizeof(struct mmsghdr)*npackets); + + for(int i=0; i Date: Fri, 6 Oct 2023 15:50:22 -0600 Subject: [PATCH 310/424] Ugh. --- src/packet_writer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 8b3207582..37e938246 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -165,7 +165,7 @@ class UDPPacketSender : public PacketWriterMethod { _last_count = npackets; _mmsg = (struct mmsghdr *) malloc(sizeof(struct mmsghdr)*npackets); - _iovs = (struct iovec *) malloc(sizeof(struct iovec)2*npackets); + _iovs = (struct iovec *) malloc(sizeof(struct iovec)*2*npackets); ::mlock(_mmsg, sizeof(struct mmsghdr)*npackets); ::mlock(_iovs, sizeof(struct iovec)*2*npackets); From 03a45869400026e84954022d3c1b041f86596d1c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 09:18:26 -0600 Subject: [PATCH 311/424] Make sure we only accept complete ARP entries. --- src/ib_verbs_send.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 3b9207c2c..dc85a7fbf 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -203,7 +204,7 @@ class VerbsSend { ::sscanf(line, "%s 0x%x 0x%x %s %s %s\n", ip_entry, &hw_type, &flags, mac_str, mask, dev); - if( ::strcmp(ip_str, ip_entry) == 0 ) { + if( (::strcmp(ip_str, ip_entry) == 0) && (flags & ATF_COM == ATF_COM) ) { ret = 0; mac[0] = (uint8_t) strtol(&mac_str[0], &end, 16); mac[1] = (uint8_t) strtol(&mac_str[3], &end, 16); From c4215875a48df5c5b94785a05c7ab6501ed75297 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 09:19:51 -0600 Subject: [PATCH 312/424] Request completion event notification as soon as the CQ is created. --- src/ib_verbs_send.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index dc85a7fbf..2d1501674 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -442,6 +442,11 @@ class VerbsSend { _verbs.cq[i] = ibv_create_cq(_verbs.ctx, BF_VERBS_SEND_NPKTBUF, NULL, NULL, 0); check_null(_verbs.cq[i], "create send completion queue"); + + // Request notifications before any receive completion can be created. + // Do NOT restrict to solicited-only completions for receive. + check_error(ibv_req_notify_cq(_verbs.cq[i], 0), + "change receive completion queue request notifications"); } // Setup the queue pairs From 4a7e633f8ed372229e810aa7aa4d8b45bae9bfa9 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 09:35:15 -0600 Subject: [PATCH 313/424] Use a more detailed accounting of packets to make sure we don't overwrite the buffers before they are free. --- src/ib_verbs_send.hpp | 85 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 2d1501674..9ff8d98e2 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -89,6 +89,8 @@ struct bf_ibv_send { bf_ibv_send_pkt* pkt_buf; bf_ibv_send_pkt* pkt_head; + int nqueued; + uint8_t offload_csum; uint32_t hardware_pacing; }; @@ -553,37 +555,12 @@ class VerbsSend { _verbs.pkt_buf[BF_VERBS_SEND_NQP*BF_VERBS_SEND_NPKTBUF-1].wr.send_flags = send_flags; _verbs.pkt_head = _verbs.pkt_buf; } - inline void wait_for_buffers() { - pollfd pfd; - ibv_cq *ev_cq; - intptr_t ev_cq_ctx; - - // Setup for poll - pfd.fd = _verbs.cc->fd; - pfd.events = POLLIN; - pfd.revents = 0; - - // poll completion channel's fd with given timeout - int rc = ::poll(&pfd, 1, _timeout); - if( rc < 0) { - // Error - throw VerbsSend::Error("error"); - } - - // Request notification upon the next completion event - // Do NOT restrict to solicited-only completions - ibv_req_notify_cq(_verbs.cq[0], 0); - - // Get the completion event(s) - while( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) == 0 ) { - // Ack the event - ibv_ack_cq_events(_verbs.cq[0], 1); - } - } - inline bf_ibv_send_pkt* queue(int npackets) { + inline void get_packet_buffers(int npackets) { int i, j; int num_wce; ibv_qp_attr qp_attr; + ibv_cq *ev_cq; + intptr_t ev_cq_ctx; ibv_wc wc[BF_VERBS_SEND_WCBATCH]; bf_ibv_send_pkt *send_pkt = NULL; bf_ibv_send_pkt *send_head = NULL; @@ -617,20 +594,39 @@ class VerbsSend { } } + // Get the completion event(s) + while( ibv_get_cq_event(_verbs.cc, &ev_cq, (void **)&ev_cq_ctx) == 0 ) { + // Ack the event + ibv_ack_cq_events(ev_cq, 1); + } + for(i=0; iwr.next = &(_verbs.pkt_head->wr); - _verbs.pkt_head = send_pkt; - } // for each work completion - } while(num_wce); + // Request notification upon the next completion event + // Do NOT restrict to solicited-only completions + if( ibv_req_notify_cq(_verbs.cq[i], 0) ) { + return NULL; + } + } + + while(_verbs.nqueued > 0 ) { + for(i=0; iwr.next = &(_verbs.pkt_head->wr); + _verbs.pkt_head = send_pkt; + } // for each work completion + + // Decrement the number of packet buffers in use + _verbs.nqueued -= num_wce; + } while(num_wce); + } } if( npackets == 0 || !_verbs.pkt_head ) { @@ -645,6 +641,7 @@ class VerbsSend { _verbs.pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; send_tail->wr.next = NULL; + _verbs.nqueued += npackets; return send_head; } @@ -795,8 +792,10 @@ class VerbsSend { throw VerbsSend::Error(std::string("Too many packets for the current buffer size")); } - this->wait_for_buffers(); + // Reclaim a set of buffers to use + this->get_packet_buffers(npackets); + // Load in the new data int i; uint64_t offset; for(i=0; iqueue(npackets); + // Queue for sending ret = ibv_post_send(_verbs.qp[0], &(head->wr), &s); if( ret ) { ret = -1; From c6e428be63dcd9baa412de041056b5df66ea1478 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 09:36:20 -0600 Subject: [PATCH 314/424] Wrong return type. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 9ff8d98e2..7ce7cfd29 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -555,7 +555,7 @@ class VerbsSend { _verbs.pkt_buf[BF_VERBS_SEND_NQP*BF_VERBS_SEND_NPKTBUF-1].wr.send_flags = send_flags; _verbs.pkt_head = _verbs.pkt_buf; } - inline void get_packet_buffers(int npackets) { + inline bf_ibv_send_pkt* get_packet_buffers(int npackets) { int i, j; int num_wce; ibv_qp_attr qp_attr; From f07c6d0d304c404cb5d3594661883ee06c98f075 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 09:45:08 -0600 Subject: [PATCH 315/424] Use compatible headers. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 7ce7cfd29..8d46fcc58 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -39,8 +39,8 @@ #include #include #include -#include #include +#include #include #include #include From 88625a6e51ab2c70b36a89b7a9fc6825dbf30365 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 11 Oct 2023 12:07:17 -0600 Subject: [PATCH 316/424] A couple of fixes to get things working. --- src/ib_verbs_send.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 8d46fcc58..b80fd8c63 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -206,7 +206,7 @@ class VerbsSend { ::sscanf(line, "%s 0x%x 0x%x %s %s %s\n", ip_entry, &hw_type, &flags, mac_str, mask, dev); - if( (::strcmp(ip_str, ip_entry) == 0) && (flags & ATF_COM == ATF_COM) ) { + if( (::strcmp(ip_str, ip_entry) == 0) && (flags & ATF_COM) ) { ret = 0; mac[0] = (uint8_t) strtol(&mac_str[0], &end, 16); mac[1] = (uint8_t) strtol(&mac_str[3], &end, 16); @@ -641,6 +641,7 @@ class VerbsSend { _verbs.pkt_head = (bf_ibv_send_pkt*) send_tail->wr.next; send_tail->wr.next = NULL; + _verbs.nqueued += npackets; return send_head; @@ -793,7 +794,7 @@ class VerbsSend { } // Reclaim a set of buffers to use - this->get_packet_buffers(npackets); + head = this->get_packet_buffers(npackets); // Load in the new data int i; From 0eb382b1ea158254c4f752a1f3d07ff6dd21bd68 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 27 Oct 2023 11:29:54 -0600 Subject: [PATCH 317/424] Enable burst sizes for packet rate limiting for all writer methods. --- src/ib_verbs_send.hpp | 4 +-- src/packet_writer.hpp | 79 +++++++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index b80fd8c63..387696b23 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -715,7 +715,7 @@ class VerbsSend { destroy_buffers(); destroy_context(); } - inline void set_rate_limit(uint32_t rate_limit, size_t udp_length=1) { + inline void set_rate_limit(uint32_t rate_limit, size_t udp_length=1, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) { int i; // Converts to B/s to kb/s assuming a packet size @@ -735,7 +735,7 @@ class VerbsSend { ::memset(&rl_attr, 0, sizeof(ibv_qp_rate_limit_attr)); rl_attr.rate_limit = rate_limit; rl_attr.typical_pkt_sz = pkt_size; - rl_attr.max_burst_sz = BF_VERBS_SEND_NPKTBURST*pkt_size; + rl_attr.max_burst_sz = max_burst_size*pkt_size; for(i=0; i #include +#ifndef BF_SEND_NPKTBURST +#define BF_SEND_NPKTBURST 16 +#endif + class RateLimiter { uint32_t _rate; uint64_t _counter; @@ -91,10 +95,11 @@ class RateLimiter { class PacketWriterMethod { protected: int _fd; + size_t _max_burst_size; RateLimiter _limiter; public: - PacketWriterMethod(int fd) - : _fd(fd), _limiter(0) {} + PacketWriterMethod(int fd, size_t max_burst_size=BF_SEND_NPKTBURST) + : _fd(fd), _max_burst_size(max_burst_size), _limiter(0) {} virtual ssize_t send_packets(char* hdrs, int hdr_size, char* data, @@ -111,24 +116,34 @@ class PacketWriterMethod { class DiskPacketWriter : public PacketWriterMethod { public: - DiskPacketWriter(int fd) - : PacketWriterMethod(fd) {} + DiskPacketWriter(int fd, size_t max_burst_size=BF_SEND_NPKTBURST) + : PacketWriterMethod(fd, max_burst_size) {} ssize_t send_packets(char* hdrs, int hdr_size, char* data, int data_size, int npackets, int flags=0) { - ssize_t status, nsent = 0; - _limiter.begin(); - for(int i=0; i 0) { + _limiter.begin(); + if( _max_burst_size > 0 ) { + nsend = std::min(_max_burst_size, (size_t) npackets); + } else { + nsend = npackets; + } + for(int j=0; j 0) { + _limiter.begin(); + if( _max_burst_size > 0 ) { + nsend = std::min(_max_burst_size, (size_t) npackets); + } else { + nsend = npackets; + } + nsent_batch = ::sendmmsg(_fd, _mmsg+i, nsend, flags); + if( nsent_batch > 0 ) { + nsent += nsent_batch; + } + /* + if( nsent_batch == -1 ) { + std::cout << "sendmmsg failed: " << std::strerror(errno) << " with " << hdr_size << " and " << data_size << std::endl; + } + */ + i += nsend; + npackets -= nsend; + _limiter.end_and_wait(nsend); } - */ return nsent; } @@ -210,8 +239,8 @@ class UDPVerbsSender : public PacketWriterMethod { iovec* _iovs; uint32_t _rate_holder; public: - UDPVerbsSender(int fd) - : PacketWriterMethod(fd), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), + UDPVerbsSender(int fd, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) + : PacketWriterMethod(fd, max_burst_size), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), _last_count(0), _mmsg(NULL), _iovs(NULL), _rate_holder(0) {} ~UDPVerbsSender() { if( _mmsg ) { @@ -256,7 +285,7 @@ class UDPVerbsSender : public PacketWriterMethod { _ibv.get_udp_header(&(_udp_hdr.udp), _last_size); if( _rate_holder > 0 ) { - _ibv.set_rate_limit(_rate_holder*_last_size); + _ibv.set_rate_limit(_rate_holder*_last_size, _last_size, _max_burst_size); } } From 75c74f6a89937a4df8fa9e3dd9cdd2603c1cf3c8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 4 Dec 2023 16:00:01 -0700 Subject: [PATCH 318/424] Fix an off-by-one error from a header mis-match in how packets are generated vs received. --- src/formats/pbeam.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index a7dc966a7..bb910fbec 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -64,7 +64,7 @@ class PBeamDecoder: virtual public PacketDecoder { int pld_size = pkt_size - sizeof(pbeam_hdr_type); pkt->decimation = be16toh(pkt_hdr->navg); pkt->time_tag = be64toh(pkt_hdr->seq); - pkt->seq = (pkt->time_tag - 1) / pkt->decimation; + pkt->seq = pkt->time_tag / pkt->decimation; //pkt->nsrc = pkt_hdr->nserver; pkt->nsrc = _nsrc; pkt->src = (pkt_hdr->beam - _src0) * pkt_hdr->nserver + (pkt_hdr->server - 1); From b0254e8d522ee39e4ad5f103ca61a45b16572238 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Dec 2023 11:14:55 -0700 Subject: [PATCH 319/424] I thought this was in configure.ac already. --- src/bifrost/config.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bifrost/config.h.in b/src/bifrost/config.h.in index 1e3e52ed4..752a5c067 100644 --- a/src/bifrost/config.h.in +++ b/src/bifrost/config.h.in @@ -63,7 +63,7 @@ extern "C" { #define BF_HWLOC_ENABLED @HAVE_HWLOC@ #define BF_VMA_ENABLED @HAVE_VMA@ #define BF_VERBS_ENABLED @HAVE_VERBS@ -#define BF_VERBS_NPKTBUF @VERBS_NPKTBUF@ +#define BF_VERBS_NPKTBUF 32768 #define BF_RDMA_ENABLED @HAVE_RDMA@ #define BF_RDMA_MAXMEM @RDMA_MAXMEM@ From b16dc15ada2da3de73bbacccb59b786567cfd77e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Dec 2023 13:06:47 -0700 Subject: [PATCH 320/424] Fix a bad merge. --- src/ib_verbs.hpp | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index fcf557660..37b559068 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -28,8 +28,6 @@ #pragma once -#include - #include #include #include @@ -52,6 +50,10 @@ #define BF_VERBS_NQP 1 #endif +#ifndef BF_VERBS_NPKTBUF +#define BF_VERBS_NPKTBUF 8192 +#endif + #ifndef BF_VERBS_WCBATCH #define BF_VERBS_WCBATCH 16 #endif @@ -276,32 +278,13 @@ class Verbs { _verbs.mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; _verbs.mr_buf = (uint8_t *) ::mmap(NULL, _verbs.mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - check_error(_verbs.mr_buf == MAP_FAILED ? -1 : 0, - "allocate memory region buffer"); + check_error(_verbs.mr_buf == MAP_FAILED, + "allocate receive memory region buffer"); check_error(::mlock(_verbs.mr_buf, _verbs.mr_size), "lock receive memory region buffer"); _verbs.mr = ibv_reg_mr(_verbs.pd, _verbs.mr_buf, _verbs.mr_size, IBV_ACCESS_LOCAL_WRITE); check_null(_verbs.mr, - "register memory region"); - - // Start Send - - _verbs.send_pkt_buf = (bf_ibv_send_pkt*) ::malloc(BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); - check_null(_verbs.send_pkt_buf, - "allocate send packet buffer"); - ::memset(_verbs.send_pkt_buf, 0, BF_VERBS_NPKTBUF*BF_VERBS_NQP * sizeof(struct bf_ibv_send_pkt)); - _verbs.send_mr_size = (size_t) BF_VERBS_NPKTBUF*BF_VERBS_NQP * _pkt_size_max; - _verbs.send_mr_buf = (uint8_t *) ::mmap(NULL, _verbs.send_mr_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_LOCKED, -1, 0); - - check_error(_verbs.send_mr_buf == MAP_FAILED ? -1 : 0, - "allocate memory region buffer"); - check_error(::mlock(_verbs.send_mr_buf, _verbs.send_mr_size), - "lock memory region buffer"); - _verbs.send_mr = ibv_reg_mr(_verbs.pd, _verbs.send_mr_buf, _verbs.send_mr_size, IBV_ACCESS_LOCAL_WRITE); - check_null(_verbs.send_mr, - "register memory region"); - - // End Send + "register receive memory region"); } void destroy_buffers() { int failures = 0; From 749f0ba87d1d60b694ce28ddfc3eaf666c08ff7c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Dec 2023 13:17:22 -0700 Subject: [PATCH 321/424] Give up on packet pacing for now. --- src/ib_verbs_send.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 387696b23..498dd9873 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -334,9 +334,11 @@ class VerbsSend { std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; _verbs.hardware_pacing = 0; + /* if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) ) { _verbs.hardware_pacing = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_max; } + */ std::cout << "_verbs.hardware_pacing: " << (int) _verbs.hardware_pacing << std::endl; break; @@ -731,6 +733,7 @@ class VerbsSend { } // Apply the rate limit + /* ibv_qp_rate_limit_attr rl_attr; ::memset(&rl_attr, 0, sizeof(ibv_qp_rate_limit_attr)); rl_attr.rate_limit = rate_limit; @@ -740,7 +743,7 @@ class VerbsSend { check_error(ibv_modify_qp_rate_limit(_verbs.qp[i], &rl_attr), "set queue pair rate limit"); } - + */ _rate_limit = rate_limit; } inline void get_ethernet_header(bf_ethernet_hdr* hdr) { From e59a8cae17a665f82af8312b3f54ed2eee8e6bf1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 11 Dec 2023 10:41:37 -0700 Subject: [PATCH 322/424] Make sure everything expects an OS index and use PU instead of CORE. --- src/hw_locality.cpp | 85 ++++++++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/src/hw_locality.cpp b/src/hw_locality.cpp index 4f40eeca6..dfbaa60d2 100644 --- a/src/hw_locality.cpp +++ b/src/hw_locality.cpp @@ -31,15 +31,24 @@ #if BF_HWLOC_ENABLED int HardwareLocality::get_numa_node_of_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_PU); int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); int ret = -1; if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_type(_topo, HWLOC_OBJ_CORE, core); + // Find correct processing unit (PU) for the core (which is an os_index) + hwloc_obj_t obj = NULL; hwloc_obj_t tmp = NULL; - while( (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, tmp)) != NULL ) { - if( hwloc_bitmap_isset(obj->nodeset, tmp->os_index) ) { + while( (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_PU, tmp)) != NULL ) { + if( tmp->os_index == core ) { + obj = tmp; + break; + } + } + // Find the correct NUMA node for the PU + while( obj != NULL && (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, tmp)) != NULL ) { + if( hwloc_bitmap_intersects(obj->cpuset, tmp->cpuset) ) { ret = tmp->os_index; + break; } } } @@ -47,43 +56,63 @@ int HardwareLocality::get_numa_node_of_core(int core) { } int HardwareLocality::bind_thread_memory_to_core(int core) { - int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_CORE); + int core_depth = hwloc_get_type_or_below_depth(_topo, HWLOC_OBJ_PU); int ncore = hwloc_get_nbobjs_by_depth(_topo, core_depth); int ret = 0; if( 0 <= core && core < ncore ) { - hwloc_obj_t obj = hwloc_get_obj_by_depth(_topo, core_depth, core); -#if HWLOC_API_VERSION >= 0x00020000 - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); - if( !hwloc_bitmap_intersects(cpuset, hwloc_topology_get_allowed_cpuset(_topo)) ) { - throw std::runtime_error("requested core is not in the list of allowed cores"); + // Find correct processing unit (PU) for the core (with is a os_index) + hwloc_obj_t obj = NULL; + hwloc_obj_t tmp = NULL; + while( (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_PU, tmp)) != NULL ) { + if( tmp->os_index == core ) { + obj = tmp; + break; + } } + if( obj != NULL ) { +#if HWLOC_API_VERSION >= 0x00020000 + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->cpuset); + if( !hwloc_bitmap_intersects(cpuset, hwloc_topology_get_allowed_cpuset(_topo)) ) { + throw std::runtime_error("requested core is not in the list of allowed cores"); + } #else - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); #endif - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_membind(_topo, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_membind(_topo, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } } return ret; } int HardwareLocality::bind_memory_area_to_numa_node(const void* addr, size_t size, int node) { int nnode = hwloc_get_nbobjs_by_type(_topo, HWLOC_OBJ_NUMANODE); - int ret = 0; + int ret = -1; if( 0 <= node && node < nnode ) { - hwloc_obj_t obj = hwloc_get_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, node); -#if HWLOC_API_VERSION >= 0x00020000 - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->nodeset); -#else - hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); -#endif - hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads - hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; - hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; - ret = hwloc_set_area_membind(_topo, addr, size, cpuset, policy, flags); - hwloc_bitmap_free(cpuset); + // Find correct NUMA node for the node (which is an os_index) + hwloc_obj_t obj = NULL; + hwloc_obj_t tmp = NULL; + while( (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, tmp)) != NULL ) { + if( tmp->os_index == node ) { + obj = tmp; + break; + } + } + if( obj != NULL ) { + #if HWLOC_API_VERSION >= 0x00020000 + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->nodeset); + #else + hwloc_cpuset_t cpuset = hwloc_bitmap_dup(obj->allowed_cpuset); + #endif + hwloc_bitmap_singlify(cpuset); // Avoid hyper-threads + hwloc_membind_policy_t policy = HWLOC_MEMBIND_BIND; + hwloc_membind_flags_t flags = HWLOC_MEMBIND_THREAD; + ret = hwloc_set_area_membind(_topo, addr, size, cpuset, policy, flags); + hwloc_bitmap_free(cpuset); + } } return ret; } From 451650b0548c57b468691fdad0bc7de6477106dc Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 11 Dec 2023 10:41:59 -0700 Subject: [PATCH 323/424] Additional verbs configuration options and packet pacing testing. --- configure | 88 +++++++++++++++++++++++++++++++++++++++++ configure.ac | 42 ++++++++++++++++++++ src/bifrost/config.h.in | 3 ++ src/ib_verbs_send.hpp | 9 ++++- 4 files changed, 141 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 845803bfe..2580e1202 100755 --- a/configure +++ b/configure @@ -739,6 +739,9 @@ HAVE_CUDA CUDA_HOME RDMA_MAXMEM HAVE_RDMA +VERBS_SEND_PACING +VERBS_SEND_NPKTBUF +VERBS_NPKTBUF HAVE_VERBS HAVE_VMA HAVE_HWLOC @@ -856,6 +859,8 @@ with_ctags enable_hwloc enable_vma enable_verbs +with_rx_buffer_size +with_tx_buffer_size enable_rdma with_rdma_max_mem with_cuda_home @@ -1572,6 +1577,10 @@ Optional Packages: --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-ctags=[PATH] absolute path to ctags executable + --with-rx-buffer-size=N default Infiniband verbs receive buffer size in + packets (default=8192) + --with-tx-buffer-size=N default Infiniband verbs send buffer size in packets + (default=512) --with-rdma-max-mem=N maximum RDMA buffer size in bytes (default=134217728) --with-cuda-home CUDA install path (default=/usr/local/cuda) @@ -21240,6 +21249,85 @@ fi fi + +# Check whether --with-rx-buffer-size was given. +if test ${with_rx_buffer_size+y} +then : + withval=$with_rx_buffer_size; +else $as_nop + with_rx_buffer_size=8192 +fi + + VERBS_NPKTBUF=$with_rx_buffer_size + + if test x$HAVE_VERBS = x0 +then : + VERBS_NPKTBUF=0 + +fi + + +# Check whether --with-tx-buffer-size was given. +if test ${with_tx_buffer_size+y} +then : + withval=$with_tx_buffer_size; +else $as_nop + with_tx_buffer_size=512 +fi + + VERBS_SEND_NPKTBUF=$with_tx_buffer_size + + if test x$HAVE_VERBS = x0 +then : + VERBS_SEND_NPKTBUF=0 + +fi + + if test x$HAVE_VERBS != x0 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Infiniband verbs packet pacing support" >&5 +printf %s "checking for Infiniband verbs packet pacing support... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include +int +main (void) +{ + + int ndev, d; + ibv_device** ibv_dev_list = NULL; + ibv_context* ibv_ctx = NULL; + ibv_device_attr_ex ibv_dev_attr; + + ibv_dev_list = ibv_get_device_list(&ndev); + for(d=0; d&5 +printf "%s\n" "yes" >&6; } +else $as_nop + VERBS_SEND_PACING=0 + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi + # # RDMA # diff --git a/configure.ac b/configure.ac index 249ed1568..6847b4099 100644 --- a/configure.ac +++ b/configure.ac @@ -139,6 +139,48 @@ AS_IF([test x$enable_verbs != xno], [AC_SUBST([HAVE_VERBS], [1]) LIBS="$LIBS -libverbs"])]) + AC_ARG_WITH([rx-buffer-size], + [AS_HELP_STRING([--with-rx-buffer-size=N], + [default Infiniband verbs receive buffer size in packets (default=8192)])], + [], + [with_rx_buffer_size=8192]) + AC_SUBST([VERBS_NPKTBUF], [$with_rx_buffer_size]) + AS_IF([test x$HAVE_VERBS = x0], + [AC_SUBST([VERBS_NPKTBUF], [0])]) + + AC_ARG_WITH([tx-buffer-size], + [AS_HELP_STRING([--with-tx-buffer-size=N], + [default Infiniband verbs send buffer size in packets (default=512)])], + [], + [with_tx_buffer_size=512]) + AC_SUBST([VERBS_SEND_NPKTBUF], [$with_tx_buffer_size]) + AS_IF([test x$HAVE_VERBS = x0], + [AC_SUBST([VERBS_SEND_NPKTBUF], [0])]) + + AS_IF([test x$HAVE_VERBS != x0], + [AC_MSG_CHECKING([for Infiniband verbs packet pacing support]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include ]], + [[ + int ndev, d; + ibv_device** ibv_dev_list = NULL; + ibv_context* ibv_ctx = NULL; + ibv_device_attr_ex ibv_dev_attr; + + ibv_dev_list = ibv_get_device_list(&ndev); + for(d=0; d Date: Mon, 11 Dec 2023 11:17:55 -0700 Subject: [PATCH 324/424] Reset tmp before trying to find the NUMA node. --- src/hw_locality.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hw_locality.cpp b/src/hw_locality.cpp index dfbaa60d2..ce505f500 100644 --- a/src/hw_locality.cpp +++ b/src/hw_locality.cpp @@ -45,6 +45,7 @@ int HardwareLocality::get_numa_node_of_core(int core) { } } // Find the correct NUMA node for the PU + tmp = NULL; while( obj != NULL && (tmp = hwloc_get_next_obj_by_type(_topo, HWLOC_OBJ_NUMANODE, tmp)) != NULL ) { if( hwloc_bitmap_intersects(obj->cpuset, tmp->cpuset) ) { ret = tmp->os_index; From 801ea2c79d61a11a6a320fdcc7aaeed23835c69e Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 19 Jan 2024 14:13:33 -0700 Subject: [PATCH 325/424] began simple header --- src/formats/simple.hpp | 157 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 src/formats/simple.hpp diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp new file mode 100644 index 000000000..b704d26a4 --- /dev/null +++ b/src/formats/simple.hpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019, The Bifrost Authors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of The Bifrost Authors nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "base.hpp" + +struct __attribute__((packed)) simple_hdr_type { + int32_t seq; //ms past the time packets started sending +}; + +class SIMPLEDecoder : virtual public PacketDecoder { + inline bool valid_packet(const PacketDesc* pkt) const { + return (pkt->seq >= 0 ) + } +public: + SIMPLEDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} + inline bool operator()(const uint8_t* pkt_ptr, + int pkt_size, + PacketDesc* pkt) const { + if( pkt_size < (int)sizeof(simple_hdr_type) ) { + return false; + } + const simple_hdr_type* pkt_hdr = (simple_hdr_type*)pkt_ptr; + const uint8_t* pkt_pld = pkt_ptr + sizeof(simple_hdr_type); + int pld_size = pkt_size - sizeof(simple_hdr_type); + pkt->seq = be32toh(pkt_hdr->timetag); + pkt->nsrc = 1; + pkt->src = 0; + pkt->payload_size = pld_size; + pkt->payload_ptr = pkt_pld; + pkt->nchan = 1; + pkt->chan0 = 0; + return this->valid_packet(pkt); + } +}; + +class SIMPLEProcessor : virtual public PacketProcessor { +public: + inline void operator()(const PacketDesc* pkt, + uint64_t seq0, + uint64_t nseq_per_obuf, + int nbuf, + uint8_t* obufs[], + size_t ngood_bytes[], + size_t* src_ngood_bytes[]) { + int obuf_idx = ((pkt->seq - seq0 >= 1*nseq_per_obuf) + + (pkt->seq - seq0 >= 2*nseq_per_obuf)); + size_t obuf_seq0 = seq0 + obuf_idx*nseq_per_obuf; + size_t nbyte = pkt->payload_size * BF_UNPACK_FACTOR; + ngood_bytes[obuf_idx] += nbyte; + src_ngood_bytes[obuf_idx][0] += nbyte; + // **CHANGED RECENTLY + int payload_size = pkt->payload_size;//pkt->nchan*(PKT_NINPUT*2*PKT_NBIT/8); + + size_t obuf_offset = (pkt->seq-obuf_seq0)*pkt->nsrc*payload_size; + typedef unaligned256_type itype; + typedef aligned256_type otype; + + obuf_offset *= BF_UNPACK_FACTOR; + + // Note: Using these SSE types allows the compiler to use SSE instructions + // However, they require aligned memory (otherwise segfault) + itype const* __restrict__ in = (itype const*)pkt->payload_ptr; + otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; + + int chan = 0; + //cout << pkt->src << ", " << pkt->nsrc << endl; + //cout << pkt->nchan << endl; + for( ; channchan; ++chan ) { +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED + _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), + _mm256_loadu_si256(reinterpret_cast(&in[chan]))); +#else +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; + aligned128_type* ddst = (aligned128_type*) &out[pkt->src + pkt->nsrc*chan]; + + _mm_store_si128(reinterpret_cast<__m128i*>(ddst), + _mm_loadu_si128(reinterpret_cast(dsrc))); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), + _mm_loadu_si128(reinterpret_cast(dsrc+1))); +#else + ::memcpy(&out[pkt->src + pkt->nsrc*chan], + &in[chan], sizeof(otype)); +#endif +#endif + } + } + + inline void blank_out_source(uint8_t* data, + int src, + int nsrc, + int nchan, + int nseq) { + typedef aligned256_type otype; + otype* __restrict__ aligned_data = (otype*)data; + for( int t=0; t(&aligned_data[src + nsrc*(c + nchan*t)]), + _mm256_setzero_si256()); +#else +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nchan*t)]; + + _mm_store_si128(reinterpret_cast<__m128i*>(ddst), + _mm_setzero_si128()); + _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), + _mm_setzero_si128()); +#else + ::memset(&aligned_data[src + nsrc*(c + nchan*t)], + 0, sizeof(otype)); +#endif +#endif + } + } + } +}; + +class SIMPLEHeaderFiller : virtual public PacketHeaderFiller { +public: + inline int get_size() { return sizeof(simple_hdr_type); } + inline void operator()(const PacketDesc* hdr_base, + BFoffset framecount, + char* hdr) { + chips_hdr_type* header = reinterpret_cast(hdr); + memset(header, 0, sizeof(simple_hdr_type)); + + header->seq = htobe32(hdr_base->seq); + } +}; From c4164969666473b58c8195ed259d5cf04fe08fc6 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 19 Jan 2024 16:11:22 -0700 Subject: [PATCH 326/424] progress --- src/bifrost/packet_capture.h | 4 ++ src/formats/formats.hpp | 1 + src/formats/simple.hpp | 2 +- src/packet_capture.hpp | 93 ++++++++++++++++++++++++++++++++++-- src/packet_writer.hpp | 14 ++++++ 5 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/bifrost/packet_capture.h b/src/bifrost/packet_capture.h index f599824fc..b280c20d4 100644 --- a/src/bifrost/packet_capture.h +++ b/src/bifrost/packet_capture.h @@ -38,6 +38,8 @@ extern "C" { // Callback setup +typedef int (*BFpacketcapture_simple_sequence_callback)(BFoffset, int, int, int, + BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_chips_sequence_callback)(BFoffset, int, int, int, BFoffset*, void const**, size_t*); typedef int (*BFpacketcapture_ibeam_sequence_callback)(BFoffset, int, int, int, @@ -59,6 +61,8 @@ typedef struct BFpacketcapture_callback_impl* BFpacketcapture_callback; BFstatus bfPacketCaptureCallbackCreate(BFpacketcapture_callback* obj); BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj); +BFstatus bfPacketCaptureCallbackSetSIMPLE(BFpacketcapture_callback obj, + BFpacketcapture_simple_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback); BFstatus bfPacketCaptureCallbackSetIBeam(BFpacketcapture_callback obj, diff --git a/src/formats/formats.hpp b/src/formats/formats.hpp index 14ed3ad9e..885030bc7 100644 --- a/src/formats/formats.hpp +++ b/src/formats/formats.hpp @@ -37,3 +37,4 @@ #include "tbf.hpp" #include "ibeam.hpp" #include "pbeam.hpp" +#include "simple.hpp" diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index b704d26a4..3e10b59a5 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -31,7 +31,7 @@ #include "base.hpp" struct __attribute__((packed)) simple_hdr_type { - int32_t seq; //ms past the time packets started sending + uint32_t seq; }; class SIMPLEDecoder : virtual public PacketDecoder { diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index a2551c3d7..10e3483a3 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -372,6 +372,7 @@ inline uint64_t round_nearest(uint64_t val, uint64_t mult) { } class BFpacketcapture_callback_impl { + BFpacketcapture_simple_sequence_callback _simple_callback; BFpacketcapture_chips_sequence_callback _chips_callback; BFpacketcapture_ibeam_sequence_callback _ibeam_callback; BFpacketcapture_pbeam_sequence_callback _pbeam_callback; @@ -382,9 +383,15 @@ class BFpacketcapture_callback_impl { BFpacketcapture_drx8_sequence_callback _drx8_callback; public: BFpacketcapture_callback_impl() - : _chips_callback(NULL), _ibeam_callback(NULL), _pbeam_callback(NULL), - _cor_callback(NULL), _vdif_callback(NULL), _tbn_callback(NULL), - _drx_callback(NULL), _drx8_callback(NULL) {} + : _simple_callback(NULL), _chips_callback(NULL), _ibeam_callback(NULL), + _pbeam_callback(NULL), _cor_callback(NULL), _vdif_callback(NULL), + _tbn_callback(NULL), _drx_callback(NULL), _drx8_callback(NULL) {} + inline void set_simple(BFpacketcapture_simple_sequence_callback callback) { + _simple_callback = callback; + } + inline BFpacketcapture_simple_sequence_callback get_simple() { + return _simple_callback; + inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } @@ -590,6 +597,78 @@ class BFpacketcapture_impl { BFpacketcapture_status recv(); }; +class BFpacketcapture_simple_impl : public BFpacketcapture_impl { + ProcLog _type_log; + ProcLog _chan_log; + + BFpacketcapture_simple_sequence_callback _sequence_callback; + + void on_sequence_start(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size ) { + // TODO: Might be safer to round to nearest here, but the current firmware + // always starts things ~3 seq's before the 1sec boundary anyway. + //seq = round_up(pkt->seq, _slot_ntime); + //*_seq = round_nearest(pkt->seq, _slot_ntime); + _seq = round_up(pkt->seq, _slot_ntime); + this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); + } + void on_sequence_active(const PacketDesc* pkt) { + if( pkt ) { + //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; + } + else { + //cout << "No latest packet" << endl; + } + } + inline bool has_sequence_changed(const PacketDesc* pkt) { + return (pkt->chan0 != _chan0) \ + || (pkt->nchan != _nchan); + } + void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { + *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; + + if( _sequence_callback ) { + int status = (*_sequence_callback)(*seq0, + _chan0, + _nchan, + _nsrc, + time_tag, + hdr, + hdr_size); + if( status != 0 ) { + // TODO: What to do here? Needed? + throw std::runtime_error("BAD HEADER CALLBACK STATUS"); + } + } else { + // Simple default for easy testing + *time_tag = *seq0; + *hdr = NULL; + *hdr_size = 0; + } + + _chan_log.update() << "chan0 : " << _chan0 << "\n" + << "nchan : " << _nchan << "\n" + << "payload_size : " << _payload_size << "\n"; + } +public: + inline BFpacketcapture_simple_impl(PacketCaptureThread* capture, + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) + : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), + _type_log((std::string(capture->get_name())+"/type").c_str()), + _chan_log((std::string(capture->get_name())+"/chans").c_str()), + _sequence_callback(sequence_callback->get_simple()) { + _decoder = new SIMPLEDecoder(nsrc, src0); + _processor = new SIMPLEProcessor(); + _type_log.update("type : %s\n", "simple"); + } +}; class BFpacketcapture_chips_impl : public BFpacketcapture_impl { ProcLog _type_log; ProcLog _chan_log; @@ -1235,7 +1314,13 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, BFiomethod backend) { BF_ASSERT(obj, BF_STATUS_INVALID_POINTER); - if( std::string(format).substr(0, 5) == std::string("chips") ) { + if( std::string(format).substr(0, 6) == std::string("simple") ) { + if( backend == BF_IO_DISK ) { + // Need to know how much to read at a time + int nchan = 1; + max_payload_size = sizeof(simple_hdr_type) + (4*nchan); + } + } else if( std::string(format).substr(0, 5) == std::string("chips") ) { if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 7884f5bbd..d3c0228fa 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -446,6 +446,18 @@ class BFpacketwriter_generic_impl : public BFpacketwriter_impl { } }; +class BFpacketwriter_simple_impl : public BFpacketwriter_impl { + ProcLog _type_log; +public: + inline BFpacketwriter_simple_impl(PacketWriterThread* writer, + int nsamples) + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_I2), + _type_log((std::string(writer->get_name())+"/type").c_str()) { + _filler = new SIMPLEHeaderFiller(); + _type_log.update("type : %s\n", "simple"); + } +}; + class BFpacketwriter_chips_impl : public BFpacketwriter_impl { ProcLog _type_log; public: @@ -558,6 +570,8 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, int nsamples = 0; if(std::string(format).substr(0, 8) == std::string("generic_") ) { nsamples = std::atoi((std::string(format).substr(8, std::string(format).length())).c_str()); + } else if( std::string(format).substr(0, 7) == std::string("simple_") ) { + nsamples = 4092; } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; From 166c5664d03b5fe99eec27419851a3db762da2fe Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 24 Jan 2024 16:54:50 -0700 Subject: [PATCH 327/424] progress --- python/bifrost/packet_capture.py | 4 ++++ src/formats/simple.hpp | 16 ++++++++-------- src/packet_capture.cpp | 21 +++++++++++++++++++-- src/packet_capture.hpp | 29 +++++++++++------------------ 4 files changed, 42 insertions(+), 28 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 760debd98..aae652231 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -38,6 +38,10 @@ class PacketCaptureCallback(BifrostObject): def __init__(self): BifrostObject.__init__( self, _bf.bfPacketCaptureCallbackCreate, _bf.bfPacketCaptureCallbackDestroy) + def set_simple(self, fnc): + self._ref_cache['simple'] = _bf.BFpacketcapture_simple_sequence_callback(fnc) + _check(_bf.bfPacketCaptureCallbackSetSIMPLE( + self.obj, self._ref_cache['simple'])) def set_chips(self, fnc): self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 3e10b59a5..4060efb05 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -36,7 +36,7 @@ struct __attribute__((packed)) simple_hdr_type { class SIMPLEDecoder : virtual public PacketDecoder { inline bool valid_packet(const PacketDesc* pkt) const { - return (pkt->seq >= 0 ) + return (pkt->seq >= 0 ); } public: SIMPLEDecoder(int nsrc, int src0) : PacketDecoder(nsrc, src0) {} @@ -49,7 +49,7 @@ class SIMPLEDecoder : virtual public PacketDecoder { const simple_hdr_type* pkt_hdr = (simple_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(simple_hdr_type); int pld_size = pkt_size - sizeof(simple_hdr_type); - pkt->seq = be32toh(pkt_hdr->timetag); + pkt->seq = be32toh(pkt_hdr->seq); pkt->nsrc = 1; pkt->src = 0; pkt->payload_size = pld_size; @@ -93,7 +93,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { //cout << pkt->src << ", " << pkt->nsrc << endl; //cout << pkt->nchan << endl; for( ; channchan; ++chan ) { -#if defined BF_AVX_ENABLED && BF_AVX_ENABLED +/*#if defined BF_AVX_ENABLED && BF_AVX_ENABLED _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), _mm256_loadu_si256(reinterpret_cast(&in[chan]))); #else @@ -104,12 +104,12 @@ class SIMPLEProcessor : virtual public PacketProcessor { _mm_store_si128(reinterpret_cast<__m128i*>(ddst), _mm_loadu_si128(reinterpret_cast(dsrc))); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_loadu_si128(reinterpret_cast(dsrc+1))); -#else + _mm_loadu_si128(reinterpret_cast(dsrc+1)));*/ +//#else ::memcpy(&out[pkt->src + pkt->nsrc*chan], &in[chan], sizeof(otype)); -#endif -#endif +//#endif +//#endif } } @@ -149,7 +149,7 @@ class SIMPLEHeaderFiller : virtual public PacketHeaderFiller { inline void operator()(const PacketDesc* hdr_base, BFoffset framecount, char* hdr) { - chips_hdr_type* header = reinterpret_cast(hdr); + simple_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(simple_hdr_type)); header->seq = htobe32(hdr_base->seq); diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index bbe8526a1..92094342e 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -28,7 +28,7 @@ #include "packet_capture.hpp" -#define BF_JAYCE_DEBUG 0 +#define BF_JAYCE_DEBUG 1 #if BF_JAYCE_DEBUG #define BF_PRINTD(stmt) \ @@ -98,16 +98,22 @@ int PacketCaptureThread::run(uint64_t seq_beg, BF_PRINTD("CONTINUE HERE"); continue; } - BF_PRINTD("FINALLY"); + BF_PRINTD("FINALLY1"); ++_stats.nvalid; + BF_PRINTD("FINALLY2"); _stats.nvalid_bytes += _pkt.payload_size; + BF_PRINTD("FINALLY3"); ++_src_stats[_pkt.src].nvalid; + BF_PRINTD("FINALLY4"); _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; + BF_PRINTD("FINALLY5"); // HACK TODO: src_ngood_bytes should be accumulated locally and // then atomically updated, like ngood_bytes. The // current way is not thread-safe. + BF_PRINTD("INPUTS" << " " << &_pkt << " " << seq_beg << " " << nseq_per_obuf << " " << nbuf <<" " << obufs<< " " << local_ngood_bytes << " " << src_ngood_bytes); (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, local_ngood_bytes, /*local_*/src_ngood_bytes); + BF_PRINTD("FINALLY6"); } if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } @@ -125,6 +131,13 @@ BFstatus bfPacketCaptureCallbackDestroy(BFpacketcapture_callback obj) { return BF_STATUS_SUCCESS; } +BFstatus bfPacketCaptureCallbackSetSIMPLE(BFpacketcapture_callback obj, + BFpacketcapture_simple_sequence_callback callback) { + BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); + obj->set_simple(callback); + return BF_STATUS_SUCCESS; +} + BFstatus bfPacketCaptureCallbackSetCHIPS(BFpacketcapture_callback obj, BFpacketcapture_chips_sequence_callback callback) { BF_ASSERT(obj, BF_STATUS_INVALID_HANDLE); @@ -184,19 +197,23 @@ BFstatus bfPacketCaptureCallbackSetDRX8(BFpacketcapture_callback obj, BFpacketcapture_status BFpacketcapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); + BF_PRINTD("impl, start clock"); uint8_t* buf_ptrs[2]; // Minor HACK to access the buffers in a 2-element queue buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; + BF_PRINTD("buff ptrs"); size_t* ngood_bytes_ptrs[2]; ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; + BF_PRINTD("ngoodbytes"); size_t* src_ngood_bytes_ptrs[2]; src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; + BF_PRINTD("srcngoodbytes"); int state = _capture->run(_seq, _nseq_per_buf, _bufs.size(), diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 10e3483a3..2953b8b23 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -342,7 +342,8 @@ class PacketCaptureThread : public BoundThread { size_t* src_ngood_bytes[], PDC* decode, PPC* process); - inline const char* get_name() { return _method->get_name(); } + inline const char* get_name() { + return _method->get_name(); } inline const size_t get_max_size() { return _method->get_max_size(); } inline const BFiomethod get_io_method() { return _method->get_io_method(); } inline const int get_core() { return _core; } @@ -391,7 +392,7 @@ class BFpacketcapture_callback_impl { } inline BFpacketcapture_simple_sequence_callback get_simple() { return _simple_callback; - + } inline void set_chips(BFpacketcapture_chips_sequence_callback callback) { _chips_callback = callback; } @@ -612,22 +613,12 @@ class BFpacketcapture_simple_impl : public BFpacketcapture_impl { this->on_sequence_changed(pkt, seq0, time_tag, hdr, hdr_size); } void on_sequence_active(const PacketDesc* pkt) { - if( pkt ) { - //cout << "Latest nchan, chan0 = " << pkt->nchan << ", " << pkt->chan0 << endl; - } - else { - //cout << "No latest packet" << endl; - } } inline bool has_sequence_changed(const PacketDesc* pkt) { - return (pkt->chan0 != _chan0) \ - || (pkt->nchan != _nchan); + return 1; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, @@ -648,9 +639,6 @@ class BFpacketcapture_simple_impl : public BFpacketcapture_impl { *hdr_size = 0; } - _chan_log.update() << "chan0 : " << _chan0 << "\n" - << "nchan : " << _nchan << "\n" - << "payload_size : " << _payload_size << "\n"; } public: inline BFpacketcapture_simple_impl(PacketCaptureThread* capture, @@ -1318,7 +1306,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nchan = 1; - max_payload_size = sizeof(simple_hdr_type) + (4*nchan); + max_payload_size = 8192; } } else if( std::string(format).substr(0, 5) == std::string("chips") ) { if( backend == BF_IO_DISK ) { @@ -1374,8 +1362,13 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, return BF_STATUS_UNSUPPORTED; } PacketCaptureThread* capture = new PacketCaptureThread(method, nsrc, core); + if (std::string(format).substr(0, 6) == std::string("simple") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_simple_impl(capture, ring, nsrc, src0, + buffer_ntime, slot_ntime, + sequence_callback), + *obj = 0); - if( std::string(format).substr(0, 5) == std::string("chips") ) { + } else if( std::string(format).substr(0, 5) == std::string("chips") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketcapture_chips_impl(capture, ring, nsrc, src0, buffer_ntime, slot_ntime, sequence_callback), From 5d0450178de39772c6195965475f985fa1f6e310 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 26 Jan 2024 11:03:07 -0700 Subject: [PATCH 328/424] simple packet working --- src/packet_capture.cpp | 2 +- src/packet_writer.hpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 92094342e..3e00f2053 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -28,7 +28,7 @@ #include "packet_capture.hpp" -#define BF_JAYCE_DEBUG 1 +#define BF_JAYCE_DEBUG 0 #if BF_JAYCE_DEBUG #define BF_PRINTD(stmt) \ diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index d3c0228fa..d41b6a354 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -451,7 +451,7 @@ class BFpacketwriter_simple_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_simple_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_I2), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_I16), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new SIMPLEHeaderFiller(); _type_log.update("type : %s\n", "simple"); @@ -570,8 +570,8 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, int nsamples = 0; if(std::string(format).substr(0, 8) == std::string("generic_") ) { nsamples = std::atoi((std::string(format).substr(8, std::string(format).length())).c_str()); - } else if( std::string(format).substr(0, 7) == std::string("simple_") ) { - nsamples = 4092; + } else if( std::string(format).substr(0, 6) == std::string("simple") ) { + nsamples = 4094; } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; @@ -613,6 +613,9 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, if( std::string(format).substr(0, 8) == std::string("generic_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_generic_impl(writer, nsamples), *obj = 0); + } else if( std::string(format).substr(0, 6) == std::string("simple") ) { + BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_simple_impl(writer, nsamples), + *obj = 0); } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { BF_TRY_RETURN_ELSE(*obj = new BFpacketwriter_chips_impl(writer, nsamples), *obj = 0); From d043ac5b95fb6a9f49d0bbf39f11942089a6dcdb Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 26 Jan 2024 11:25:35 -0700 Subject: [PATCH 329/424] re-enable optimization --- src/formats/simple.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 4060efb05..bd5ad891c 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -93,7 +93,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { //cout << pkt->src << ", " << pkt->nsrc << endl; //cout << pkt->nchan << endl; for( ; channchan; ++chan ) { -/*#if defined BF_AVX_ENABLED && BF_AVX_ENABLED +#if defined BF_AVX_ENABLED && BF_AVX_ENABLED _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), _mm256_loadu_si256(reinterpret_cast(&in[chan]))); #else @@ -104,7 +104,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { _mm_store_si128(reinterpret_cast<__m128i*>(ddst), _mm_loadu_si128(reinterpret_cast(dsrc))); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_loadu_si128(reinterpret_cast(dsrc+1)));*/ + _mm_loadu_si128(reinterpret_cast(dsrc+1))); //#else ::memcpy(&out[pkt->src + pkt->nsrc*chan], &in[chan], sizeof(otype)); From 978e4d2136a9709d8a61f267b32cd34d640ae95a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 26 Jan 2024 15:00:41 -0700 Subject: [PATCH 330/424] Missed a couple. --- src/formats/simple.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index bd5ad891c..23a0edfd6 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -105,11 +105,11 @@ class SIMPLEProcessor : virtual public PacketProcessor { _mm_loadu_si128(reinterpret_cast(dsrc))); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), _mm_loadu_si128(reinterpret_cast(dsrc+1))); -//#else +#else ::memcpy(&out[pkt->src + pkt->nsrc*chan], &in[chan], sizeof(otype)); -//#endif -//#endif +#endif +#endif } } From 066f35664a518b1a1bb9e3930fa4351e0e88c752 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 26 Jan 2024 16:36:39 -0700 Subject: [PATCH 331/424] Also update the packet size so we know what to expect in the future. --- src/packet_capture.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 2953b8b23..2624debf3 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -619,7 +619,8 @@ class BFpacketcapture_simple_impl : public BFpacketcapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - + _payload_size = pkt->payload_size; + if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, _chan0, From a1cf369770571c61268f56b7edc1184008ecd811 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 26 Jan 2024 16:37:25 -0700 Subject: [PATCH 332/424] There is so little to the header that we cannot tell if the observing setup has changed or not. --- src/packet_capture.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 2624debf3..b0811c2d8 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -615,7 +615,7 @@ class BFpacketcapture_simple_impl : public BFpacketcapture_impl { void on_sequence_active(const PacketDesc* pkt) { } inline bool has_sequence_changed(const PacketDesc* pkt) { - return 1; + return 0; } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); From c63f37ea1f3c0264cee7e41e807725864a385f07 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 8 Feb 2024 12:55:54 -0700 Subject: [PATCH 333/424] Fixed not copying all the data to ring buffer --- src/formats/simple.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 23a0edfd6..c46fb2f6d 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -93,7 +93,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { //cout << pkt->src << ", " << pkt->nsrc << endl; //cout << pkt->nchan << endl; for( ; channchan; ++chan ) { -#if defined BF_AVX_ENABLED && BF_AVX_ENABLED +/* #if defined BF_AVX_ENABLED && BF_AVX_ENABLED _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), _mm256_loadu_si256(reinterpret_cast(&in[chan]))); #else @@ -105,11 +105,11 @@ class SIMPLEProcessor : virtual public PacketProcessor { _mm_loadu_si128(reinterpret_cast(dsrc))); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), _mm_loadu_si128(reinterpret_cast(dsrc+1))); -#else +#else*/ ::memcpy(&out[pkt->src + pkt->nsrc*chan], - &in[chan], sizeof(otype)); -#endif -#endif + &in[chan], 256*sizeof(otype)); +// #endif +// #endif } } @@ -122,7 +122,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { otype* __restrict__ aligned_data = (otype*)data; for( int t=0; t(&aligned_data[src + nsrc*(c + nchan*t)]), _mm256_setzero_si256()); #else @@ -133,11 +133,11 @@ class SIMPLEProcessor : virtual public PacketProcessor { _mm_setzero_si128()); _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), _mm_setzero_si128()); -#else +#else*/ ::memset(&aligned_data[src + nsrc*(c + nchan*t)], 0, sizeof(otype)); -#endif -#endif +// #endif +// #endif } } } From e89a650974b3e49b8617367593998a99e83acd66 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 8 Feb 2024 13:34:31 -0700 Subject: [PATCH 334/424] simplify --- src/formats/simple.hpp | 52 ++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index c46fb2f6d..11e764091 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -90,24 +90,25 @@ class SIMPLEProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan = 0; + int nelem = 256; //cout << pkt->src << ", " << pkt->nsrc << endl; //cout << pkt->nchan << endl; - for( ; channchan; ++chan ) { + for( ; chan(&out[pkt->src + pkt->nsrc*chan]), _mm256_loadu_si256(reinterpret_cast(&in[chan]))); -#else -#if defined BF_SSE_ENABLED && BF_SSE_ENABLED - const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; - aligned128_type* ddst = (aligned128_type*) &out[pkt->src + pkt->nsrc*chan]; - - _mm_store_si128(reinterpret_cast<__m128i*>(ddst), - _mm_loadu_si128(reinterpret_cast(dsrc))); - _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_loadu_si128(reinterpret_cast(dsrc+1))); #else*/ - ::memcpy(&out[pkt->src + pkt->nsrc*chan], - &in[chan], 256*sizeof(otype)); +// #if defined BF_SSE_ENABLED && BF_SSE_ENABLED +// const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; +// aligned128_type* ddst = (aligned128_type*) &out[chan]; +// +// _mm_store_si128(reinterpret_cast<__m128i*>(ddst), +// _mm_loadu_si128(reinterpret_cast(dsrc))); // Problem HERE? +// _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), +// _mm_loadu_si128(reinterpret_cast(dsrc+1))); +// #else + ::memcpy(&out[chan], + &in[chan], sizeof(otype)); // #endif // #endif } @@ -116,28 +117,29 @@ class SIMPLEProcessor : virtual public PacketProcessor { inline void blank_out_source(uint8_t* data, int src, int nsrc, - int nchan, + int nchan, int nseq) { typedef aligned256_type otype; + int nelem = 256; otype* __restrict__ aligned_data = (otype*)data; for( int t=0; t(&aligned_data[src + nsrc*(c + nchan*t)]), + _mm256_store_si256(reinterpret_cast<__m256i*>(&aligned_data[src + nsrc*(c + nelem*t)]), _mm256_setzero_si256()); -#else -#if defined BF_SSE_ENABLED && BF_SSE_ENABLED - aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nchan*t)]; - - _mm_store_si128(reinterpret_cast<__m128i*>(ddst), - _mm_setzero_si128()); - _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_setzero_si128()); #else*/ - ::memset(&aligned_data[src + nsrc*(c + nchan*t)], +// #if defined BF_SSE_ENABLED && BF_SSE_ENABLED +// aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nelem*t)]; +// +// _mm_store_si128(reinterpret_cast<__m128i*>(ddst), +// _mm_setzero_si128()); +// _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), +// _mm_setzero_si128()); +// #else + ::memset(&aligned_data[src + nsrc*(c + nelem*t)], 0, sizeof(otype)); // #endif -// #endif +//#endif } } } From c7478b14b60333a9177933ee40ebc8da543d1e42 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 16 Feb 2024 14:11:20 -0700 Subject: [PATCH 335/424] Update simple.hpp Remove optimizations, they don't work anyway --- src/formats/simple.hpp | 38 +++----------------------------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 11e764091..b663da222 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -91,27 +91,9 @@ class SIMPLEProcessor : virtual public PacketProcessor { int chan = 0; int nelem = 256; - //cout << pkt->src << ", " << pkt->nsrc << endl; - //cout << pkt->nchan << endl; - for( ; chan(&out[pkt->src + pkt->nsrc*chan]), - _mm256_loadu_si256(reinterpret_cast(&in[chan]))); -#else*/ -// #if defined BF_SSE_ENABLED && BF_SSE_ENABLED -// const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; -// aligned128_type* ddst = (aligned128_type*) &out[chan]; -// -// _mm_store_si128(reinterpret_cast<__m128i*>(ddst), -// _mm_loadu_si128(reinterpret_cast(dsrc))); // Problem HERE? -// _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), -// _mm_loadu_si128(reinterpret_cast(dsrc+1))); -// #else - ::memcpy(&out[chan], - &in[chan], sizeof(otype)); -// #endif -// #endif - } + for( ; chan(&aligned_data[src + nsrc*(c + nelem*t)]), - _mm256_setzero_si256()); -#else*/ -// #if defined BF_SSE_ENABLED && BF_SSE_ENABLED -// aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nelem*t)]; -// -// _mm_store_si128(reinterpret_cast<__m128i*>(ddst), -// _mm_setzero_si128()); -// _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), -// _mm_setzero_si128()); -// #else ::memset(&aligned_data[src + nsrc*(c + nelem*t)], 0, sizeof(otype)); -// #endif -//#endif } } } From 77ee338a97393c4a6e8669661dc5fdff300f7b1c Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 14:47:43 -0700 Subject: [PATCH 336/424] Bad merge. --- configure | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/configure b/configure index 66d6c8164..fa9861d0b 100755 --- a/configure +++ b/configure @@ -21641,14 +21641,15 @@ cudaMalloc(0, 0); return 0; } _ACEOF -if ac_fn_cxx_try_compile "$LINENO" +if ac_fn_cxx_try_link "$LINENO" then : else $as_nop HAVE_CUDA=0 fi -rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext if test "$HAVE_CUDA" = "1"; then LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" @@ -21672,22 +21673,22 @@ _ACEOF if ac_fn_cxx_try_link "$LINENO" then : CUDA_VERSION=$( ${NVCC} --version | ${GREP} -Po -e "release.*," | cut -d, -f1 | cut -d\ -f2 ) - CUDA_MAJOR=$( echo "${CUDA_VERSION}" | cut -d. -f1 ) - if test "${CUDA_MAJOR}" -ge 10; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes - v$CUDA_VERSION" >&5 printf "%s\n" "yes - v$CUDA_VERSION" >&6; } - else - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - found v$CUDA_VERSION" >&5 -printf "%s\n" "no - found v$CUDA_VERSION" >&6; } - fi else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no - build failure" >&5 -printf "%s\n" "no - build failure" >&6; } - HAVE_CUDA=0 + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + HAVE_CUDA=0 fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext + else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + HAVE_CUDA=0 + + fi CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" @@ -27576,3 +27577,4 @@ printf "%s\n" "$as_me: options:$OPTIONS" >&6;} echo "" echo "Bifrost is now ready to be compiled. Please run 'make'" echo "" + From 10f64379297e68346b14ca31621dd1870c999570 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 14:52:42 -0700 Subject: [PATCH 337/424] Getting closer with this update. --- config/cuda.m4 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/cuda.m4 b/config/cuda.m4 index 0744efec6..71c3214e0 100644 --- a/config/cuda.m4 +++ b/config/cuda.m4 @@ -251,10 +251,10 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" + NVCCLIBS="-lcuda -lcudart" ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' AC_RUN_IFELSE([ AC_LANG_PROGRAM([[ @@ -292,7 +292,7 @@ AC_DEFUN([AX_CHECK_CUDA], CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" else AC_SUBST([GPU_SHAREDMEM], [$with_shared_mem]) fi From 03fa46aaf62320d7ae0bba8b6fc98edda9a6a1eb Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 14:53:02 -0700 Subject: [PATCH 338/424] Update configure. --- configure | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure b/configure index fa9861d0b..c7b07ae79 100755 --- a/configure +++ b/configure @@ -21930,10 +21930,10 @@ printf %s "checking for minimum shared memory per block... " >&6; } CXXFLAGS_save="$CXXFLAGS" LDFLAGS_save="$LDFLAGS" - LIBS_save="$LIBS" + NVCCLIBS_save="$NVCCLIBS" LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="-lcuda -lcudart" + NVCCLIBS="-lcuda -lcudart" ac_run='$NVCC -o conftest$ac_ext $LDFLAGS $LIBS conftest.$ac_ext>&5' if test "$cross_compiling" = yes then : @@ -21997,7 +21997,7 @@ fi CXXFLAGS="$CXXFLAGS_save" LDFLAGS="$LDFLAGS_save" - LIBS="$LIBS_save" + NVCCLIBS="$NVCCLIBS_save" else GPU_SHAREDMEM=$with_shared_mem From 08508b48c5f2331298e92716736d234f68799a7f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 15:25:48 -0700 Subject: [PATCH 339/424] Missed one. --- config/cuda.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/cuda.m4 b/config/cuda.m4 index 71c3214e0..055418ea1 100644 --- a/config/cuda.m4 +++ b/config/cuda.m4 @@ -47,7 +47,7 @@ AC_DEFUN([AX_CHECK_CUDA], ac_compile='$NVCC -c $NVCCFLAGS conftest.$ac_ext >&5' LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart" + NVCCLIBS="$LIBS -lcuda -lcudart" ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS conftest.$ac_ext >&5' AC_LINK_IFELSE([ From 38264a894b81e56d7e6c7320b148f0d60fd0f91b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 15:26:10 -0700 Subject: [PATCH 340/424] Rebuild. --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index c7b07ae79..2fc51bfdd 100755 --- a/configure +++ b/configure @@ -21624,7 +21624,7 @@ printf %s "checking for a working CUDA 10+ installation... " >&6; } ac_compile='$NVCC -c $NVCCFLAGS conftest.$ac_ext >&5' LDFLAGS="-L$CUDA_HOME/lib64 -L$CUDA_HOME/lib" - LIBS="$LIBS -lcuda -lcudart" + NVCCLIBS="$LIBS -lcuda -lcudart" ac_link='$NVCC -o conftest$ac_exeext $NVCCFLAGS $LDFLAGS $LIBS conftest.$ac_ext >&5' cat confdefs.h - <<_ACEOF >conftest.$ac_ext From b6e6799f1910743ea0f05575d348c8d6fc491d87 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 15:56:07 -0700 Subject: [PATCH 341/424] I think this is the correct fix. --- python/typehinting.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/typehinting.py b/python/typehinting.py index ae06c0b05..b283ae95c 100644 --- a/python/typehinting.py +++ b/python/typehinting.py @@ -6,7 +6,8 @@ def build_typehinting(filename): 'space': {}, 'dtype': {}, 'capture': {}, - 'transmit': {}, + 'io': {}, + 'whence': {}, 'reduce': {}} with open(filename, 'r') as fh: From c9275ac759ab100179780c94bc0d2880e6b693f5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 16:00:36 -0700 Subject: [PATCH 342/424] Lower cased names for the 'io' enum as well. --- python/typehinting.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/typehinting.py b/python/typehinting.py index b283ae95c..915515732 100644 --- a/python/typehinting.py +++ b/python/typehinting.py @@ -24,6 +24,9 @@ def build_typehinting(filename): if tag == 'space': name = name.replace('BF_SPACE_', '') enums[tag][name.lower()] = value + elif tag == 'io': + name = name.replace('BF_IO_', '') + enums[tag][name.lower()] = value elif tag == 'reduce': name = name.replace('BF_REDUCE_', '') name = name.replace('POWER_', 'pwr') From d1bb73a1a6bdea6268eb336133aff08f13dd3357 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 16:21:50 -0700 Subject: [PATCH 343/424] Type hints. --- python/bifrost/packet_capture.py | 58 ++++++++++++++++++++------------ python/bifrost/packet_writer.py | 35 ++++++++++++------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index 760debd98..e3bc8dcf2 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2024, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -27,46 +27,54 @@ # **TODO: Write tests for this class -from bifrost.libbifrost import _bf, _check, _get, BifrostObject +from bifrost.libbifrost import _bf, _th, _check, _get, BifrostObject +from bifrost.udp_socket import UDPSocket +from bifrost.ring import Ring +from bifrost.ring2 import Ring as Ring2 import ctypes from functools import reduce +from io import IOBase +from typing import Optional, Union + +from bifrost import telemetry +telemetry.track_module() class PacketCaptureCallback(BifrostObject): _ref_cache = {} def __init__(self): BifrostObject.__init__( self, _bf.bfPacketCaptureCallbackCreate, _bf.bfPacketCaptureCallbackDestroy) - def set_chips(self, fnc): + def set_chips(self, fnc: _bf.BFpacketcapture_chips_sequence_callback): self._ref_cache['chips'] = _bf.BFpacketcapture_chips_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCHIPS( self.obj, self._ref_cache['chips'])) - def set_ibeam(self, fnc): + def set_ibeam(self, fnc: _bf.BFpacketcapture_ibeam_sequence_callback): self._ref_cache['ibeam'] = _bf.BFpacketcapture_ibeam_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetIBeam( self.obj, self._ref_cache['ibeam'])) - def set_pbeam(self, fnc): + def set_pbeam(self, fnc: _bf.BFpacketcapture_pbeam_sequence_callback): self._ref_cache['pbeam'] = _bf.BFpacketcapture_pbeam_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetPBeam( self.obj, self._ref_cache['pbeam'])) - def set_cor(self, fnc): + def set_cor(self, fnc: _bf.BFpacketcapture_cor_sequence_callback): self._ref_cache['cor'] = _bf.BFpacketcapture_cor_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetCOR( self.obj, self._ref_cache['cor'])) - def set_vdif(self, fnc): + def set_vdif(self, fnc: _bf.BFpacketcapture_vdif_sequence_callback): self._ref_cache['vdif'] = _bf.BFpacketcapture_vdif_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetVDIF( self.obj, self._ref_cache['vdif'])) - def set_tbn(self, fnc): + def set_tbn(self, fnc: _bf.BFpacketcapture_tbn_sequence_callback): self._ref_cache['tbn'] = _bf.BFpacketcapture_tbn_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetTBN( self.obj, self._ref_cache['tbn'])) - def set_drx(self, fnc): + def set_drx(self, fnc: _bf.BFpacketcapture_drx_sequence_callback): self._ref_cache['drx'] = _bf.BFpacketcapture_drx_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetDRX( self.obj, self._ref_cache['drx'])) - def set_drx8(self, fnc): + def set_drx8(self, fnc: _bf.BFpacketcapture_drx8_sequence_callback): self._ref_cache['drx8'] = _bf.BFpacketcapture_drx8_sequence_callback(fnc) _check(_bf.bfPacketCaptureCallbackSetDRX8( self.obj, self._ref_cache['drx8'])) @@ -83,7 +91,7 @@ def __enter__(self): return self def __exit__(self, type, value, tb): self.end() - def recv(self): + def recv(self) -> _th.BFcapture_enum: status = _bf.BFpacketcapture_status() _check(_bf.bfPacketCaptureRecv(self.obj, status)) return status.value @@ -93,8 +101,10 @@ def end(self): _check(_bf.bfPacketCaptureEnd(self.obj)) class UDPCapture(_CaptureBase): - def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): + def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], + nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, + slot_ntime: int, sequence_callback: PacketCaptureCallback, + core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -110,8 +120,10 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, sequence_callback.obj, core) class UDPSniffer(_CaptureBase): - def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): + def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], + nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, + slot_ntime: int, sequence_callback: PacketCaptureCallback, + core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -127,8 +139,10 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, sequence_callback.obj, core) class UDPVerbsCapture(_CaptureBase): - def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, - buffer_ntime, slot_ntime, sequence_callback, core=None): + def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], + nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, + slot_ntime: int, sequence_callback: PacketCaptureCallback, + core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -143,8 +157,10 @@ def __init__(self, fmt, sock, ring, nsrc, src0, max_payload_size, sequence_callback.obj, core) class DiskReader(_CaptureBase): - def __init__(self, fmt, fh, ring, nsrc, src0, - buffer_nframe, slot_nframe, sequence_callback, core=None): + def __init__(self, fmt: str, fh: IOBase, ring: Union[Ring,Ring2], + nsrc: int, src0: int, buffer_nframe: int, slot_nframe: int, + sequence_callback: PacketCaptureCallback, + core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -160,11 +176,11 @@ def __init__(self, fmt, fh, ring, nsrc, src0, sequence_callback.obj, core) # Make sure we start in the same place in the file self.seek(fh.tell(), _bf.BF_WHENCE_SET) - def seek(self, offset, whence=_bf.BF_WHENCE_CUR): + def seek(self, offset: int, whence: _th.BFwhence_enum=_bf.BF_WHENCE_CUR): position = ctypes.c_ulong(0) _check(_bf.bfPacketCaptureSeek(self.obj, offset, whence, position)) return position.value - def tell(self): + def tell(self) -> int: position = ctypes.c_ulong(0) _check(_bf.bfPacketCaptureTell(self.obj, position)) return position.value diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 2ae2f7d95..77801b7d3 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -1,5 +1,5 @@ -# Copyright (c) 2019-2023, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2024, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -29,22 +29,31 @@ from bifrost.libbifrost import _bf, _check, _get, BifrostObject from bifrost.ndarray import asarray +from bifrost.ndarray import ndarray +from bifrost.udp_socket import UDPSocket + +from io import IOBase + +from typing import Optional + +from bifrost import telemetry +telemetry.track_module() class HeaderInfo(BifrostObject): def __init__(self): BifrostObject.__init__( self, _bf.bfHeaderInfoCreate, _bf.bfHeaderInfoDestroy) - def set_nsrc(self, nsrc): + def set_nsrc(self, nsrc: int): _check(_bf.bfHeaderInfoSetNSrc(self.obj, nsrc)) - def set_nchan(self, nchan): + def set_nchan(self, nchan: int): _check(_bf.bfHeaderInfoSetNChan(self.obj, nchan)) - def set_chan0(self, chan0): + def set_chan0(self, chan0: int): _check(_bf.bfHeaderInfoSetChan0(self.obj, chan0)) - def set_tuning(self, tuning): + def set_tuning(self, tuning: int): _check(_bf.bfHeaderInfoSetTuning(self.obj, tuning)) - def set_gain(self, gain): + def set_gain(self, gain: int): _check(_bf.bfHeaderInfoSetGain(self.obj, gain)) - def set_decimation(self, decimation): + def set_decimation(self, decimation: int): _check(_bf.bfHeaderInfoSetDecimation(self.obj, decimation)) class _WriterBase(BifrostObject): @@ -52,11 +61,13 @@ def __enter__(self): return self def __exit__(self, type, value, tb): pass - def set_rate_limit(self, rate_limit_pps): + def set_rate_limit(self, rate_limit_pps: int): _check(_bf.bfPacketWriterSetRateLimit(self.obj, rate_limit_pps)) def reset_counter(self): _check(_bf.bfPacketWriterResetCounter(self.obj)) - def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): + def send(self, headerinfo: HeaderInfo, + seq: int, seq_increment: int, src: int, src_increment: int, + idata: ndarray): _check(_bf.bfPacketWriterSend(self.obj, headerinfo.obj, seq, @@ -66,7 +77,7 @@ def send(self, headerinfo, seq, seq_increment, src, src_increment, idata): asarray(idata).as_BFarray())) class UDPTransmit(_WriterBase): - def __init__(self, fmt, sock, core=None): + def __init__(self, fmt: str, sock: UDPSocket, core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -80,7 +91,7 @@ def __init__(self, fmt, sock, core=None): class UDPVerbsTransmit(_WriterBase): - def __init__(self, fmt, sock, core=None): + def __init__(self, fmt: str, sock: UDPSocket, core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: @@ -94,7 +105,7 @@ def __init__(self, fmt, sock, core=None): class DiskWriter(_WriterBase): - def __init__(self, fmt, fh, core=None): + def __init__(self, fmt: str, fh: IOBase, core: Optional[int]=None): try: fmt = fmt.encode() except AttributeError: From c383f320fc785681d25e6a71f7a31a23df6e1c71 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 16:32:59 -0700 Subject: [PATCH 344/424] Type hints and cleanups. --- python/bifrost/rdma.py | 47 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/python/bifrost/rdma.py b/python/bifrost/rdma.py index 44e47aafc..49108539e 100644 --- a/python/bifrost/rdma.py +++ b/python/bifrost/rdma.py @@ -1,6 +1,6 @@ -# Copyright (c) 2022, The Bifrost Authors. All rights reserved. -# Copyright (c) 2022, The University of New Mexico. All rights reserved. +# Copyright (c) 2022-2024, The Bifrost Authors. All rights reserved. +# Copyright (c) 2022-2024, The University of New Mexico. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -26,40 +26,41 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# Python2 compatibility -from __future__ import absolute_import - -from bifrost.libbifrost import _bf, _check, _get, BifrostObject +from bifrost.libbifrost import _bf, _th, _check, _get, BifrostObject from bifrost.ndarray import ndarray, asarray from bifrost.proclog import ProcLog import bifrost.affinity as cpu_affinity +from bifrost.udp_socket import UDPSocket +from bifrost.ring import Ring +from bifrost.ring2 import Ring as Ring2 import time import ctypes +from typing import Optional, Tuple, Union + +from bifrost import telemetry +telemetry.track_module() + class RdmaSender(BifrostObject): - def __init__(self, sock, message_size): + def __init__(self, sock: UDPSocket, message_size: int): BifrostObject.__init__( self, _bf.bfRdmaCreate, _bf.bfRdmaDestroy, sock.fileno(), message_size, 1) - def send_header(self, time_tag, header, offset_from_head): - try: - header = header.encode() - except AttributeError: - # Python2 catch - pass + def send_header(self, time_tag: int, header: str, offset_from_head: int): + header = header.encode() header_buf = ctypes.create_string_buffer(header) _check(_bf.bfRdmaSendHeader(self.obj, time_tag, len(header), ctypes.cast(header_buf, ctypes.c_void_p), offset_from_head)) - def send_span(self, span_data): + def send_span(self, span_data: ndarray): _check(_bf.bfRdmaSendSpan(self.obj, asarray(span_data).as_BFarray())) class RdmaReceiver(BifrostObject): - def __init__(self, sock, message_size, buffer_factor=5): + def __init__(self, sock: UDPSocket, message_size: int, buffer_factor: int=5): BifrostObject.__init__( self, _bf.bfRdmaCreate, _bf.bfRdmaDestroy, sock.fileno(), message_size, 0) @@ -75,7 +76,7 @@ def __init__(self, sock, message_size, buffer_factor=5): contents_buf = ctypes.create_string_buffer(self.message_size) self.contents_bufs.append(contents_buf) self.index = 0 - def receive(self): + def receive(self) -> Union[Tuple[int,int,str],ndarray]: contents_buf = self.contents_bufs[self.index] self.index += 1 if self.index == self.buffer_factor: @@ -96,7 +97,8 @@ def receive(self): return span_data class RingSender(object): - def __init__(self, iring, sock, gulp_size, guarantee=True, core=-1): + def __init__(self, iring: Union[Ring,Ring2], sock: UDPSocket, gulp_size: int, + guarantee: bool=True, core: Optional[int]=None): self.iring = iring self.sock = sock self.gulp_size = gulp_size @@ -111,6 +113,11 @@ def __init__(self, iring, sock, gulp_size, guarantee=True, core=-1): self.in_proclog.update( {'nring':1, 'ring0':self.iring.name}) def main(self): + if self.core is not None: + cpu_affinity.set_core(self.core) + self.bind_proclog.update({'ncore': 1, + 'core0': cpu_affinity.get_core(),}) + sender = RdmaSender(self.sock, self.gulp_size) for iseq in self.iring.read(guarantee=self.guarantee): @@ -138,7 +145,8 @@ def main(self): class RingReceiver(object): - def __init__(self, oring, sock, gulp_size, guarantee=True, core=-1): + def __init__(self, oring; Union[Ring,Ring2], sock: UDPSocket, gulp_size: int, + guarantee: bool=True, core: Optional[int]=None): self.oring = oring self.sock = sock self.gulp_size = gulp_size @@ -153,7 +161,8 @@ def __init__(self, oring, sock, gulp_size, guarantee=True, core=-1): self.out_proclog.update( {'nring':1, 'ring0':self.oring.name}) def main(self): - cpu_affinity.set_core(self.core) + if self.core is not None: + cpu_affinity.set_core(self.core) self.bind_proclog.update({'ncore': 1, 'core0': cpu_affinity.get_core(),}) From 7c07ef0f89bd1b81a688517c7ec963f32a64e9ec Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 16:40:27 -0700 Subject: [PATCH 345/424] Drop some more Py2 stuff. --- python/bifrost/packet_capture.py | 28 ++++------------------------ python/bifrost/packet_writer.py | 21 +++------------------ 2 files changed, 7 insertions(+), 42 deletions(-) diff --git a/python/bifrost/packet_capture.py b/python/bifrost/packet_capture.py index e3bc8dcf2..6d0ce6425 100644 --- a/python/bifrost/packet_capture.py +++ b/python/bifrost/packet_capture.py @@ -105,17 +105,12 @@ def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, slot_ntime: int, sequence_callback: PacketCaptureCallback, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( self, _bf.bfUdpCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, + fmt.encode(), sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) @@ -124,17 +119,12 @@ def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, slot_ntime: int, sequence_callback: PacketCaptureCallback, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( self, _bf.bfUdpSnifferCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, + fmt.encode(), sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) @@ -143,16 +133,11 @@ def __init__(self, fmt: str, sock: UDPSocket, ring: Union[Ring,Ring2], nsrc: int, src0: int, max_payload_size: int, buffer_ntime: int, slot_ntime: int, sequence_callback: PacketCaptureCallback, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass if core is None: core = -1 BifrostObject.__init__( self, _bf.bfUdpVerbsCaptureCreate, _bf.bfPacketCaptureDestroy, - fmt, sock.fileno(), ring.obj, nsrc, src0, + fmt.encode(), sock.fileno(), ring.obj, nsrc, src0, max_payload_size, buffer_ntime, slot_ntime, sequence_callback.obj, core) @@ -161,17 +146,12 @@ def __init__(self, fmt: str, fh: IOBase, ring: Union[Ring,Ring2], nsrc: int, src0: int, buffer_nframe: int, slot_nframe: int, sequence_callback: PacketCaptureCallback, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass nsrc = self._flatten_value(nsrc) if core is None: core = -1 BifrostObject.__init__( self, _bf.bfDiskReaderCreate, _bf.bfPacketCaptureDestroy, - fmt, fh.fileno(), ring.obj, nsrc, src0, + fmt.encode(), fh.fileno(), ring.obj, nsrc, src0, buffer_nframe, slot_nframe, sequence_callback.obj, core) # Make sure we start in the same place in the file diff --git a/python/bifrost/packet_writer.py b/python/bifrost/packet_writer.py index 77801b7d3..0fbeae05b 100644 --- a/python/bifrost/packet_writer.py +++ b/python/bifrost/packet_writer.py @@ -78,41 +78,26 @@ def send(self, headerinfo: HeaderInfo, class UDPTransmit(_WriterBase): def __init__(self, fmt: str, sock: UDPSocket, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass if core is None: core = -1 BifrostObject.__init__( self, _bf.bfUdpTransmitCreate, _bf.bfPacketWriterDestroy, - fmt, sock.fileno(), core) + fmt.encode(), sock.fileno(), core) class UDPVerbsTransmit(_WriterBase): def __init__(self, fmt: str, sock: UDPSocket, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass if core is None: core = -1 BifrostObject.__init__( self, _bf.bfUdpVerbsTransmitCreate, _bf.bfPacketWriterDestroy, - fmt, sock.fileno(), core) + fmt.encode(), sock.fileno(), core) class DiskWriter(_WriterBase): def __init__(self, fmt: str, fh: IOBase, core: Optional[int]=None): - try: - fmt = fmt.encode() - except AttributeError: - # Python2 catch - pass if core is None: core = -1 BifrostObject.__init__( self, _bf.bfDiskWriterCreate, _bf.bfPacketWriterDestroy, - fmt, fh.fileno(), core) + fmt.encode(), fh.fileno(), core) From a9640e19de54d81cba0c0f889d300b22b7469cea Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 16:54:02 -0700 Subject: [PATCH 346/424] Typo. --- python/bifrost/rdma.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/bifrost/rdma.py b/python/bifrost/rdma.py index 49108539e..aabc99274 100644 --- a/python/bifrost/rdma.py +++ b/python/bifrost/rdma.py @@ -145,7 +145,7 @@ def main(self): class RingReceiver(object): - def __init__(self, oring; Union[Ring,Ring2], sock: UDPSocket, gulp_size: int, + def __init__(self, oring: Union[Ring,Ring2], sock: UDPSocket, gulp_size: int, guarantee: bool=True, core: Optional[int]=None): self.oring = oring self.sock = sock From 67f9b70969114cc0de5f310255131978866fb75a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 17:02:03 -0700 Subject: [PATCH 347/424] Updates to also test on Py3.12 and clear up some Node.js 16 warnings. --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 82c0cb501..c8b2b5eed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: "Build and Test" "on": [push, pull_request] jobs: pre_build: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: @@ -20,7 +20,7 @@ jobs: strategy: matrix: os: [self-hosted, ubuntu-latest, macos-latest] - python-version: ['3.8', '3.10'] + python-version: ['3.8', '3.10', '3.12'] include: - os: ubuntu-20.04 python-version: '3.6' @@ -53,7 +53,7 @@ jobs: gnu-sed \ hwloc \ pkg-config - - uses: actions/setup-python@v4.3.0 + - uses: actions/setup-python@v5.0.0 with: python-version: ${{ matrix.python-version }} - name: "Software Install - Python" From 82939d3bcddd9b5b2e081b26201e463aabe5cf12 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 19:12:44 -0700 Subject: [PATCH 348/424] No imp module in Py3.12. --- test/test_scripts.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_scripts.py b/test/test_scripts.py index 03a061932..2240d3518 100644 --- a/test/test_scripts.py +++ b/test/test_scripts.py @@ -29,7 +29,6 @@ import unittest import os import re -import imp import sys import glob @@ -41,8 +40,6 @@ TEST_DIR = os.path.dirname(__file__) TOOLS_DIR = os.path.join(TEST_DIR, '..', 'tools') TESTBENCH_DIR = os.path.join(TEST_DIR, '..', 'testbench') -modInfoBuild = imp.find_module('bifrost', [os.path.join(TEST_DIR, '..', 'python')]) -BIFROST_DIR = os.path.abspath(modInfoBuild[1]) run_scripts_tests = False try: From 012aa2fbebf1b31ee1f0dbe8b5c447e6283c0210 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 20:55:15 -0700 Subject: [PATCH 349/424] Drop the GUPPI tests in testbench. --- .github/workflows/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c8b2b5eed..00b8923ee 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -112,8 +112,6 @@ jobs: coverage run --source=bifrost.ring,bifrost,bifrost.pipeline test_fft.py coverage run --source=bifrost.ring,bifrost,bifrost.pipeline your_first_block.py python download_breakthrough_listen_data.py -y - coverage run --source=bifrost.ring,bifrost,bifrost.pipeline test_guppi.py - coverage run --source=bifrost.ring,bifrost,bifrost.pipeline test_guppi_reader.py coverage run --source=bifrost.ring,bifrost,bifrost.pipeline test_fdmt.py ./testdata/pulsars/blc0_guppi_57407_61054_PSR_J1840%2B5640_0004.fil coverage xml - name: "Upload Coverage" From 53f0f2d4baf1bc5cd09412b00b8999ed59500118 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 21:05:31 -0700 Subject: [PATCH 350/424] RegEx fix. --- test/test_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_scripts.py b/test/test_scripts.py index 2240d3518..f679747e0 100644 --- a/test/test_scripts.py +++ b/test/test_scripts.py @@ -50,7 +50,7 @@ pass run_scripts_tests &= (sys.version_info[0] >= 3) -_LINT_RE = re.compile('(?P.*?)\:(?P\d+)\: \[(?P.*?)\] (?P.*)') +_LINT_RE = re.compile('(?P.*?)\:(?P[0-9]+)\: \[(?P.*?)\] (?P.*)') @unittest.skipUnless(run_scripts_tests, "requires the 'pylint' module") class ScriptTest(unittest.TestCase): From 962339f8c0359dd650aef90da7287328071a3ad4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 21:15:42 -0700 Subject: [PATCH 351/424] RegEx fix. --- tools/like_pmap.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/like_pmap.py b/tools/like_pmap.py index f5a2e2ee4..31b6a18f6 100755 --- a/tools/like_pmap.py +++ b/tools/like_pmap.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 -# Copyright (c) 2017-2023, The Bifrost Authors. All rights reserved. -# Copyright (c) 2017-2023, The University of New Mexico. All rights reserved. +# Copyright (c) 2017-2024, The Bifrost Authors. All rights reserved. +# Copyright (c) 2017-2024, The University of New Mexico. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -92,7 +92,7 @@ def main(args): raise RuntimeError("Cannot find NUMA memory info for PID: %i" % args.pid) # Parse out the anonymous entries in this file - _numaRE = re.compile('(?P[0-9a-f]+).*[(anon)|(mapped)]=(?P\d+).*(swapcache=(?P\d+))?.*N(?P\d+)=(?P\d+)') + _numaRE = re.compile('(?P[0-9a-f]+).*[(anon)|(mapped)]=(?P[0-9]+).*(swapcache=(?P[0-9]+))?.*N(?P[0-9]+)=(?P[0-9]+)') areas = {} files = {} for line in numaInfo.split('\n'): From 0c8f19be5df61810806e53aaff7acdfc64ad4f76 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 19 Feb 2024 23:33:53 -0700 Subject: [PATCH 352/424] Another regex fix. --- test/test_scripts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_scripts.py b/test/test_scripts.py index f679747e0..baef30311 100644 --- a/test/test_scripts.py +++ b/test/test_scripts.py @@ -50,7 +50,7 @@ pass run_scripts_tests &= (sys.version_info[0] >= 3) -_LINT_RE = re.compile('(?P.*?)\:(?P[0-9]+)\: \[(?P.*?)\] (?P.*)') +_LINT_RE = re.compile('(?P.*?):(?P[0-9]+): \[(?P.*?)\] (?P.*)') @unittest.skipUnless(run_scripts_tests, "requires the 'pylint' module") class ScriptTest(unittest.TestCase): From 567297b05ec6ab2fcaa787c5f573aa47194dafd3 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 22 Feb 2024 12:53:54 -0700 Subject: [PATCH 353/424] not working yet --- test/test_disk_io.py | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index f58fe61dc..7dda130de 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -35,9 +35,55 @@ from bifrost.packet_capture import PacketCaptureCallback, DiskReader from bifrost.quantize import quantize from bifrost.pipeline import SourceBlock, SinkBlock +import datetime import numpy as np +start_pipeline = datetime.datetime.now() +class SIMPLEReader(object): + def __init__(self, sock, ring): + self.sock = sock + self.ring = ring + self.nsrc = 1 + def seq_callback(self, seq0, chan0, nchan, nsrc, + time_tag_ptr, hdr_ptr, hdr_size_ptr): + FS = 196.0e6 + CHAN_BW = 1e3 + # timestamp0 = (self.utc_start - ADP_EPOCH).total_seconds() + # time_tag0 = timestamp0 * int(FS) + time_tag = int((datetime.datetime.now() - start_pipeline).total_seconds()*1e6) + time_tag_ptr[0] = time_tag + cfreq = 55e6 + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'nchan': nchan, + 'cfreq': cfreq, + 'bw': CHAN_BW, + 'nstand': 2, + #'stand0': src0*16, # TODO: Pass src0 to the callback too(?) + 'npol': 2, + 'complex': False, + 'nbit': 2} + hdr_str = json.dumps(hdr).encode() + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + self.header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(self.header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_simple(self.seq_callback) + with DiskReader("simple" , self.sock, self.ring, self.nsrc, 0, 128, 128, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + class TBNReader(object): def __init__(self, sock, ring): self.sock = sock @@ -201,6 +247,68 @@ def _open(self, filename, mode): if filename not in self._cache: self._cache.append(filename) return fh + + def _get_simple_data(self): + desc = HeaderInfo() + data_q = bf.ndarray(np.ones((512,1,4094)), dtype='i16') + return desc, data_q + + def test_write_simple(self): + fh = self._open('test_simple.dat','wb') + oop = DiskWriter('simple', fh) + desc,data = self._get_simple_data() + oop.send(desc,0,512, 0, 1, data) + fh.close() + expectedsize = 512*8192 + self.assertEqual(os.path.getsize('test_simple.dat'), \ + expectedsize) + + def test_read_simple(self): + # Write + fh = self._open('test_simple.dat', 'wb') + oop = DiskWriter('simple', fh) + + # Get TBN data + desc, data = self._get_simple_data() + + # Go! + oop.send(desc,0,512, 0, 1, data) + fh.close() + + # Read + fh = self._open('test_simple.dat', 'rb') + ring = Ring(name="capture_simple") + iop = SIMPLEReader(fh, ring) + ## Data accumulation + final = [] + expectedsize = 8192*512 + aop = AccumulateOp(ring, final, expectedsize,dtype=np.short) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get simple data + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + for f in final: + print(f) + final = np.array(final, dtype=np.short) + final = bf.ndarray(shape=final.shape, dtype='i16', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) + + # Clean up + del oop + fh.close() + def _get_tbn_data(self): # Setup the packet HeaderInfo From 9c4306f2040210460e10b0ae9e9b216d30b2fb73 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 23 Feb 2024 14:29:11 -0700 Subject: [PATCH 354/424] working disk io test for simple --- src/formats/simple.hpp | 2 -- test/test_disk_io.py | 41 +++++++++++++++++++---------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index b663da222..72058d8fb 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -84,8 +84,6 @@ class SIMPLEProcessor : virtual public PacketProcessor { obuf_offset *= BF_UNPACK_FACTOR; - // Note: Using these SSE types allows the compiler to use SSE instructions - // However, they require aligned memory (otherwise segfault) itype const* __restrict__ in = (itype const*)pkt->payload_ptr; otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 7dda130de..6615d3c5f 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -76,7 +76,7 @@ def seq_callback(self, seq0, chan0, nchan, nsrc, def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_simple(self.seq_callback) - with DiskReader("simple" , self.sock, self.ring, self.nsrc, 0, 128, 128, + with DiskReader("simple" , self.sock, self.ring, self.nsrc, 0, 512, 512, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -89,8 +89,6 @@ def __init__(self, sock, ring): self.sock = sock self.ring = ring def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag hdr = {'time_tag': time_tag, 'seq0': seq0, 'chan0': chan0, @@ -100,7 +98,6 @@ def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): 'npol': 2, 'complex': True, 'nbit': 8} - #print "******** CFREQ:", hdr['cfreq'] try: hdr_str = json.dumps(hdr).encode() except AttributeError: @@ -131,8 +128,6 @@ def __init__(self, sock, ring, nsrc=4): self.ring = ring self.nsrc = nsrc def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag hdr = {'time_tag': time_tag, 'seq0': seq0, 'chan0': chan0, @@ -144,7 +139,6 @@ def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ 'npol': 2, 'complex': True, 'nbit': 4} - #print "******** CFREQ:", hdr['cfreq'] try: hdr_str = json.dumps(hdr).encode() except AttributeError: @@ -176,8 +170,6 @@ def __init__(self, sock, ring, nchan, nsrc=1): self.nchan = nchan self.nsrc = nsrc def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag hdr = {'time_tag': time_tag, 'seq0': seq0, 'chan0': chan0, @@ -188,7 +180,6 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ 'npol': 4, 'complex': False, 'nbit': 32} - #print("******** HDR:", hdr) try: hdr_str = json.dumps(hdr).encode() except AttributeError: @@ -228,7 +219,7 @@ def main(self): while not self.ring.writing_ended(): for ispan in iseq_spans: idata = ispan.data_view(self.dtype) - self.output.append(idata) + self.output.append(idata.copy()) class DiskIOTest(unittest.TestCase): @@ -250,14 +241,15 @@ def _open(self, filename, mode): def _get_simple_data(self): desc = HeaderInfo() - data_q = bf.ndarray(np.ones((512,1,4094)), dtype='i16') + testdata = self.s0[:2096128].real.astype(np.short) + data_q = bf.ndarray(testdata.reshape(512,1,4094), dtype='i16') return desc, data_q def test_write_simple(self): fh = self._open('test_simple.dat','wb') oop = DiskWriter('simple', fh) desc,data = self._get_simple_data() - oop.send(desc,0,512, 0, 1, data) + oop.send(desc,0,1, 0, 1, data) fh.close() expectedsize = 512*8192 self.assertEqual(os.path.getsize('test_simple.dat'), \ @@ -272,11 +264,13 @@ def test_read_simple(self): desc, data = self._get_simple_data() # Go! - oop.send(desc,0,512, 0, 1, data) + oop.send(desc,0,1, 0, 1, data) fh.close() # Read fh = self._open('test_simple.dat', 'rb') + from shutil import copyfile + copyfile("test_simple.dat","check_simple.dat") ring = Ring(name="capture_simple") iop = SIMPLEReader(fh, ring) ## Data accumulation @@ -296,15 +290,18 @@ def test_read_simple(self): # Compare ## Reorder to match what we sent out - for f in final: - print(f) final = np.array(final, dtype=np.short) - final = bf.ndarray(shape=final.shape, dtype='i16', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) - + + finalcopy = final.copy() + # The following statement starts with 32 bytes of garbage + finalcopy = bf.ndarray(shape=finalcopy.shape, dtype='i16', buffer=finalcopy.ctypes.data) + + # This statuement should be equivalent, but instead does not contain garbage + final = bf.ndarray(final, dtype='i16' ) + final = final.reshape(data.shape) + + np.testing.assert_equal(final,data) + # Clean up del oop fh.close() From 6570bab281de9c0b7fd7511514598d29dd26c55d Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Fri, 23 Feb 2024 14:57:25 -0700 Subject: [PATCH 355/424] working test_udp --- test/test_disk_io.py | 9 +--- test/test_udp_io.py | 114 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+), 8 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 6615d3c5f..fd1a803ec 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -269,13 +269,11 @@ def test_read_simple(self): # Read fh = self._open('test_simple.dat', 'rb') - from shutil import copyfile - copyfile("test_simple.dat","check_simple.dat") ring = Ring(name="capture_simple") iop = SIMPLEReader(fh, ring) ## Data accumulation final = [] - expectedsize = 8192*512 + expectedsize = 4096*512 aop = AccumulateOp(ring, final, expectedsize,dtype=np.short) # Start the reader and accumlator threads @@ -292,11 +290,6 @@ def test_read_simple(self): ## Reorder to match what we sent out final = np.array(final, dtype=np.short) - finalcopy = final.copy() - # The following statement starts with 32 bytes of garbage - finalcopy = bf.ndarray(shape=finalcopy.shape, dtype='i16', buffer=finalcopy.ctypes.data) - - # This statuement should be equivalent, but instead does not contain garbage final = bf.ndarray(final, dtype='i16' ) final = final.reshape(data.shape) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index b38e2038d..fe2d347d9 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -31,6 +31,7 @@ import ctypes import threading import bifrost as bf +import datetime from bifrost.ring import Ring from bifrost.address import Address from bifrost.udp_socket import UDPSocket @@ -39,7 +40,52 @@ from bifrost.quantize import quantize import numpy as np +start_pipeline = datetime.datetime.now() + +class SIMPLEReader(object): + def __init__(self, sock, ring): + self.sock = sock + self.ring = ring + self.nsrc = 1 + def seq_callback(self, seq0, chan0, nchan, nsrc, + time_tag_ptr, hdr_ptr, hdr_size_ptr): + FS = 196.0e6 + CHAN_BW = 1e3 + # timestamp0 = (self.utc_start - ADP_EPOCH).total_seconds() + # time_tag0 = timestamp0 * int(FS) + time_tag = int((datetime.datetime.now() - start_pipeline).total_seconds()*1e6) + time_tag_ptr[0] = time_tag + cfreq = 55e6 + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'nchan': nchan, + 'cfreq': cfreq, + 'bw': CHAN_BW, + 'nstand': 2, + #'stand0': src0*16, # TODO: Pass src0 to the callback too(?) + 'npol': 2, + 'complex': False, + 'nbit': 2} + hdr_str = json.dumps(hdr).encode() + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + self.header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(self.header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_simple(self.seq_callback) + with UDPCapture("simple" , self.sock, self.ring, self.nsrc, 0, 9000,512, 512, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture class TBNReader(object): def __init__(self, sock, ring): self.sock = sock @@ -193,6 +239,74 @@ def setUp(self): w = 0.2 self.s0 = 5*np.cos(w * t, dtype='float32') \ + 3j*np.sin(w * t, dtype='float32') + + def _get_simple_data(self): + desc = HeaderInfo() + testdata = self.s0[:2096128].real.astype(np.short) + data_q = bf.ndarray(testdata.reshape(512,1,4094), dtype='i16') + return desc, data_q + + def test_write_simple(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + # Get simple data + op = UDPTransmit('simple', sock) + + desc, data = self._get_simple_data() + # Go! + op.send(desc, 0, 1, 0, 1, data) + sock.close() + + def test_read_simple(self): + # Setup the ring + ring = Ring(name="capture_simple") + + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('simple', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = SIMPLEReader(isock, ring) + ## Data accumulation + final = [] + expectedsize = 4096*512 + aop = AccumulateOp(ring, final, expectedsize,dtype=np.short) + + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get simple data and send it off + desc, data = self._get_simple_data() + for p in range(data.shape[0]): + oop.send(desc, p*1, 1, 0, 1, data[p,...].reshape(1,1,4094)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.short) + + + final = bf.ndarray(final, dtype='i16' ) + final = final.reshape(data.shape) + + np.testing.assert_equal(final,data) + + # Clean up + del oop + isock.close() + osock.close() def _get_tbn_data(self): # Setup the packet HeaderInfo From 9e5946ab93f3cbed2182e03dec0bb3dd77f77659 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 10:58:27 -0700 Subject: [PATCH 356/424] remove debugging print statements --- src/packet_capture.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index 3e00f2053..b9178df84 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -98,22 +98,16 @@ int PacketCaptureThread::run(uint64_t seq_beg, BF_PRINTD("CONTINUE HERE"); continue; } - BF_PRINTD("FINALLY1"); + BF_PRINTD("FINALLY"); ++_stats.nvalid; - BF_PRINTD("FINALLY2"); _stats.nvalid_bytes += _pkt.payload_size; - BF_PRINTD("FINALLY3"); ++_src_stats[_pkt.src].nvalid; - BF_PRINTD("FINALLY4"); _src_stats[_pkt.src].nvalid_bytes += _pkt.payload_size; - BF_PRINTD("FINALLY5"); // HACK TODO: src_ngood_bytes should be accumulated locally and // then atomically updated, like ngood_bytes. The // current way is not thread-safe. - BF_PRINTD("INPUTS" << " " << &_pkt << " " << seq_beg << " " << nseq_per_obuf << " " << nbuf <<" " << obufs<< " " << local_ngood_bytes << " " << src_ngood_bytes); (*process)(&_pkt, seq_beg, nseq_per_obuf, nbuf, obufs, local_ngood_bytes, /*local_*/src_ngood_bytes); - BF_PRINTD("FINALLY6"); } if( nbuf > 0 ) { atomic_add_and_fetch(ngood_bytes[0], local_ngood_bytes[0]); } if( nbuf > 1 ) { atomic_add_and_fetch(ngood_bytes[1], local_ngood_bytes[1]); } From f5e371e69a6d2f47c649f66dcf194ff79b936ccb Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 11:19:59 -0700 Subject: [PATCH 357/424] remove more debugging print statements --- src/formats/simple.hpp | 2 +- src/packet_capture.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 72058d8fb..0c682c7ed 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -31,7 +31,7 @@ #include "base.hpp" struct __attribute__((packed)) simple_hdr_type { - uint32_t seq; + uint64_t seq; }; class SIMPLEDecoder : virtual public PacketDecoder { diff --git a/src/packet_capture.cpp b/src/packet_capture.cpp index b9178df84..ff1bc7ac1 100644 --- a/src/packet_capture.cpp +++ b/src/packet_capture.cpp @@ -191,23 +191,19 @@ BFstatus bfPacketCaptureCallbackSetDRX8(BFpacketcapture_callback obj, BFpacketcapture_status BFpacketcapture_impl::recv() { _t0 = std::chrono::high_resolution_clock::now(); - BF_PRINTD("impl, start clock"); uint8_t* buf_ptrs[2]; // Minor HACK to access the buffers in a 2-element queue buf_ptrs[0] = _bufs.size() > 0 ? (uint8_t*)_bufs.front()->data() : NULL; buf_ptrs[1] = _bufs.size() > 1 ? (uint8_t*)_bufs.back()->data() : NULL; - BF_PRINTD("buff ptrs"); size_t* ngood_bytes_ptrs[2]; ngood_bytes_ptrs[0] = _buf_ngood_bytes.size() > 0 ? &_buf_ngood_bytes.front() : NULL; ngood_bytes_ptrs[1] = _buf_ngood_bytes.size() > 1 ? &_buf_ngood_bytes.back() : NULL; - BF_PRINTD("ngoodbytes"); size_t* src_ngood_bytes_ptrs[2]; src_ngood_bytes_ptrs[0] = _buf_src_ngood_bytes.size() > 0 ? &_buf_src_ngood_bytes.front()[0] : NULL; src_ngood_bytes_ptrs[1] = _buf_src_ngood_bytes.size() > 1 ? &_buf_src_ngood_bytes.back()[0] : NULL; - BF_PRINTD("srcngoodbytes"); int state = _capture->run(_seq, _nseq_per_buf, _bufs.size(), From 2906a95a12d498a3ed5194c5325d00309fed9ad2 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 11:21:42 -0700 Subject: [PATCH 358/424] undo line break --- src/packet_capture.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index b0811c2d8..3172c259f 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -342,8 +342,7 @@ class PacketCaptureThread : public BoundThread { size_t* src_ngood_bytes[], PDC* decode, PPC* process); - inline const char* get_name() { - return _method->get_name(); } + inline const char* get_name() { return _method->get_name(); } inline const size_t get_max_size() { return _method->get_max_size(); } inline const BFiomethod get_io_method() { return _method->get_io_method(); } inline const int get_core() { return _core; } From a7a523789a724529355c7a64073a2266b6877582 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 11:28:58 -0700 Subject: [PATCH 359/424] correct packet format size for simple --- src/packet_capture.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index 3172c259f..ce814249e 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -1306,7 +1306,7 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, if( backend == BF_IO_DISK ) { // Need to know how much to read at a time int nchan = 1; - max_payload_size = 8192; + max_payload_size = 8200; } } else if( std::string(format).substr(0, 5) == std::string("chips") ) { if( backend == BF_IO_DISK ) { From 00756b7281010e809d0d7a0d7420391fa7463efa Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 11:45:25 -0700 Subject: [PATCH 360/424] Update packet_writer.hpp fix packet size --- src/packet_writer.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index d41b6a354..abcf24bfb 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -451,7 +451,7 @@ class BFpacketwriter_simple_impl : public BFpacketwriter_impl { public: inline BFpacketwriter_simple_impl(PacketWriterThread* writer, int nsamples) - : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_I16), + : BFpacketwriter_impl(writer, nullptr, nsamples, BF_DTYPE_CI16), _type_log((std::string(writer->get_name())+"/type").c_str()) { _filler = new SIMPLEHeaderFiller(); _type_log.update("type : %s\n", "simple"); @@ -571,7 +571,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, if(std::string(format).substr(0, 8) == std::string("generic_") ) { nsamples = std::atoi((std::string(format).substr(8, std::string(format).length())).c_str()); } else if( std::string(format).substr(0, 6) == std::string("simple") ) { - nsamples = 4094; + nsamples = 4096; } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; From 801f6be6bd2dd91d7691d368313a019cf993eb06 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 12:02:38 -0700 Subject: [PATCH 361/424] Update simple.hpp correct dtype size --- src/formats/simple.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 0c682c7ed..32e12ebb1 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -88,7 +88,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan = 0; - int nelem = 256; + int nelem = 128; for( ; chan Date: Tue, 27 Feb 2024 12:03:43 -0700 Subject: [PATCH 362/424] Update packet_writer.hpp --- src/packet_writer.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index abcf24bfb..627d40454 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -571,7 +571,7 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, if(std::string(format).substr(0, 8) == std::string("generic_") ) { nsamples = std::atoi((std::string(format).substr(8, std::string(format).length())).c_str()); } else if( std::string(format).substr(0, 6) == std::string("simple") ) { - nsamples = 4096; + nsamples = 2048; } else if( std::string(format).substr(0, 6) == std::string("chips_") ) { int nchan = std::atoi((std::string(format).substr(6, std::string(format).length())).c_str()); nsamples = 32*nchan; From d7ebb9b5ffc72a819c5a4be2f666daad498790a1 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 12:05:43 -0700 Subject: [PATCH 363/424] Update test_disk_io.py --- test/test_disk_io.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index fd1a803ec..327d634f6 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -241,8 +241,13 @@ def _open(self, filename, mode): def _get_simple_data(self): desc = HeaderInfo() - testdata = self.s0[:2096128].real.astype(np.short) - data_q = bf.ndarray(testdata.reshape(512,1,4094), dtype='i16') + + # Reorder as packets, stands, time + data = self.s0.reshape(512,1,4096) + # Convert to ci16 for simple + data_q = bf.ndarray(shape=data.shape, dtype='ci16') + quantize(data, data_q, scale=10) + return desc, data_q def test_write_simple(self): @@ -251,7 +256,7 @@ def test_write_simple(self): desc,data = self._get_simple_data() oop.send(desc,0,1, 0, 1, data) fh.close() - expectedsize = 512*8192 + expectedsize = 512*8200 self.assertEqual(os.path.getsize('test_simple.dat'), \ expectedsize) @@ -260,7 +265,7 @@ def test_read_simple(self): fh = self._open('test_simple.dat', 'wb') oop = DiskWriter('simple', fh) - # Get TBN data + # Get data desc, data = self._get_simple_data() # Go! @@ -290,7 +295,7 @@ def test_read_simple(self): ## Reorder to match what we sent out final = np.array(final, dtype=np.short) - final = bf.ndarray(final, dtype='i16' ) + final = bf.ndarray(final, dtype='ci16' ) final = final.reshape(data.shape) np.testing.assert_equal(final,data) From 06ccc82a2bdbe8006b2f6f0f41381f5c7295aae0 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 14:39:58 -0700 Subject: [PATCH 364/424] working on udp io test --- src/formats/simple.hpp | 2 +- test/test_disk_io.py | 44 ++++++++------ test/test_udp_io.py | 131 ++++++++++++++++++++++------------------- 3 files changed, 98 insertions(+), 79 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 32e12ebb1..0c682c7ed 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -88,7 +88,7 @@ class SIMPLEProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan = 0; - int nelem = 128; + int nelem = 256; for( ; chan Date: Tue, 27 Feb 2024 14:40:20 -0700 Subject: [PATCH 365/424] remove debug file copy --- test/test_disk_io.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index c0dbea62a..0432c3c12 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -278,8 +278,6 @@ def test_read_simple(self): fh.close() # Read - import shutil - shutil.copy("test_simple.dat", "check_simple.dat") fh = self._open('test_simple.dat', 'rb') ring = Ring(name="capture_simple") From 66b0197cc65b1871dae063922406091442ef5f7b Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 27 Feb 2024 15:03:02 -0700 Subject: [PATCH 366/424] test udp io not working --- test/test_udp_io.py | 120 ++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 5712ebab6..2f64e9fb7 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -252,71 +252,71 @@ def _get_simple_data(self): return desc, data_q - # def test_write_simple(self): - # addr = Address('127.0.0.1', 7147) - # sock = UDPSocket() - # sock.connect(addr) - # # Get simple data - # op = UDPTransmit('simple', sock) + def test_write_simple(self): + addr = Address('127.0.0.1', 7147) + sock = UDPSocket() + sock.connect(addr) + # Get simple data + op = UDPTransmit('simple', sock) - # desc, data = self._get_simple_data() - # # Go! - # op.send(desc, 0, 1, 0, 1, data) - # sock.close() + desc, data = self._get_simple_data() + # Go! + op.send(desc, 0, 1, 0, 1, data) + sock.close() - # def test_read_simple(self): - # # Setup the ring - # ring = Ring(name="capture_simple") - # - # # Setup the blocks - # addr = Address('127.0.0.1', 7147) - # ## Output via UDPTransmit - # osock = UDPSocket() - # osock.connect(addr) - # oop = UDPTransmit('simple', osock) - # ## Input via UDPCapture - # isock = UDPSocket() - # isock.bind(addr) - # isock.timeout = 1.0 - # iop = SIMPLEReader(isock, ring) - # ## Data accumulation - # final = [] - # expectedsize = 2048*1024*2 - # aop = AccumulateOp(ring, final, expectedsize,dtype=np.uint16) - # - # - # # Start the reader and accumlator threads - # reader = threading.Thread(target=iop.main) - # accumu = threading.Thread(target=aop.main) - # reader.start() - # accumu.start() - # - # # Get simple data and send it off - # desc, data = self._get_simple_data() - # for p in range(data.shape[0]): - # oop.send(desc, p*1, 1, 0, 1, data[p,...].reshape(1,1,2048)) - # time.sleep(0.001) - # reader.join() - # accumu.join() - # - # # Compare - # ## Reorder to match what we sent out - # final = np.array(final, dtype=np.uint16) + def test_read_simple(self): + # Setup the ring + ring = Ring(name="capture_simple") + + # Setup the blocks + addr = Address('127.0.0.1', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('simple', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = SIMPLEReader(isock, ring) + ## Data accumulation + final = [] + expectedsize = 2048*1024*2 + aop = AccumulateOp(ring, final, expectedsize,dtype=np.uint16) + + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get simple data and send it off + desc, data = self._get_simple_data() + for p in range(data.shape[0]): + oop.send(desc, p*1, 1, 0, 1, data[p,...].reshape(1,1,2048)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint16) - # final = final.reshape(-1,2048,1,2) - # final = final.transpose(0,2,1,3).copy() - # final = bf.ndarray(shape=(final.shape[0],1,2048), dtype='ci16', buffer=final.ctypes.data) + final = final.reshape(-1,2048,1,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],1,2048), dtype='ci16', buffer=final.ctypes.data) - # ## Reduce to match the capture block size - # data = data[:final.shape[0],...] - # for i in range(1, data.shape[0]): - # np.testing.assert_equal(final[i,...], data[i,...]) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) - # # Clean up - # del oop - # isock.close() - # osock.close() - # + # Clean up + del oop + isock.close() + osock.close() + def _get_tbn_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() From 48299909040334fc568623236f81f36afa97476e Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 28 Feb 2024 11:18:10 -0700 Subject: [PATCH 367/424] retry --- test/test_udp_io.py | 598 +++++++++++++++++++++++--------------------- 1 file changed, 314 insertions(+), 284 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 2f64e9fb7..4ce8a0faf 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -32,6 +32,7 @@ import threading import bifrost as bf import datetime +from contextlib import closing from bifrost.ring import Ring from bifrost.address import Address from bifrost.udp_socket import UDPSocket @@ -230,7 +231,7 @@ def main(self): self.output.append(idata) -class UDPIOTest(unittest.TestCase): +class simpleUDPIOTest(unittest.TestCase): """Test simple IO for the UDP-based packet reader and writing""" def setUp(self): """Generate some dummy data to read""" @@ -239,7 +240,6 @@ def setUp(self): w = 0.2 self.s0 = 5*np.cos(w * t, dtype='float32') \ + 3j*np.sin(w * t, dtype='float32') - def _get_simple_data(self): desc = HeaderInfo() @@ -254,15 +254,14 @@ def _get_simple_data(self): def test_write_simple(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - # Get simple data - op = UDPTransmit('simple', sock) + with closing(UDPSocket()) as sock: + sock.connect(addr) + # Get simple data + op = UDPTransmit('simple', sock) - desc, data = self._get_simple_data() - # Go! - op.send(desc, 0, 1, 0, 1, data) - sock.close() + desc, data = self._get_simple_data() + # Go! + op.send(desc, 0, 1, 0, 1, data) def test_read_simple(self): # Setup the ring @@ -271,51 +270,58 @@ def test_read_simple(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('simple', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = SIMPLEReader(isock, ring) - ## Data accumulation - final = [] - expectedsize = 2048*1024*2 - aop = AccumulateOp(ring, final, expectedsize,dtype=np.uint16) - - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get simple data and send it off - desc, data = self._get_simple_data() - for p in range(data.shape[0]): - oop.send(desc, p*1, 1, 0, 1, data[p,...].reshape(1,1,2048)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint16) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('simple', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = SIMPLEReader(isock, ring) + ## Data accumulation + final = [] + expectedsize = 2048*1024*2 + aop = AccumulateOp(ring, final, expectedsize,dtype=np.int16) + + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get simple data and send it off + desc, data = self._get_simple_data() + for p in range(data.shape[0]): + oop.send(desc, p*1, 1, 0, 1, data[p,...].reshape(1,1,2048)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint16) - final = final.reshape(-1,2048,1,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],1,2048), dtype='ci16', buffer=final.ctypes.data) + final = final.reshape(-1,2048,1,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(final, dtype='ci16') - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) # Clean up del oop - isock.close() - osock.close() +class tbnUDPIOTest(unittest.TestCase): + """Test simple IO for the UDP-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') def _get_tbn_data(self): # Setup the packet HeaderInfo @@ -329,22 +335,21 @@ def _get_tbn_data(self): # Convert to ci8 for TBN data_q = bf.ndarray(shape=data.shape, dtype='ci8') quantize(data, data_q, scale=10) - + # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) return desc, data_q def test_write_tbn(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Get TBN data - desc, data = self._get_tbn_data() - - # Go! - op.send(desc, 0, 1960*512, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + op.send(desc, 0, 1960*512, 0, 1, data) def test_read_tbn(self): # Setup the ring ring = Ring(name="capture_tbn") @@ -352,48 +357,59 @@ def test_read_tbn(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('tbn', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = TBNReader(isock, ring) - ## Data accumulation - final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get TBN data and send it off - desc, data = self._get_tbn_data() - for p in range(data.shape[0]): - oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = TBNReader(isock, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2,dtype=np.byte) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + desc, data = self._get_tbn_data() + for p in range(data.shape[0]): + oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + npfinal = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8' ) + final['re'] = npfinal[:,:,:,0] + final['im'] = npfinal[:,:,:,1] + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(2, data.shape[0]): + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop - isock.close() - osock.close() + +class drxUDPIOTest(unittest.TestCase): + """Test simple IO for the UDP-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') + def _get_drx_data(self): # Setup the packet HeaderInfo @@ -413,16 +429,15 @@ def _get_drx_data(self): return desc, data_q def test_write_drx(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('drx', sock) - - # Get TBN data - desc, data = self._get_drx_data() - - # Go! - op.send(desc, 0, 10*4096, (1<<3), 128, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Get TBN data + desc, data = self._get_drx_data() + + # Go! + op.send(desc, 0, 10*4096, (1<<3), 128, data) def test_read_drx(self): # Setup the ring ring = Ring(name="capture_drx") @@ -430,49 +445,47 @@ def test_read_drx(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('drx', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = DRXReader(isock, ring) - ## Data accumulation - final = [] - aop = AccumulateOp(ring, final, 49*4*4096*1) - - # Start the reader - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get DRX data and send it off - desc, data = self._get_drx_data() - for p in range(data.shape[0]): - oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) - oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,4) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = DRXReader(isock, ring) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*4*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + desc, data = self._get_drx_data() + for p in range(data.shape[0]): + oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,4) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(final, dtype='ci4') + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(2, data.shape[0]): + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop - isock.close() - osock.close() def test_write_drx_single(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() @@ -493,49 +506,58 @@ def test_read_drx_single(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('drx', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = DRXReader(isock, ring, nsrc=2) - ## Data accumulation - final = [] - aop = AccumulateOp(ring, final, 49*2*4096*1) - - # Start the reader - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get DRX data and send it off - desc, data = self._get_drx_data() - desc.set_nsrc(2) - for p in range(data.shape[0]): - oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,2) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - for j in range(2): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = DRXReader(isock, ring, nsrc=2) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*2*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + desc, data = self._get_drx_data() + desc.set_nsrc(2) + for p in range(data.shape[0]): + oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,4096,2) + final = final.transpose(0,2,1).copy() + final = bf.ndarray(final, dtype='ci4') + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(1, data.shape[0]): + for j in range(2): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop - isock.close() - osock.close() + +class pbeamUDPIOTest(unittest.TestCase): + """Test simple IO for the UDP-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') + def _get_pbeam_data(self): # Setup the packet HeaderInfo @@ -555,16 +577,15 @@ def _get_pbeam_data(self): return desc, data def test_write_pbeam(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('pbeam1_128', sock) - - # Get PBeam data - desc, data = self._get_pbeam_data() - - # Go! - op.send(desc, 0, 24, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('pbeam1_128', sock) + + # Get PBeam data + desc, data = self._get_pbeam_data() + + # Go! + op.send(desc, 0, 24, 0, 1, data) def test_read_pbeam(self): # Setup the ring ring = Ring(name="capture_pbeam") @@ -573,58 +594,66 @@ def test_read_pbeam(self): addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('pbeam1_128', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = PBeamReader(isock, ring, nsrc=1) - ## Data accumulation - final = [] - aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get PBeam data and send it off - desc, data = self._get_pbeam_data() - for p in range(data.shape[0]): - oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.float32) - final = final.reshape(-1,128*4,1) - final = final.transpose(0,2,1).copy() - ## Reduce to match the capture block size - data = data[:(final.shape[0]//240-1)*240,...] - for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('pbeam1_128', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = PBeamReader(isock, ring, nsrc=1) + ## Data accumulation + final = [] + aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get PBeam data and send it off + desc, data = self._get_pbeam_data() + for p in range(data.shape[0]): + oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.float32) + final = final.reshape(-1,128*4,1) + final = final.transpose(0,2,1).copy() + ## Reduce to match the capture block size + data = data[:(final.shape[0]//240-1)*240,...] + for i in range(2, data.shape[0]): + np.testing.assert_equal(final[i,...], data[i,...]) # Clean up del oop - isock.close() - osock.close() + +class multicastUDPIOTest(unittest.TestCase): + """Test simple IO for the UDP-based packet reader and writing""" + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') def test_write_multicast(self): addr = Address('224.0.0.251', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Get TBN data - desc, data = self._get_tbn_data() - - # Go! - op.send(desc, 0, 1960*512, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + op.send(desc, 0, 1960*512, 0, 1, data) def test_read_multicast(self): # Setup the ring ring = Ring(name="capture_multi") @@ -633,44 +662,45 @@ def test_read_multicast(self): addr = Address('224.0.0.251', 7147) ## Output via UDPTransmit osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('tbn', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = TBNReader(isock, ring) - # Data accumulation - final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get TBN data and send it off - desc, data = self._get_tbn_data() - for p in range(data.shape[0]): - oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 1.0 + iop = TBNReader(isock, ring) + # Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2,dtype=np.byte) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + desc, data = self._get_tbn_data() + for p in range(data.shape[0]): + oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + npfinal = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8' ) + final['re'] = npfinal[:,:,:,0] + final['im'] = npfinal[:,:,:,1] + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(2, data.shape[0]): + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) # Clean up del oop - isock.close() - osock.close() From 3fb41941210c5653eebb2e4eb5c61f175c449109 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 28 Feb 2024 11:24:16 -0700 Subject: [PATCH 368/424] fix --- test/test_udp_io.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 4ce8a0faf..2a07f6e18 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -388,7 +388,8 @@ def test_read_tbn(self): final = np.array(final, dtype=np.uint8) final = final.reshape(-1,512,32,2) npfinal = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8' ) + print(npfinal.shape,data.shape) + final = bf.ndarray(shape=(npfinal.shape[0],32,512), dtype='ci8' ) final['re'] = npfinal[:,:,:,0] final['im'] = npfinal[:,:,:,1] ## Reduce to match the capture block size @@ -642,6 +643,22 @@ def setUp(self): w = 0.2 self.s0 = 5*np.cos(w * t, dtype='float32') \ + 3j*np.sin(w * t, dtype='float32') + def _get_tbn_data(self): + # Setup the packet HeaderInfo + desc = HeaderInfo() + desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + desc.set_gain(20) + + # Reorder as packets, stands, time + data = self.s0.reshape(512,32,-1) + data = data.transpose(2,1,0).copy() + # Convert to ci8 for TBN + data_q = bf.ndarray(shape=data.shape, dtype='ci8') + quantize(data, data_q, scale=10) + + # Update the number of data sources and return + desc.set_nsrc(data_q.shape[1]) + return desc, data_q def test_write_multicast(self): addr = Address('224.0.0.251', 7147) From f081fd15318d6358df95af0c963e27fdc5b8f139 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 28 Feb 2024 11:55:42 -0700 Subject: [PATCH 369/424] working version of packet tests --- test/test_udp_io.py | 69 +++++---------------------------------------- 1 file changed, 7 insertions(+), 62 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 2a07f6e18..26f26a7df 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -231,7 +231,7 @@ def main(self): self.output.append(idata) -class simpleUDPIOTest(unittest.TestCase): +class UDPIOTest(unittest.TestCase): """Test simple IO for the UDP-based packet reader and writing""" def setUp(self): """Generate some dummy data to read""" @@ -280,7 +280,7 @@ def test_read_simple(self): iop = SIMPLEReader(isock, ring) ## Data accumulation final = [] - expectedsize = 2048*1024*2 + expectedsize = 2048*1024 aop = AccumulateOp(ring, final, expectedsize,dtype=np.int16) @@ -303,8 +303,10 @@ def test_read_simple(self): final = np.array(final, dtype=np.uint16) final = final.reshape(-1,2048,1,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(final, dtype='ci16') + npfinal = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(npfinal.shape[0],1,2048), dtype='ci8' ) + final['re'] = npfinal[:,:,:,0] + final['im'] = npfinal[:,:,:,1] ## Reduce to match the capture block size data = data[:final.shape[0],...] @@ -313,16 +315,7 @@ def test_read_simple(self): # Clean up del oop -class tbnUDPIOTest(unittest.TestCase): - """Test simple IO for the UDP-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - + def _get_tbn_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -388,7 +381,6 @@ def test_read_tbn(self): final = np.array(final, dtype=np.uint8) final = final.reshape(-1,512,32,2) npfinal = final.transpose(0,2,1,3).copy() - print(npfinal.shape,data.shape) final = bf.ndarray(shape=(npfinal.shape[0],32,512), dtype='ci8' ) final['re'] = npfinal[:,:,:,0] final['im'] = npfinal[:,:,:,1] @@ -401,17 +393,6 @@ def test_read_tbn(self): # Clean up del oop -class drxUDPIOTest(unittest.TestCase): - """Test simple IO for the UDP-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - - def _get_drx_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -549,16 +530,6 @@ def test_read_drx_single(self): # Clean up del oop -class pbeamUDPIOTest(unittest.TestCase): - """Test simple IO for the UDP-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - def _get_pbeam_data(self): # Setup the packet HeaderInfo @@ -634,32 +605,6 @@ def test_read_pbeam(self): # Clean up del oop -class multicastUDPIOTest(unittest.TestCase): - """Test simple IO for the UDP-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - def _get_tbn_data(self): - # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) - desc.set_gain(20) - - # Reorder as packets, stands, time - data = self.s0.reshape(512,32,-1) - data = data.transpose(2,1,0).copy() - # Convert to ci8 for TBN - data_q = bf.ndarray(shape=data.shape, dtype='ci8') - quantize(data, data_q, scale=10) - - # Update the number of data sources and return - desc.set_nsrc(data_q.shape[1]) - return desc, data_q - def test_write_multicast(self): addr = Address('224.0.0.251', 7147) with closing(UDPSocket()) as sock: From 8dce32d8ea004a6b5a0662eced4b3d3c5085eb24 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 6 Mar 2024 13:49:35 -0700 Subject: [PATCH 370/424] Need be64toh, not 32 --- src/formats/simple.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 0c682c7ed..a1defc3a4 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -49,7 +49,7 @@ class SIMPLEDecoder : virtual public PacketDecoder { const simple_hdr_type* pkt_hdr = (simple_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(simple_hdr_type); int pld_size = pkt_size - sizeof(simple_hdr_type); - pkt->seq = be32toh(pkt_hdr->seq); + pkt->seq = be64toh(pkt_hdr->seq); pkt->nsrc = 1; pkt->src = 0; pkt->payload_size = pld_size; From e1d950b28d28dfbfb68ab766cd48351019362c5f Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Wed, 6 Mar 2024 14:02:06 -0700 Subject: [PATCH 371/424] and the header filler too --- src/formats/simple.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index a1defc3a4..0b7b4dc7f 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -120,6 +120,6 @@ class SIMPLEHeaderFiller : virtual public PacketHeaderFiller { simple_hdr_type* header = reinterpret_cast(hdr); memset(header, 0, sizeof(simple_hdr_type)); - header->seq = htobe32(hdr_base->seq); + header->seq = htobe64(hdr_base->seq); } }; From 30a03f935ceeec08a85dde46fb27cafb1365205d Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 7 Mar 2024 11:33:36 -0700 Subject: [PATCH 372/424] debugging --- src/ring_impl.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/ring_impl.cpp b/src/ring_impl.cpp index b1126142f..ef726be49 100644 --- a/src/ring_impl.cpp +++ b/src/ring_impl.cpp @@ -70,16 +70,23 @@ class RingReallocLock { inline RingReallocLock(unique_lock_type& lock, BFring_impl* ring) : _lock(lock), _ring(ring) { + std::cout<<"herei"<_nrealloc_pending; + std::cout<<"herej"<_realloc_condition.wait(_lock, [this]() { + std::cout<<"herek"<_nwrite_open == 0 && _ring->_nread_open == 0); }); } inline ~RingReallocLock() { + std::cout<<"herel"<_nrealloc_pending; + std::cout<<"herem"<_read_condition.notify_all(); + std::cout<<"heren"<_write_condition.notify_all(); + std::cout<<"hereo"< Date: Thu, 7 Mar 2024 12:35:42 -0700 Subject: [PATCH 373/424] remove debugging --- src/ring_impl.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/ring_impl.cpp b/src/ring_impl.cpp index ef726be49..cc452ac24 100644 --- a/src/ring_impl.cpp +++ b/src/ring_impl.cpp @@ -70,23 +70,16 @@ class RingReallocLock { inline RingReallocLock(unique_lock_type& lock, BFring_impl* ring) : _lock(lock), _ring(ring) { - std::cout<<"herei"<_nrealloc_pending; - std::cout<<"herej"<_realloc_condition.wait(_lock, [this]() { - std::cout<<"herek"<_nwrite_open == 0 && _ring->_nread_open == 0); }); } inline ~RingReallocLock() { - std::cout<<"herel"<_nrealloc_pending; - std::cout<<"herem"<_read_condition.notify_all(); - std::cout<<"heren"<_write_condition.notify_all(); - std::cout<<"hereo"< Date: Fri, 8 Mar 2024 13:54:27 -0700 Subject: [PATCH 374/424] remove debugging --- src/ring_impl.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/ring_impl.cpp b/src/ring_impl.cpp index ef726be49..cc452ac24 100644 --- a/src/ring_impl.cpp +++ b/src/ring_impl.cpp @@ -70,23 +70,16 @@ class RingReallocLock { inline RingReallocLock(unique_lock_type& lock, BFring_impl* ring) : _lock(lock), _ring(ring) { - std::cout<<"herei"<_nrealloc_pending; - std::cout<<"herej"<_realloc_condition.wait(_lock, [this]() { - std::cout<<"herek"<_nwrite_open == 0 && _ring->_nread_open == 0); }); } inline ~RingReallocLock() { - std::cout<<"herel"<_nrealloc_pending; - std::cout<<"herem"<_read_condition.notify_all(); - std::cout<<"heren"<_write_condition.notify_all(); - std::cout<<"hereo"< Date: Fri, 8 Mar 2024 17:34:11 -0700 Subject: [PATCH 375/424] Unlock memory before free. --- src/ib_verbs.hpp | 3 +++ src/ib_verbs_send.hpp | 3 +++ src/packet_writer.cpp | 1 + src/packet_writer.hpp | 2 ++ 4 files changed, 9 insertions(+) diff --git a/src/ib_verbs.hpp b/src/ib_verbs.hpp index 37b559068..187f7ce0a 100644 --- a/src/ib_verbs.hpp +++ b/src/ib_verbs.hpp @@ -295,6 +295,9 @@ class Verbs { } if( _verbs.mr_buf ) { + if( ::munlock(_verbs.mr_buf, _verbs.mr_size) ) { + failures += 1; + } if( ::munmap(_verbs.mr_buf, _verbs.mr_size) ) { failures += 1; } diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index f244c9f92..8ebe9fde0 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -410,6 +410,9 @@ class VerbsSend { } if( _verbs.mr_buf ) { + if( ::munlock(_verbs.mr_buf, _verbs.mr_size) ) { + failures += 1; + } if( ::munmap(_verbs.mr_buf, _verbs.mr_size) ) { failures += 1; } diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index e358478eb..71fd1a3c0 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -61,6 +61,7 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo info, if( hdr_size != _last_size || npackets != _last_count ) { if( _pkt_hdrs ) { + ::munlock(_pkt_hdrs, _last_count*_last_size*sizeof(char)); free(_pkt_hdrs); } diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 7884f5bbd..0aebaf081 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -172,9 +172,11 @@ class UDPPacketSender : public PacketWriterMethod { int flags=0) { if( npackets != _last_count ) { if( _mmsg ) { + ::munlock(_mmsg, sizeof(struct mmsghdr)*_last_count); free(_mmsg); } if( _iovs ) { + ::munlock(_iovs, sizeof(struct iovec)*2*_last_count); free(_iovs); } From 8d80917c5b806c2924506b23d02304a5a94bd0c0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Mar 2024 17:36:20 -0700 Subject: [PATCH 376/424] Missed a couple unlocks. Plus, just use _limiter for the rate limit. --- src/packet_writer.hpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 0aebaf081..547fbd5a5 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -239,11 +239,10 @@ class UDPVerbsSender : public PacketWriterMethod { int _last_count; mmsghdr* _mmsg; iovec* _iovs; - uint32_t _rate_holder; public: UDPVerbsSender(int fd, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) : PacketWriterMethod(fd, max_burst_size), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), - _last_count(0), _mmsg(NULL), _iovs(NULL), _rate_holder(0) {} + _last_count(0), _mmsg(NULL), _iovs(NULL) {} ~UDPVerbsSender() { if( _mmsg ) { free(_mmsg); @@ -260,9 +259,11 @@ class UDPVerbsSender : public PacketWriterMethod { int flags=0) { if( npackets != _last_count ) { if( _mmsg ) { + ::munlock(_mmsg, sizeof(struct mmsghdr)*_last_count); free(_mmsg); } if( _iovs ) { + ::munlock(_iovs, sizeof(struct iovec)*3*_last_count); free(_iovs); } @@ -286,8 +287,8 @@ class UDPVerbsSender : public PacketWriterMethod { _ibv.get_ipv4_header(&(_udp_hdr.ipv4), _last_size); _ibv.get_udp_header(&(_udp_hdr.udp), _last_size); - if( _rate_holder > 0 ) { - _ibv.set_rate_limit(_rate_holder*_last_size, _last_size, _max_burst_size); + if( _limiter.get_rate() > 0 ) { + _ibv.set_rate_limit(_limiter.get_rate()*_last_size, _last_size, _max_burst_size); } } @@ -310,8 +311,6 @@ class UDPVerbsSender : public PacketWriterMethod { return nsent; } inline const char* get_name() { return "udp_verbs_transmit"; } - inline void set_rate(uint32_t rate_limit) { _rate_holder = rate_limit; } - inline uint32_t get_rate() { return _rate_holder; } }; #endif // BF_VERBS_ENABLED From d97c645001a034e74951f854cc885fd1636531d4 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Mar 2024 17:38:02 -0700 Subject: [PATCH 377/424] Drop provide a default packet size. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 8ebe9fde0..4ddbcdbce 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -723,7 +723,7 @@ class VerbsSend { destroy_buffers(); destroy_context(); } - inline void set_rate_limit(uint32_t rate_limit, size_t udp_length=1, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) { + inline void set_rate_limit(uint32_t rate_limit, size_t udp_length, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) { int i; // Converts to B/s to kb/s assuming a packet size From 012c9ee6acbceed28594c0e4bc8fca589bec27bb Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Mar 2024 17:45:12 -0700 Subject: [PATCH 378/424] Check both the upper and lower ends of the packet pacing range. --- src/ib_verbs_send.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index 4ddbcdbce..c672f93ce 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -96,7 +96,7 @@ struct bf_ibv_send { int nqueued; uint8_t offload_csum; - uint32_t hardware_pacing; + uint32_t hardware_pacing[2]; }; struct __attribute__((packed)) bf_ethernet_hdr { @@ -337,12 +337,13 @@ class VerbsSend { #endif std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; - _verbs.hardware_pacing = 0; + _verbs.hardware_pacing = {0}; #if defined BF_VERBS_SEND_PACING && BF_VERBS_SEND_PACING if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) ) { - _verbs.hardware_pacing = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_max; + _verbs.hardware_pacing[0] = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_min; + _verbs.hardware_pacing[1] = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_max; } - std::cout << "_verbs.hardware_pacing: " << (int) _verbs.hardware_pacing << std::endl; + std::cout << "_verbs.hardware_pacing: " << (int) _verbs.hardware_pacing[0] << ", " << (int) _verbs.hardware_pacing[1] << std::endl; #endif break; } @@ -732,9 +733,9 @@ class VerbsSend { // Verify that this rate limit is valid if( rate_limit == 0 ) { - rate_limit = _verbs.hardware_pacing; + rate_limit = _verbs.hardware_pacing[1]; } - if( rate_limit > _verbs.hardware_pacing ) { + if( rate_limit < _verbs.hardware_pacing[0] || rate_limit > _verbs.hardware_pacing[1] ) { throw VerbsSend::Error("Failed to set rate limit, specified rate limit is out of range"); } From cfad6a1b90282938835c8d244ca25c58f616d69d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 8 Mar 2024 18:19:24 -0700 Subject: [PATCH 379/424] Change assignment. --- src/ib_verbs_send.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ib_verbs_send.hpp b/src/ib_verbs_send.hpp index c672f93ce..40d2e7093 100644 --- a/src/ib_verbs_send.hpp +++ b/src/ib_verbs_send.hpp @@ -337,7 +337,7 @@ class VerbsSend { #endif std::cout << "_verbs.offload_csum: " << (int) _verbs.offload_csum << std::endl; - _verbs.hardware_pacing = {0}; + _verbs.hardware_pacing[0] = _verbs.hardware_pacing[1] = 0; #if defined BF_VERBS_SEND_PACING && BF_VERBS_SEND_PACING if( ibv_is_qpt_supported(ibv_dev_attr.packet_pacing_caps.supported_qpts, IBV_QPT_RAW_PACKET) ) { _verbs.hardware_pacing[0] = ibv_dev_attr.packet_pacing_caps.qp_rate_limit_min; From e443012a7f8ced5762c6efe173d37add28788666 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Mar 2024 17:16:58 -0600 Subject: [PATCH 380/424] Make a copy of the ring's data (#231). --- test/test_disk_io.py | 2 +- test/test_udp_io.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index f58fe61dc..283e3b4d4 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -182,7 +182,7 @@ def main(self): while not self.ring.writing_ended(): for ispan in iseq_spans: idata = ispan.data_view(self.dtype) - self.output.append(idata) + self.output.append(idata.copy()) class DiskIOTest(unittest.TestCase): diff --git a/test/test_udp_io.py b/test/test_udp_io.py index b38e2038d..60ec8c8b6 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -181,7 +181,7 @@ def main(self): while not self.ring.writing_ended(): for ispan in iseq_spans: idata = ispan.data_view(self.dtype) - self.output.append(idata) + self.output.append(idata.copy()) class UDPIOTest(unittest.TestCase): From 351000a610e80b66b7b4d7395282e8d446e8feab Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 15 Mar 2024 18:31:15 -0600 Subject: [PATCH 381/424] Refactor into a TestCase per packet format. --- test/test_disk_io.py | 265 ++++++++++++++++---------------- test/test_udp_io.py | 359 ++++++++++++++++++++++--------------------- 2 files changed, 315 insertions(+), 309 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 283e3b4d4..ca8fbdf05 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2024, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -37,6 +37,43 @@ from bifrost.pipeline import SourceBlock, SinkBlock import numpy as np +class AccumulateOp(object): + def __init__(self, ring, output, size, dtype=np.uint8): + self.ring = ring + self.output = output + self.size = size*(dtype().nbytes) + self.dtype = dtype + + self.ring.resize(self.size*10) + + def main(self): + for iseq in self.ring.read(guarantee=True): + iseq_spans = iseq.read(self.size) + while not self.ring.writing_ended(): + for ispan in iseq_spans: + idata = ispan.data_view(self.dtype) + self.output.append(idata.copy()) + +class BaseDiskIOTest(object): + class BaseDiskIOTestCase(unittest.TestCase): + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') + # Filename cache so we can cleanup later + self._cache = [] + def _open(self, filename, mode): + fh = open(filename, mode) + if filename not in self._cache: + self._cache.append(filename) + return fh + def tearDown(self): + for filename in self._cache: + os.unlink(filename) + class TBNReader(object): def __init__(self, sock, ring): @@ -77,131 +114,9 @@ def main(self): if status in (1,4,5,6): break del capture - - -class DRXReader(object): - def __init__(self, sock, ring, nsrc=4): - self.sock = sock - self.ring = ring - self.nsrc = nsrc - def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag - hdr = {'time_tag': time_tag, - 'seq0': seq0, - 'chan0': chan0, - 'chan1': chan1, - 'cfreq0': 196e6 * chan0/2.**32, - 'cfreq1': 196e6 * chan1/2.**32, - 'bw': 196e6/decim, - 'nstand': nsrc/2, - 'npol': 2, - 'complex': True, - 'nbit': 4} - #print "******** CFREQ:", hdr['cfreq'] - try: - hdr_str = json.dumps(hdr).encode() - except AttributeError: - # Python2 catch - pass - # TODO: Can't pad with NULL because returned as C-string - #hdr_str = json.dumps(hdr).ljust(4096, '\0') - #hdr_str = json.dumps(hdr).ljust(4096, ' ') - header_buf = ctypes.create_string_buffer(hdr_str) - hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) - hdr_size_ptr[0] = len(hdr_str) - return 0 - def main(self): - seq_callback = PacketCaptureCallback() - seq_callback.set_drx(self.callback) - with DiskReader("drx", self.sock, self.ring, self.nsrc, 0, 49, 49, - sequence_callback=seq_callback) as capture: - while True: - status = capture.recv() - if status in (1,4,5,6): - break - del capture - - -class PBeamReader(object): - def __init__(self, sock, ring, nchan, nsrc=1): - self.sock = sock - self.ring = ring - self.nchan = nchan - self.nsrc = nsrc - def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag - hdr = {'time_tag': time_tag, - 'seq0': seq0, - 'chan0': chan0, - 'cfreq0': chan0*(196e6/8192), - 'bw': nchan*(196e6/8192), - 'navg': navg, - 'nbeam': nbeam, - 'npol': 4, - 'complex': False, - 'nbit': 32} - #print("******** HDR:", hdr) - try: - hdr_str = json.dumps(hdr).encode() - except AttributeError: - # Python2 catch - pass - # TODO: Can't pad with NULL because returned as C-string - #hdr_str = json.dumps(hdr).ljust(4096, '\0') - #hdr_str = json.dumps(hdr).ljust(4096, ' ') - header_buf = ctypes.create_string_buffer(hdr_str) - hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) - hdr_size_ptr[0] = len(hdr_str) - return 0 - def main(self): - seq_callback = PacketCaptureCallback() - seq_callback.set_pbeam(self.callback) - with DiskReader("pbeam_%i" % self.nchan, self.sock, self.ring, self.nsrc, 1, 240, 240, - sequence_callback=seq_callback) as capture: - while True: - status = capture.recv() - if status in (1,4,5,6): - break - del capture - - -class AccumulateOp(object): - def __init__(self, ring, output, size, dtype=np.uint8): - self.ring = ring - self.output = output - self.size = size*(dtype().nbytes) - self.dtype = dtype - - self.ring.resize(self.size*10) - - def main(self): - for iseq in self.ring.read(guarantee=True): - iseq_spans = iseq.read(self.size) - while not self.ring.writing_ended(): - for ispan in iseq_spans: - idata = ispan.data_view(self.dtype) - self.output.append(idata.copy()) - - -class DiskIOTest(unittest.TestCase): - """Test simple IO for the disk-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - # Filename cache so we can cleanup later - self._cache = [] - def _open(self, filename, mode): - fh = open(filename, mode) - if filename not in self._cache: - self._cache.append(filename) - return fh +class TBNDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): + """Test simple IO for the disk-based TBN packet reader and writing""" def _get_tbn_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -275,7 +190,53 @@ def test_read_tbn(self): # Clean up del oop fh.close() - + + +class DRXReader(object): + def __init__(self, sock, ring, nsrc=4): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'chan1': chan1, + 'cfreq0': 196e6 * chan0/2.**32, + 'cfreq1': 196e6 * chan1/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 4} + #print "******** CFREQ:", hdr['cfreq'] + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_drx(self.callback) + with DiskReader("drx", self.sock, self.ring, self.nsrc, 0, 49, 49, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + +class DRXDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): + """Test simple IO for the disk-based DRX packet reader and writing""" def _get_drx_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -407,7 +368,53 @@ def test_read_drx_single(self): # Clean up del oop fh.close() - + + +class PBeamReader(object): + def __init__(self, sock, ring, nchan, nsrc=1): + self.sock = sock + self.ring = ring + self.nchan = nchan + self.nsrc = nsrc + def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq0': chan0*(196e6/8192), + 'bw': nchan*(196e6/8192), + 'navg': navg, + 'nbeam': nbeam, + 'npol': 4, + 'complex': False, + 'nbit': 32} + #print("******** HDR:", hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_pbeam(self.callback) + with DiskReader("pbeam_%i" % self.nchan, self.sock, self.ring, self.nsrc, 1, 240, 240, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + +class PBeamDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): + """Test simple IO for the disk-based PBeam packet reader and writing""" def _get_pbeam_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -480,7 +487,3 @@ def test_read_pbeam(self): # Clean up del oop fh.close() - - def tearDown(self): - for filename in self._cache: - os.unlink(filename) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 60ec8c8b6..e9698850e 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -1,4 +1,4 @@ -# Copyright (c) 2019-2022, The Bifrost Authors. All rights reserved. +# Copyright (c) 2019-2024, The Bifrost Authors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -39,6 +39,31 @@ from bifrost.quantize import quantize import numpy as np +class AccumulateOp(object): + def __init__(self, ring, output, size, dtype=np.uint8): + self.ring = ring + self.output = output + self.size = size*(dtype().nbytes) + self.dtype = dtype + + def main(self): + for iseq in self.ring.read(guarantee=True): + iseq_spans = iseq.read(self.size) + while not self.ring.writing_ended(): + for ispan in iseq_spans: + idata = ispan.data_view(self.dtype) + self.output.append(idata.copy()) + +class BaseUDPIOTest(object): + class BaseUDPIOTestCase(unittest.TestCase): + def setUp(self): + """Generate some dummy data to read""" + # Generate test vector and save to file + t = np.arange(256*4096*2) + w = 0.2 + self.s0 = 5*np.cos(w * t, dtype='float32') \ + + 3j*np.sin(w * t, dtype='float32') + class TBNReader(object): def __init__(self, sock, ring): @@ -80,120 +105,8 @@ def main(self): break del capture - -class DRXReader(object): - def __init__(self, sock, ring, nsrc=4): - self.sock = sock - self.ring = ring - self.nsrc = nsrc - def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag - hdr = {'time_tag': time_tag, - 'seq0': seq0, - 'chan0': chan0, - 'chan1': chan1, - 'cfreq0': 196e6 * chan0/2.**32, - 'cfreq1': 196e6 * chan1/2.**32, - 'bw': 196e6/decim, - 'nstand': nsrc/2, - 'npol': 2, - 'complex': True, - 'nbit': 4} - #print "******** CFREQ:", hdr['cfreq'] - try: - hdr_str = json.dumps(hdr).encode() - except AttributeError: - # Python2 catch - pass - # TODO: Can't pad with NULL because returned as C-string - #hdr_str = json.dumps(hdr).ljust(4096, '\0') - #hdr_str = json.dumps(hdr).ljust(4096, ' ') - header_buf = ctypes.create_string_buffer(hdr_str) - hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) - hdr_size_ptr[0] = len(hdr_str) - return 0 - def main(self): - seq_callback = PacketCaptureCallback() - seq_callback.set_drx(self.callback) - with UDPCapture("drx", self.sock, self.ring, self.nsrc, 0, 9000, 49, 49, - sequence_callback=seq_callback) as capture: - while True: - status = capture.recv() - if status in (1,4,5,6): - break - del capture - - -class PBeamReader(object): - def __init__(self, sock, ring, nsrc=1): - self.sock = sock - self.ring = ring - self.nsrc = nsrc - def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): - #print "++++++++++++++++ seq0 =", seq0 - #print " time_tag =", time_tag - hdr = {'time_tag': time_tag, - 'seq0': seq0, - 'chan0': chan0, - 'cfreq0': chan0*(196e6/8192), - 'bw': nchan*(196e6/8192), - 'navg': navg, - 'nbeam': nbeam, - 'npol': 4, - 'complex': False, - 'nbit': 32} - #print("******** HDR:", hdr) - try: - hdr_str = json.dumps(hdr).encode() - except AttributeError: - # Python2 catch - pass - # TODO: Can't pad with NULL because returned as C-string - #hdr_str = json.dumps(hdr).ljust(4096, '\0') - #hdr_str = json.dumps(hdr).ljust(4096, ' ') - header_buf = ctypes.create_string_buffer(hdr_str) - hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) - hdr_size_ptr[0] = len(hdr_str) - return 0 - def main(self): - seq_callback = PacketCaptureCallback() - seq_callback.set_pbeam(self.callback) - with UDPCapture("pbeam", self.sock, self.ring, self.nsrc, 1, 9000, 240, 240, - sequence_callback=seq_callback) as capture: - while True: - status = capture.recv() - if status in (1,4,5,6): - break - del capture - - -class AccumulateOp(object): - def __init__(self, ring, output, size, dtype=np.uint8): - self.ring = ring - self.output = output - self.size = size*(dtype().nbytes) - self.dtype = dtype - - def main(self): - for iseq in self.ring.read(guarantee=True): - iseq_spans = iseq.read(self.size) - while not self.ring.writing_ended(): - for ispan in iseq_spans: - idata = ispan.data_view(self.dtype) - self.output.append(idata.copy()) - - -class UDPIOTest(unittest.TestCase): - """Test simple IO for the UDP-based packet reader and writing""" - def setUp(self): - """Generate some dummy data to read""" - # Generate test vector and save to file - t = np.arange(256*4096*2) - w = 0.2 - self.s0 = 5*np.cos(w * t, dtype='float32') \ - + 3j*np.sin(w * t, dtype='float32') - +class TBNUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): + """Test simple IO for the UDP-based TBN packet reader and writing""" def _get_tbn_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -271,7 +184,114 @@ def test_read_tbn(self): del oop isock.close() osock.close() + def test_write_multicast(self): + addr = Address('224.0.0.251', 7147) + sock = UDPSocket() + sock.connect(addr) + op = UDPTransmit('tbn', sock) + # Get TBN data + desc, data = self._get_tbn_data() + + # Go! + op.send(desc, 0, 1960*512, 0, 1, data) + sock.close() + def test_read_multicast(self): + # Setup the ring + ring = Ring(name="capture_multi") + + # Setup the blocks + addr = Address('224.0.0.251', 7147) + ## Output via UDPTransmit + osock = UDPSocket() + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + isock = UDPSocket() + isock.bind(addr) + isock.timeout = 1.0 + iop = TBNReader(isock, ring) + # Data accumulation + final = [] + aop = AccumulateOp(ring, final, 49*32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + desc, data = self._get_tbn_data() + for p in range(data.shape[0]): + oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + ## Reorder to match what we sent out + final = np.array(final, dtype=np.uint8) + final = final.reshape(-1,512,32,2) + final = final.transpose(0,2,1,3).copy() + final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) + ## Reduce to match the capture block size + data = data[:final.shape[0],...] + for i in range(2, data.shape[0]): + for j in range(data.shape[1]): + np.testing.assert_equal(final[i,j,...], data[i,j,...]) + + # Clean up + del oop + isock.close() + osock.close() + + +class DRXReader(object): + def __init__(self, sock, ring, nsrc=4): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'chan1': chan1, + 'cfreq0': 196e6 * chan0/2.**32, + 'cfreq1': 196e6 * chan1/2.**32, + 'bw': 196e6/decim, + 'nstand': nsrc/2, + 'npol': 2, + 'complex': True, + 'nbit': 4} + #print "******** CFREQ:", hdr['cfreq'] + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_drx(self.callback) + with UDPCapture("drx", self.sock, self.ring, self.nsrc, 0, 9000, 49, 49, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + +class DRXUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): + """Test simple IO for the UDP-based DRX packet reader and writing""" def _get_drx_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -413,7 +433,52 @@ def test_read_drx_single(self): del oop isock.close() osock.close() - + + +class PBeamReader(object): + def __init__(self, sock, ring, nsrc=1): + self.sock = sock + self.ring = ring + self.nsrc = nsrc + def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ptr): + #print "++++++++++++++++ seq0 =", seq0 + #print " time_tag =", time_tag + hdr = {'time_tag': time_tag, + 'seq0': seq0, + 'chan0': chan0, + 'cfreq0': chan0*(196e6/8192), + 'bw': nchan*(196e6/8192), + 'navg': navg, + 'nbeam': nbeam, + 'npol': 4, + 'complex': False, + 'nbit': 32} + #print("******** HDR:", hdr) + try: + hdr_str = json.dumps(hdr).encode() + except AttributeError: + # Python2 catch + pass + # TODO: Can't pad with NULL because returned as C-string + #hdr_str = json.dumps(hdr).ljust(4096, '\0') + #hdr_str = json.dumps(hdr).ljust(4096, ' ') + header_buf = ctypes.create_string_buffer(hdr_str) + hdr_ptr[0] = ctypes.cast(header_buf, ctypes.c_void_p) + hdr_size_ptr[0] = len(hdr_str) + return 0 + def main(self): + seq_callback = PacketCaptureCallback() + seq_callback.set_pbeam(self.callback) + with UDPCapture("pbeam", self.sock, self.ring, self.nsrc, 1, 9000, 240, 240, + sequence_callback=seq_callback) as capture: + while True: + status = capture.recv() + if status in (1,4,5,6): + break + del capture + +class PBeamUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): + """Test simple IO for the UDP-based PBeam packet reader and writing""" def _get_pbeam_data(self): # Setup the packet HeaderInfo desc = HeaderInfo() @@ -489,65 +554,3 @@ def test_read_pbeam(self): del oop isock.close() osock.close() - - def test_write_multicast(self): - addr = Address('224.0.0.251', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Get TBN data - desc, data = self._get_tbn_data() - - # Go! - op.send(desc, 0, 1960*512, 0, 1, data) - sock.close() - def test_read_multicast(self): - # Setup the ring - ring = Ring(name="capture_multi") - - # Setup the blocks - addr = Address('224.0.0.251', 7147) - ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('tbn', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 1.0 - iop = TBNReader(isock, ring) - # Data accumulation - final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get TBN data and send it off - desc, data = self._get_tbn_data() - for p in range(data.shape[0]): - oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) - - # Clean up - del oop - isock.close() - osock.close() From edfaca016e859112439330adf120a34b38b7d6e6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sat, 16 Mar 2024 18:10:40 -0600 Subject: [PATCH 382/424] Naming cleanup. --- test/test_disk_io.py | 16 ++++++++-------- test/test_udp_io.py | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index ca8fbdf05..94183e5b0 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -133,7 +133,7 @@ def _get_tbn_data(self): # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) return desc, data_q - def test_write_tbn(self): + def test_write(self): fh = self._open('test_tbn.dat', 'wb') oop = DiskWriter('tbn', fh) @@ -146,7 +146,7 @@ def test_write_tbn(self): self.assertEqual(os.path.getsize('test_tbn.dat'), \ 1048*data.shape[0]*data.shape[1]) - def test_read_tbn(self): + def test_read(self): # Write fh = self._open('test_tbn.dat', 'wb') oop = DiskWriter('tbn', fh) @@ -253,7 +253,7 @@ def _get_drx_data(self): # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) return desc, data_q - def test_write_drx(self): + def test_write(self): fh = self._open('test_drx.dat', 'wb') oop = DiskWriter('drx', fh) @@ -266,7 +266,7 @@ def test_write_drx(self): self.assertEqual(os.path.getsize('test_drx.dat'), \ 4128*data.shape[0]*data.shape[1]) - def test_read_drx(self): + def test_read(self): # Write fh = self._open('test_drx.dat', 'wb') oop = DiskWriter('drx', fh) @@ -310,7 +310,7 @@ def test_read_drx(self): # Clean up del oop fh.close() - def test_write_drx_single(self): + def test_write_single(self): fh = self._open('test_drx_single.dat', 'wb') oop = DiskWriter('drx', fh) @@ -324,7 +324,7 @@ def test_write_drx_single(self): self.assertEqual(os.path.getsize('test_drx_single.dat'), \ 4128*data.shape[0]*data.shape[1]/2) - def test_read_drx_single(self): + def test_read_single(self): # Write fh = self._open('test_drx_single.dat', 'wb') oop = DiskWriter('drx', fh) @@ -431,7 +431,7 @@ def _get_pbeam_data(self): # Update the number of data sources and return desc.set_nsrc(data.shape[1]) return desc, data - def test_write_pbeam(self): + def test_write(self): fh = self._open('test_pbeam.dat', 'wb') oop = DiskWriter('pbeam1_128', fh) @@ -444,7 +444,7 @@ def test_write_pbeam(self): self.assertEqual(os.path.getsize('test_pbeam.dat'), \ (18+128*4*4)*data.shape[0]*data.shape[1]) - def test_read_pbeam(self): + def test_read(self): # Write fh = self._open('test_pbeam.dat', 'wb') oop = DiskWriter('pbeam1_128', fh) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index e9698850e..899886b65 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -123,7 +123,7 @@ def _get_tbn_data(self): # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) return desc, data_q - def test_write_tbn(self): + def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() sock.connect(addr) @@ -135,7 +135,7 @@ def test_write_tbn(self): # Go! op.send(desc, 0, 1960*512, 0, 1, data) sock.close() - def test_read_tbn(self): + def test_read(self): # Setup the ring ring = Ring(name="capture_tbn") @@ -308,7 +308,7 @@ def _get_drx_data(self): # Update the number of data sources and return desc.set_nsrc(data_q.shape[1]) return desc, data_q - def test_write_drx(self): + def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() sock.connect(addr) @@ -320,7 +320,7 @@ def test_write_drx(self): # Go! op.send(desc, 0, 10*4096, (1<<3), 128, data) sock.close() - def test_read_drx(self): + def test_read(self): # Setup the ring ring = Ring(name="capture_drx") @@ -370,7 +370,7 @@ def test_read_drx(self): del oop isock.close() osock.close() - def test_write_drx_single(self): + def test_write_single(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() sock.connect(addr) @@ -383,7 +383,7 @@ def test_write_drx_single(self): # Go! op.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) sock.close() - def test_read_drx_single(self): + def test_read_single(self): # Setup the ring ring = Ring(name="capture_drx_single") @@ -495,7 +495,7 @@ def _get_pbeam_data(self): # Update the number of data sources and return desc.set_nsrc(data.shape[1]) return desc, data - def test_write_pbeam(self): + def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() sock.connect(addr) @@ -507,7 +507,7 @@ def test_write_pbeam(self): # Go! op.send(desc, 0, 24, 0, 1, data) sock.close() - def test_read_pbeam(self): + def test_read(self): # Setup the ring ring = Ring(name="capture_pbeam") From 0e6d1d82eb0fe57f25c143782bbafaed6fd572ea Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sun, 17 Mar 2024 08:11:59 -0600 Subject: [PATCH 383/424] Even more cleanups to make the test suite more useful as an example. --- test/test_disk_io.py | 192 +++++++++++++++++----------------- test/test_udp_io.py | 238 ++++++++++++++++++++++--------------------- 2 files changed, 221 insertions(+), 209 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 94183e5b0..4ee9b6508 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -38,21 +38,23 @@ import numpy as np class AccumulateOp(object): - def __init__(self, ring, output, size, dtype=np.uint8): + def __init__(self, ring, output_timetags, output_data, size, dtype=np.uint8): self.ring = ring - self.output = output + self.output_timetags = output_timetags + self.output_data = output_data self.size = size*(dtype().nbytes) self.dtype = dtype - self.ring.resize(self.size*10) - def main(self): for iseq in self.ring.read(guarantee=True): + self.output_timetags.append(iseq.time_tag) + self.output_data.append([]) + iseq_spans = iseq.read(self.size) while not self.ring.writing_ended(): for ispan in iseq_spans: idata = ispan.data_view(self.dtype) - self.output.append(idata.copy()) + self.output_data[-1].append(idata.copy()) class BaseDiskIOTest(object): class BaseDiskIOTestCase(unittest.TestCase): @@ -76,9 +78,10 @@ def tearDown(self): class TBNReader(object): - def __init__(self, sock, ring): + def __init__(self, sock, ring, nsrc=32): self.sock = sock self.ring = ring + self.nsrc = nsrc def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): #print "++++++++++++++++ seq0 =", seq0 #print " time_tag =", time_tag @@ -107,7 +110,7 @@ def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_tbn(self.callback) - with DiskReader("tbn", self.sock, self.ring, 32, 0, 49, 196, + with DiskReader("tbn", self.sock, self.ring, self.nsrc, 0, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -117,11 +120,11 @@ def main(self): class TBNDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): """Test simple IO for the disk-based TBN packet reader and writing""" - def _get_tbn_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) - desc.set_gain(20) + hdr_desc = HeaderInfo() + hdr_desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + hdr_desc.set_gain(20) # Reorder as packets, stands, time data = self.s0.reshape(512,32,-1) @@ -131,17 +134,17 @@ def _get_tbn_data(self): quantize(data, data_q, scale=10) # Update the number of data sources and return - desc.set_nsrc(data_q.shape[1]) - return desc, data_q + hdr_desc.set_nsrc(data_q.shape[1]) + return 1, hdr_desc, data_q def test_write(self): fh = self._open('test_tbn.dat', 'wb') oop = DiskWriter('tbn', fh) # Get TBN data - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() # Go! - oop.send(desc, 0, 1960*512, 0, 1, data) + oop.send(hdr_desc, timetag0, 1960*512, 0, 1, data) fh.close() self.assertEqual(os.path.getsize('test_tbn.dat'), \ @@ -152,19 +155,20 @@ def test_read(self): oop = DiskWriter('tbn', fh) # Get TBN data - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() # Go! - oop.send(desc, 0, 1960*512, 0, 1, data) + oop.send(hdr_desc, timetag0, 1960*512, 0, 1, data) fh.close() # Read fh = self._open('test_tbn.dat', 'rb') ring = Ring(name="capture_tbn") - iop = TBNReader(fh, ring) + iop = TBNReader(fh, ring, nsrc=32) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) + aop = AccumulateOp(ring, times, final, 32*512*2) # Start the reader and accumlator threads reader = threading.Thread(target=iop.main) @@ -177,15 +181,16 @@ def test_read(self): accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for seq_timetag,seq_data in zip(times, final): + ## Loop over sequences + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,512,32,2) + seq_data = seq_data.transpose(0,2,1,3).copy() + ## Drop the last axis (complexity) since we are going to ci8 + seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) + + ## Ignore the first set of packets + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) # Clean up del oop @@ -227,7 +232,7 @@ def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_drx(self.callback) - with DiskReader("drx", self.sock, self.ring, self.nsrc, 0, 49, 49, + with DiskReader("drx", self.sock, self.ring, self.nsrc, 0, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -237,11 +242,11 @@ def main(self): class DRXDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): """Test simple IO for the disk-based DRX packet reader and writing""" - def _get_drx_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_decimation(10) - desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + hdr_desc = HeaderInfo() + hdr_desc.set_decimation(10) + hdr_desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) # Reorder as packets, beams, time data = self.s0.reshape(4096,4,-1) @@ -251,17 +256,17 @@ def _get_drx_data(self): quantize(data, data_q) # Update the number of data sources and return - desc.set_nsrc(data_q.shape[1]) - return desc, data_q + hdr_desc.set_nsrc(data_q.shape[1]) + return 1, hdr_desc, data_q def test_write(self): fh = self._open('test_drx.dat', 'wb') oop = DiskWriter('drx', fh) # Get DRX data - desc, data = self._get_drx_data() + timetag0, hdr_desc, data = self._get_data() # Go! - oop.send(desc, 0, 10*4096, (1<<3), 128, data) + oop.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) fh.close() self.assertEqual(os.path.getsize('test_drx.dat'), \ @@ -272,19 +277,20 @@ def test_read(self): oop = DiskWriter('drx', fh) # Get DRX data and write it out - desc, data = self._get_drx_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): - oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) - oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) fh.close() # Read fh = self._open('test_drx.dat', 'rb') ring = Ring(name="capture_drx") - iop = DRXReader(fh, ring) + iop = DRXReader(fh, ring, nsrc=4) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*4*4096*1) + aop = AccumulateOp(ring, times, final, 4*4096*1) # Start the reader reader = threading.Thread(target=iop.main) @@ -297,15 +303,14 @@ def test_read(self): accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,4) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,4) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) # Clean up del oop @@ -315,24 +320,26 @@ def test_write_single(self): oop = DiskWriter('drx', fh) # Get DRX data - desc, data = self._get_drx_data() - desc.set_nsrc(2) + timetag0, hdr_desc, data = self._get_data() + hdr_desc.set_nsrc(2) + data = data[:,[0,1],:].copy() # Go! - oop.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + oop.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) fh.close() self.assertEqual(os.path.getsize('test_drx_single.dat'), \ - 4128*data.shape[0]*data.shape[1]/2) + 4128*data.shape[0]*data.shape[1]) def test_read_single(self): # Write fh = self._open('test_drx_single.dat', 'wb') oop = DiskWriter('drx', fh) # Get DRX data and write it out - desc, data = self._get_drx_data() - desc.set_nsrc(2) - oop.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + timetag0, hdr_desc, data = self._get_data() + hdr_desc.set_nsrc(2) + data = data[:,[0,1],:].copy() + oop.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) fh.close() # Read @@ -340,8 +347,9 @@ def test_read_single(self): ring = Ring(name="capture_drx_single") iop = DRXReader(fh, ring, nsrc=2) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*2*4096*1) + aop = AccumulateOp(ring, times, final, 2*4096*1) # Start the reader reader = threading.Thread(target=iop.main) @@ -354,16 +362,14 @@ def test_read_single(self): accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,2) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - data = data[:,[0,1],:] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,2) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) # Clean up del oop @@ -405,7 +411,7 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_pbeam(self.callback) - with DiskReader("pbeam_%i" % self.nchan, self.sock, self.ring, self.nsrc, 1, 240, 240, + with DiskReader("pbeam_%i" % self.nchan, self.sock, self.ring, self.nsrc, 1, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -415,31 +421,31 @@ def main(self): class PBeamDiskIOTest(BaseDiskIOTest.BaseDiskIOTestCase): """Test simple IO for the disk-based PBeam packet reader and writing""" - def _get_pbeam_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_tuning(2) - desc.set_chan0(1034) - desc.set_nchan(128) - desc.set_decimation(24) + hdr_desc = HeaderInfo() + hdr_desc.set_tuning(2) + hdr_desc.set_chan0(1034) + hdr_desc.set_nchan(128) + hdr_desc.set_decimation(24) # Reorder as packets, beam, chan/pol data = self.s0.reshape(128*4,1,-1) data = data.transpose(2,1,0) - data = data.real.copy() + data = data.real[:1024,...].copy() # Update the number of data sources and return - desc.set_nsrc(data.shape[1]) - return desc, data + hdr_desc.set_nsrc(data.shape[1]) + return 1, hdr_desc, data def test_write(self): fh = self._open('test_pbeam.dat', 'wb') oop = DiskWriter('pbeam1_128', fh) # Get PBeam data - desc, data = self._get_pbeam_data() + timetag0, hdr_desc, data = self._get_data() # Go! - oop.send(desc, 0, 24, 0, 2, data) + oop.send(hdr_desc, timetag0, 24, 0, 1, data) fh.close() self.assertEqual(os.path.getsize('test_pbeam.dat'), \ @@ -450,10 +456,10 @@ def test_read(self): oop = DiskWriter('pbeam1_128', fh) # Get PBeam data - desc, data = self._get_pbeam_data() + timetag0, hdr_desc, data = self._get_data() # Go! - oop.send(desc, 1, 24, 0, 1, data) + oop.send(hdr_desc, timetag0, 24, 0, 1, data) fh.close() # Read @@ -461,8 +467,9 @@ def test_read(self): ring = Ring(name="capture_pbeam") iop = PBeamReader(fh, ring, 128, nsrc=1) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) + aop = AccumulateOp(ring, times, final, 1*128*4, dtype=np.float32) # Start the reader and accumlator threads reader = threading.Thread(target=iop.main) @@ -470,19 +477,18 @@ def test_read(self): reader.start() accumu.start() - # Get TBN data + # Get PBeam data reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.float32) - final = final.reshape(-1,128*4,1) - final = final.transpose(0,2,1).copy() - ## Reduce to match the capture block size - data = data[:(final.shape[0]//240-1)*240,...] - for i in range(1, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.float32) + seq_data = seq_data.reshape(-1,128*4,1) + seq_data = seq_data.transpose(0,2,1).copy() + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) # Clean up del oop diff --git a/test/test_udp_io.py b/test/test_udp_io.py index 899886b65..a42bc0cef 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -40,19 +40,23 @@ import numpy as np class AccumulateOp(object): - def __init__(self, ring, output, size, dtype=np.uint8): + def __init__(self, ring, output_timetags, output_data, size, dtype=np.uint8): self.ring = ring - self.output = output + self.output_timetags = output_timetags + self.output_data = output_data self.size = size*(dtype().nbytes) self.dtype = dtype def main(self): for iseq in self.ring.read(guarantee=True): + self.output_timetags.append(iseq.time_tag) + self.output_data.append([]) + iseq_spans = iseq.read(self.size) while not self.ring.writing_ended(): for ispan in iseq_spans: idata = ispan.data_view(self.dtype) - self.output.append(idata.copy()) + self.output_data[-1].append(idata.copy()) class BaseUDPIOTest(object): class BaseUDPIOTestCase(unittest.TestCase): @@ -66,9 +70,10 @@ def setUp(self): class TBNReader(object): - def __init__(self, sock, ring): + def __init__(self, sock, ring, nsrc=32): self.sock = sock self.ring = ring + self.nsrc = nsrc def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): #print "++++++++++++++++ seq0 =", seq0 #print " time_tag =", time_tag @@ -97,7 +102,7 @@ def callback(self, seq0, time_tag, decim, chan0, nsrc, hdr_ptr, hdr_size_ptr): def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_tbn(self.callback) - with UDPCapture("tbn", self.sock, self.ring, 32, 0, 9000, 49, 196, + with UDPCapture("tbn", self.sock, self.ring, self.nsrc, 0, 9000, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -107,11 +112,11 @@ def main(self): class TBNUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): """Test simple IO for the UDP-based TBN packet reader and writing""" - def _get_tbn_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) - desc.set_gain(20) + hdr_desc = HeaderInfo() + hdr_desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + hdr_desc.set_gain(20) # Reorder as packets, stands, time data = self.s0.reshape(512,32,-1) @@ -121,8 +126,8 @@ def _get_tbn_data(self): quantize(data, data_q, scale=10) # Update the number of data sources and return - desc.set_nsrc(data_q.shape[1]) - return desc, data_q + hdr_desc.set_nsrc(data_q.shape[1]) + return 1, hdr_desc, data_q def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() @@ -130,10 +135,10 @@ def test_write(self): op = UDPTransmit('tbn', sock) # Get TBN data - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() # Go! - op.send(desc, 0, 1960*512, 0, 1, data) + op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) sock.close() def test_read(self): # Setup the ring @@ -148,11 +153,12 @@ def test_read(self): ## Input via UDPCapture isock = UDPSocket() isock.bind(addr) - isock.timeout = 1.0 - iop = TBNReader(isock, ring) + isock.timeout = 0.1 + iop = TBNReader(isock, ring, nsrc=32) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) + aop = AccumulateOp(ring, times, final, 32*512*2) # Start the reader and accumlator threads reader = threading.Thread(target=iop.main) @@ -161,25 +167,25 @@ def test_read(self): accumu.start() # Get TBN data and send it off - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): - oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) time.sleep(0.001) reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + for seq_timetag,seq_data in zip(times, final): + ## Loop over sequences + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,512,32,2) + seq_data = seq_data.transpose(0,2,1,3).copy() + ## Drop the last axis (complexity) since we are going to ci8 + seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) + + ## Ignore the first set of packets + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + # Clean up del oop isock.close() @@ -191,10 +197,10 @@ def test_write_multicast(self): op = UDPTransmit('tbn', sock) # Get TBN data - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() # Go! - op.send(desc, 0, 1960*512, 0, 1, data) + op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) sock.close() def test_read_multicast(self): # Setup the ring @@ -209,11 +215,12 @@ def test_read_multicast(self): ## Input via UDPCapture isock = UDPSocket() isock.bind(addr) - isock.timeout = 1.0 - iop = TBNReader(isock, ring) + isock.timeout = 0.1 + iop = TBNReader(isock, ring, nsrc=32) # Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*32*512*2) + aop = AccumulateOp(ring, times, final, 32*512*2) # Start the reader and accumlator threads reader = threading.Thread(target=iop.main) @@ -222,25 +229,25 @@ def test_read_multicast(self): accumu.start() # Get TBN data and send it off - desc, data = self._get_tbn_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): - oop.send(desc, p*1960*512, 1960*512, 0, 1, data[p,...].reshape(1,32,512)) + oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) time.sleep(0.001) reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,512,32,2) - final = final.transpose(0,2,1,3).copy() - final = bf.ndarray(shape=(final.shape[0],32,512), dtype='ci8', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + for seq_timetag,seq_data in zip(times, final): + ## Loop over sequences + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,512,32,2) + seq_data = seq_data.transpose(0,2,1,3).copy() + ## Drop the last axis (complexity) since we are going to ci8 + seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) + + ## Ignore the first set of packets + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + # Clean up del oop isock.close() @@ -282,7 +289,7 @@ def callback(self, seq0, time_tag, decim, chan0, chan1, nsrc, hdr_ptr, hdr_size_ def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_drx(self.callback) - with UDPCapture("drx", self.sock, self.ring, self.nsrc, 0, 9000, 49, 49, + with UDPCapture("drx", self.sock, self.ring, self.nsrc, 0, 9000, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -292,11 +299,11 @@ def main(self): class DRXUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): """Test simple IO for the UDP-based DRX packet reader and writing""" - def _get_drx_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_decimation(10) - desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) + hdr_desc = HeaderInfo() + hdr_desc.set_decimation(10) + hdr_desc.set_tuning(int(round(74e6 / 196e6 * 2**32))) # Reorder as packets, beams, time data = self.s0.reshape(4096,4,-1) @@ -306,8 +313,8 @@ def _get_drx_data(self): quantize(data, data_q) # Update the number of data sources and return - desc.set_nsrc(data_q.shape[1]) - return desc, data_q + hdr_desc.set_nsrc(data_q.shape[1]) + return 1, hdr_desc, data_q def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() @@ -315,10 +322,10 @@ def test_write(self): op = UDPTransmit('drx', sock) # Get TBN data - desc, data = self._get_drx_data() + timetag0, hdr_desc, data = self._get_data() # Go! - op.send(desc, 0, 10*4096, (1<<3), 128, data) + op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) sock.close() def test_read(self): # Setup the ring @@ -333,11 +340,12 @@ def test_read(self): ## Input via UDPCapture isock = UDPSocket() isock.bind(addr) - isock.timeout = 1.0 - iop = DRXReader(isock, ring) + isock.timeout = 0.1 + iop = DRXReader(isock, ring, nsrc=4) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*4*4096*1) + aop = AccumulateOp(ring, times, final, 4*4096*1) # Start the reader reader = threading.Thread(target=iop.main) @@ -346,26 +354,24 @@ def test_read(self): accumu.start() # Get DRX data and send it off - desc, data = self._get_drx_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): - oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) - oop.send(desc, p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) time.sleep(0.001) reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,4) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],4,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(2, data.shape[0]): - for j in range(data.shape[1]): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,4) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + # Clean up del oop isock.close() @@ -377,11 +383,12 @@ def test_write_single(self): op = UDPTransmit('drx', sock) # Get DRX data - desc, data = self._get_drx_data() - desc.set_nsrc(2) + timetag0, hdr_desc, data = self._get_data() + hdr_desc.set_nsrc(2) + data = data[:,[0,1],:].copy() # Go! - op.send(desc, 0, 10*4096, (1<<3), 128, data[:,[0,1],:].copy()) + op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) sock.close() def test_read_single(self): # Setup the ring @@ -396,11 +403,12 @@ def test_read_single(self): ## Input via UDPCapture isock = UDPSocket() isock.bind(addr) - isock.timeout = 1.0 + isock.timeout = 0.1 iop = DRXReader(isock, ring, nsrc=2) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 49*2*4096*1) + aop = AccumulateOp(ring, times, final, 2*4096*1) # Start the reader reader = threading.Thread(target=iop.main) @@ -409,26 +417,24 @@ def test_read_single(self): accumu.start() # Get DRX data and send it off - desc, data = self._get_drx_data() - desc.set_nsrc(2) + timetag0, hdr_desc, data = self._get_data() + data = data[:,[0,1],:].copy() for p in range(data.shape[0]): - oop.send(desc, p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],:].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[[p],...]) time.sleep(0.001) reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.uint8) - final = final.reshape(-1,4096,2) - final = final.transpose(0,2,1).copy() - final = bf.ndarray(shape=(final.shape[0],2,4096), dtype='ci4', buffer=final.ctypes.data) - ## Reduce to match the capture block size - data = data[:final.shape[0],...] - for i in range(1, data.shape[0]): - for j in range(2): - np.testing.assert_equal(final[i,j,...], data[i,j,...]) - + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,2) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + # Clean up del oop isock.close() @@ -469,7 +475,7 @@ def callback(self, seq0, time_tag, navg, chan0, nchan, nbeam, hdr_ptr, hdr_size_ def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_pbeam(self.callback) - with UDPCapture("pbeam", self.sock, self.ring, self.nsrc, 1, 9000, 240, 240, + with UDPCapture("pbeam", self.sock, self.ring, self.nsrc, 1, 9000, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -479,22 +485,22 @@ def main(self): class PBeamUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): """Test simple IO for the UDP-based PBeam packet reader and writing""" - def _get_pbeam_data(self): + def _get_data(self): # Setup the packet HeaderInfo - desc = HeaderInfo() - desc.set_tuning(1) - desc.set_chan0(345) - desc.set_nchan(128) - desc.set_decimation(24) + hdr_desc = HeaderInfo() + hdr_desc.set_tuning(1) + hdr_desc.set_chan0(345) + hdr_desc.set_nchan(128) + hdr_desc.set_decimation(24) # Reorder as packets, beam, chan/pol data = self.s0.reshape(128*4,1,-1) data = data.transpose(2,1,0) - data = data.real.copy() + data = data.real[:1024,...].copy() # Update the number of data sources and return - desc.set_nsrc(data.shape[1]) - return desc, data + hdr_desc.set_nsrc(data.shape[1]) + return 1, hdr_desc, data def test_write(self): addr = Address('127.0.0.1', 7147) sock = UDPSocket() @@ -502,10 +508,10 @@ def test_write(self): op = UDPTransmit('pbeam1_128', sock) # Get PBeam data - desc, data = self._get_pbeam_data() + timetag0, hdr_desc, data = self._get_data() # Go! - op.send(desc, 0, 24, 0, 1, data) + op.send(hdr_desc, timetag0, 24, 0, 1, data) sock.close() def test_read(self): # Setup the ring @@ -520,11 +526,12 @@ def test_read(self): ## Input via UDPCapture isock = UDPSocket() isock.bind(addr) - isock.timeout = 1.0 + isock.timeout = 0.1 iop = PBeamReader(isock, ring, nsrc=1) ## Data accumulation + times = [] final = [] - aop = AccumulateOp(ring, final, 240*128*4, dtype=np.float32) + aop = AccumulateOp(ring, times, final, 1*128*4, dtype=np.float32) # Start the reader and accumlator threads reader = threading.Thread(target=iop.main) @@ -533,22 +540,21 @@ def test_read(self): accumu.start() # Get PBeam data and send it off - desc, data = self._get_pbeam_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): - oop.send(desc, p*24, 24, 0, 1, data[p,...].reshape(1,1,128*4)) + oop.send(hdr_desc, timetag0+p*24, 24, 0, 1, data[[p],...]) time.sleep(0.001) reader.join() accumu.join() # Compare - ## Reorder to match what we sent out - final = np.array(final, dtype=np.float32) - final = final.reshape(-1,128*4,1) - final = final.transpose(0,2,1).copy() - ## Reduce to match the capture block size - data = data[:(final.shape[0]//240-1)*240,...] - for i in range(2, data.shape[0]): - np.testing.assert_equal(final[i,...], data[i,...]) + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.float32) + seq_data = seq_data.reshape(-1,128*4,1) + seq_data = seq_data.transpose(0,2,1).copy() + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) # Clean up del oop From 03d507319c0e5fda36853da245b1c10f6fb0a93a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sun, 17 Mar 2024 08:34:58 -0600 Subject: [PATCH 384/424] More with closing(). --- test/test_udp_io.py | 509 +++++++++++++++++++++----------------------- 1 file changed, 247 insertions(+), 262 deletions(-) diff --git a/test/test_udp_io.py b/test/test_udp_io.py index e025a19ee..ee2b736a2 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -132,16 +132,15 @@ def _get_data(self): return 1, hdr_desc, data_q def test_write(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Get TBN data - timetag0, hdr_desc, data = self._get_data() - - # Go! - op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + timetag0, hdr_desc, data = self._get_data() + + # Go! + op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) def test_read(self): # Setup the ring ring = Ring(name="capture_tbn") @@ -149,61 +148,58 @@ def test_read(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('tbn', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 0.1 - iop = TBNReader(isock, ring, nsrc=32) - ## Data accumulation - times = [] - final = [] - aop = AccumulateOp(ring, times, final, 32*512*2) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get TBN data and send it off - timetag0, hdr_desc, data = self._get_data() - for p in range(data.shape[0]): - oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - for seq_timetag,seq_data in zip(times, final): - ## Loop over sequences - seq_data = np.array(seq_data, dtype=np.uint8) - seq_data = seq_data.reshape(-1,512,32,2) - seq_data = seq_data.transpose(0,2,1,3).copy() - ## Drop the last axis (complexity) since we are going to ci8 - seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) - - ## Ignore the first set of packets - np.testing.assert_equal(seq_data[1:,...], data[1:,...]) - - # Clean up - del oop - isock.close() - osock.close() + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 0.1 + iop = TBNReader(isock, ring, nsrc=32) + ## Data accumulation + times = [] + final = [] + aop = AccumulateOp(ring, times, final, 32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + timetag0, hdr_desc, data = self._get_data() + for p in range(data.shape[0]): + oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + for seq_timetag,seq_data in zip(times, final): + ## Loop over sequences + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,512,32,2) + seq_data = seq_data.transpose(0,2,1,3).copy() + ## Drop the last axis (complexity) since we are going to ci8 + seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) + + ## Ignore the first set of packets + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + + # Clean up + del oop def test_write_multicast(self): addr = Address('224.0.0.251', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('tbn', sock) - - # Get TBN data - timetag0, hdr_desc, data = self._get_data() - - # Go! - op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('tbn', sock) + + # Get TBN data + timetag0, hdr_desc, data = self._get_data() + + # Go! + op.send(hdr_desc, timetag0, 1960*512, 0, 1, data) def test_read_multicast(self): # Setup the ring ring = Ring(name="capture_multi") @@ -211,49 +207,47 @@ def test_read_multicast(self): # Setup the blocks addr = Address('224.0.0.251', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('tbn', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 0.1 - iop = TBNReader(isock, ring, nsrc=32) - # Data accumulation - times = [] - final = [] - aop = AccumulateOp(ring, times, final, 32*512*2) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get TBN data and send it off - timetag0, hdr_desc, data = self._get_data() - for p in range(data.shape[0]): - oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - for seq_timetag,seq_data in zip(times, final): - ## Loop over sequences - seq_data = np.array(seq_data, dtype=np.uint8) - seq_data = seq_data.reshape(-1,512,32,2) - seq_data = seq_data.transpose(0,2,1,3).copy() - ## Drop the last axis (complexity) since we are going to ci8 - seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) - - ## Ignore the first set of packets - np.testing.assert_equal(seq_data[1:,...], data[1:,...]) - - # Clean up - del oop - isock.close() - osock.close() + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('tbn', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 0.1 + iop = TBNReader(isock, ring, nsrc=32) + # Data accumulation + times = [] + final = [] + aop = AccumulateOp(ring, times, final, 32*512*2) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get TBN data and send it off + timetag0, hdr_desc, data = self._get_data() + for p in range(data.shape[0]): + oop.send(hdr_desc, timetag0+p*1960*512, 1960*512, 0, 1, data[[p],...]) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + for seq_timetag,seq_data in zip(times, final): + ## Loop over sequences + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,512,32,2) + seq_data = seq_data.transpose(0,2,1,3).copy() + ## Drop the last axis (complexity) since we are going to ci8 + seq_data = bf.ndarray(shape=seq_data.shape[:-1], dtype='ci8', buffer=seq_data.ctypes.data) + + ## Ignore the first set of packets + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + + # Clean up + del oop class DRXReader(object): @@ -319,16 +313,15 @@ def _get_data(self): return 1, hdr_desc, data_q def test_write(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('drx', sock) - - # Get TBN data - timetag0, hdr_desc, data = self._get_data() - - # Go! - op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Get TBN data + timetag0, hdr_desc, data = self._get_data() + + # Go! + op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) def test_read(self): # Setup the ring ring = Ring(name="capture_drx") @@ -336,62 +329,59 @@ def test_read(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('drx', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 0.1 - iop = DRXReader(isock, ring, nsrc=4) - ## Data accumulation - times = [] - final = [] - aop = AccumulateOp(ring, times, final, 4*4096*1) - - # Start the reader - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get DRX data and send it off - timetag0, hdr_desc, data = self._get_data() - for p in range(data.shape[0]): - oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) - oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - for seq_timetag,seq_data in zip(times, final): - ## Reorder to match what we sent out - seq_data = np.array(seq_data, dtype=np.uint8) - seq_data = seq_data.reshape(-1,4096,4) - seq_data = seq_data.transpose(0,2,1).copy() - seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) - - np.testing.assert_equal(seq_data[1:,...], data[1:,...]) - - # Clean up - del oop - isock.close() - osock.close() + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 0.1 + iop = DRXReader(isock, ring, nsrc=4) + ## Data accumulation + times = [] + final = [] + aop = AccumulateOp(ring, times, final, 4*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + timetag0, hdr_desc, data = self._get_data() + for p in range(data.shape[0]): + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[p,[0,1],...].reshape(1,2,4096)) + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (2<<3), 128, data[p,[2,3],...].reshape(1,2,4096)) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,4) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + + # Clean up + del oop def test_write_single(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('drx', sock) - - # Get DRX data - timetag0, hdr_desc, data = self._get_data() - hdr_desc.set_nsrc(2) - data = data[:,[0,1],:].copy() - - # Go! - op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('drx', sock) + + # Get DRX data + timetag0, hdr_desc, data = self._get_data() + hdr_desc.set_nsrc(2) + data = data[:,[0,1],:].copy() + + # Go! + op.send(hdr_desc, timetag0, 10*4096, (1<<3), 128, data) def test_read_single(self): # Setup the ring ring = Ring(name="capture_drx_single") @@ -399,48 +389,46 @@ def test_read_single(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('drx', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 0.1 - iop = DRXReader(isock, ring, nsrc=2) - ## Data accumulation - times = [] - final = [] - aop = AccumulateOp(ring, times, final, 2*4096*1) - - # Start the reader - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get DRX data and send it off - timetag0, hdr_desc, data = self._get_data() - data = data[:,[0,1],:].copy() - for p in range(data.shape[0]): - oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[[p],...]) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - for seq_timetag,seq_data in zip(times, final): - ## Reorder to match what we sent out - seq_data = np.array(seq_data, dtype=np.uint8) - seq_data = seq_data.reshape(-1,4096,2) - seq_data = seq_data.transpose(0,2,1).copy() - seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) - - np.testing.assert_equal(seq_data[1:,...], data[1:,...]) - - # Clean up - del oop - isock.close() - osock.close() + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('drx', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 0.1 + iop = DRXReader(isock, ring, nsrc=2) + ## Data accumulation + times = [] + final = [] + aop = AccumulateOp(ring, times, final, 2*4096*1) + + # Start the reader + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get DRX data and send it off + timetag0, hdr_desc, data = self._get_data() + data = data[:,[0,1],:].copy() + for p in range(data.shape[0]): + oop.send(hdr_desc, timetag0+p*10*4096, 10*4096, (1<<3), 128, data[[p],...]) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.uint8) + seq_data = seq_data.reshape(-1,4096,2) + seq_data = seq_data.transpose(0,2,1).copy() + seq_data = bf.ndarray(shape=seq_data.shape, dtype='ci4', buffer=seq_data.ctypes.data) + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + + # Clean up + del oop class PBeamReader(object): @@ -505,16 +493,15 @@ def _get_data(self): return 1, hdr_desc, data def test_write(self): addr = Address('127.0.0.1', 7147) - sock = UDPSocket() - sock.connect(addr) - op = UDPTransmit('pbeam1_128', sock) - - # Get PBeam data - timetag0, hdr_desc, data = self._get_data() - - # Go! - op.send(hdr_desc, timetag0, 24, 0, 1, data) - sock.close() + with closing(UDPSocket()) as sock: + sock.connect(addr) + op = UDPTransmit('pbeam1_128', sock) + + # Get PBeam data + timetag0, hdr_desc, data = self._get_data() + + # Go! + op.send(hdr_desc, timetag0, 24, 0, 1, data) def test_read(self): # Setup the ring ring = Ring(name="capture_pbeam") @@ -522,46 +509,44 @@ def test_read(self): # Setup the blocks addr = Address('127.0.0.1', 7147) ## Output via UDPTransmit - osock = UDPSocket() - osock.connect(addr) - oop = UDPTransmit('pbeam1_128', osock) - ## Input via UDPCapture - isock = UDPSocket() - isock.bind(addr) - isock.timeout = 0.1 - iop = PBeamReader(isock, ring, nsrc=1) - ## Data accumulation - times = [] - final = [] - aop = AccumulateOp(ring, times, final, 1*128*4, dtype=np.float32) - - # Start the reader and accumlator threads - reader = threading.Thread(target=iop.main) - accumu = threading.Thread(target=aop.main) - reader.start() - accumu.start() - - # Get PBeam data and send it off - timetag0, hdr_desc, data = self._get_data() - for p in range(data.shape[0]): - oop.send(hdr_desc, timetag0+p*24, 24, 0, 1, data[[p],...]) - time.sleep(0.001) - reader.join() - accumu.join() - - # Compare - for seq_timetag,seq_data in zip(times, final): - ## Reorder to match what we sent out - seq_data = np.array(seq_data, dtype=np.float32) - seq_data = seq_data.reshape(-1,128*4,1) - seq_data = seq_data.transpose(0,2,1).copy() - - np.testing.assert_equal(seq_data[1:,...], data[1:,...]) - - # Clean up - del oop - isock.close() - osock.close() + with closing(UDPSocket()) as osock: + osock.connect(addr) + oop = UDPTransmit('pbeam1_128', osock) + ## Input via UDPCapture + with closing(UDPSocket()) as isock: + isock.bind(addr) + isock.timeout = 0.1 + iop = PBeamReader(isock, ring, nsrc=1) + ## Data accumulation + times = [] + final = [] + aop = AccumulateOp(ring, times, final, 1*128*4, dtype=np.float32) + + # Start the reader and accumlator threads + reader = threading.Thread(target=iop.main) + accumu = threading.Thread(target=aop.main) + reader.start() + accumu.start() + + # Get PBeam data and send it off + timetag0, hdr_desc, data = self._get_data() + for p in range(data.shape[0]): + oop.send(hdr_desc, timetag0+p*24, 24, 0, 1, data[[p],...]) + time.sleep(0.001) + reader.join() + accumu.join() + + # Compare + for seq_timetag,seq_data in zip(times, final): + ## Reorder to match what we sent out + seq_data = np.array(seq_data, dtype=np.float32) + seq_data = seq_data.reshape(-1,128*4,1) + seq_data = seq_data.transpose(0,2,1).copy() + + np.testing.assert_equal(seq_data[1:,...], data[1:,...]) + + # Clean up + del oop start_pipeline = datetime.datetime.now() From 53cd5048c9388550c50e6597d8ae4660b629b019 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sun, 17 Mar 2024 08:37:35 -0600 Subject: [PATCH 385/424] Formatting. --- src/formats/simple.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/formats/simple.hpp b/src/formats/simple.hpp index 0b7b4dc7f..98f4f244d 100644 --- a/src/formats/simple.hpp +++ b/src/formats/simple.hpp @@ -49,13 +49,13 @@ class SIMPLEDecoder : virtual public PacketDecoder { const simple_hdr_type* pkt_hdr = (simple_hdr_type*)pkt_ptr; const uint8_t* pkt_pld = pkt_ptr + sizeof(simple_hdr_type); int pld_size = pkt_size - sizeof(simple_hdr_type); - pkt->seq = be64toh(pkt_hdr->seq); - pkt->nsrc = 1; - pkt->src = 0; + pkt->seq = be64toh(pkt_hdr->seq); + pkt->nsrc = 1; + pkt->src = 0; pkt->payload_size = pld_size; pkt->payload_ptr = pkt_pld; - pkt->nchan = 1; - pkt->chan0 = 0; + pkt->nchan = 1; + pkt->chan0 = 0; return this->valid_packet(pkt); } }; @@ -88,10 +88,10 @@ class SIMPLEProcessor : virtual public PacketProcessor { otype* __restrict__ out = (otype* )&obufs[obuf_idx][obuf_offset]; int chan = 0; - int nelem = 256; + int nelem = 256; for( ; chan Date: Sun, 17 Mar 2024 08:56:38 -0600 Subject: [PATCH 386/424] Formatting. --- src/packet_capture.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index ce814249e..25ba75fc1 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -642,12 +642,12 @@ class BFpacketcapture_simple_impl : public BFpacketcapture_impl { } public: inline BFpacketcapture_simple_impl(PacketCaptureThread* capture, - BFring ring, - int nsrc, - int src0, - int buffer_ntime, - int slot_ntime, - BFpacketcapture_callback sequence_callback) + BFring ring, + int nsrc, + int src0, + int buffer_ntime, + int slot_ntime, + BFpacketcapture_callback sequence_callback) : BFpacketcapture_impl(capture, nullptr, nullptr, ring, nsrc, buffer_ntime, slot_ntime), _type_log((std::string(capture->get_name())+"/type").c_str()), _chan_log((std::string(capture->get_name())+"/chans").c_str()), @@ -685,9 +685,9 @@ class BFpacketcapture_chips_impl : public BFpacketcapture_impl { } void on_sequence_changed(const PacketDesc* pkt, BFoffset* seq0, BFoffset* time_tag, const void** hdr, size_t* hdr_size) { *seq0 = _seq;// + _nseq_per_buf*_bufs.size(); - _chan0 = pkt->chan0; - _nchan = pkt->nchan; - _payload_size = pkt->payload_size; + _chan0 = pkt->chan0; + _nchan = pkt->nchan; + _payload_size = pkt->payload_size; if( _sequence_callback ) { int status = (*_sequence_callback)(*seq0, From 96bc19a74e8d2762ccec38c166e420b83f93be3b Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Sun, 17 Mar 2024 08:59:43 -0600 Subject: [PATCH 387/424] The SIMPLE tests seem sensitive to what timetag0 is. --- test/test_disk_io.py | 4 ++-- test/test_udp_io.py | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/test/test_disk_io.py b/test/test_disk_io.py index 10c0c2c07..2c1ca6aed 100644 --- a/test/test_disk_io.py +++ b/test/test_disk_io.py @@ -531,7 +531,7 @@ def seq_callback(self, seq0, chan0, nchan, nsrc, def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_simple(self.seq_callback) - with DiskReader("simple" , self.sock, self.ring, self.nsrc, 0, 256, 1024, + with DiskReader("simple" , self.sock, self.ring, self.nsrc, 0, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -551,7 +551,7 @@ def _get_simple_data(self): data_q = bf.ndarray(shape=data.shape, dtype='ci16') quantize(data, data_q, scale=10) - return 1, hdr_desc, data_q + return 128, hdr_desc, data_q def test_write_simple(self): fh = self._open('test_simple.dat','wb') diff --git a/test/test_udp_io.py b/test/test_udp_io.py index ee2b736a2..0e0897377 100644 --- a/test/test_udp_io.py +++ b/test/test_udp_io.py @@ -587,7 +587,7 @@ def seq_callback(self, seq0, chan0, nchan, nsrc, def main(self): seq_callback = PacketCaptureCallback() seq_callback.set_simple(self.seq_callback) - with UDPCapture("simple" , self.sock, self.ring, self.nsrc, 0, 9000,512, 512, + with UDPCapture("simple" , self.sock, self.ring, self.nsrc, 0, 9000, 16, 128, sequence_callback=seq_callback) as capture: while True: status = capture.recv() @@ -598,7 +598,7 @@ def main(self): class SimpleUDPIOTest(BaseUDPIOTest.BaseUDPIOTestCase): """Test simple IO for the UDP-based Simple packet reader and writing""" - def _get_simple_data(self): + def _get_data(self): hdr_desc = HeaderInfo() # Reorder as packets, stands, time @@ -608,20 +608,20 @@ def _get_simple_data(self): data_q = bf.ndarray(shape=data.shape, dtype='ci16') quantize(data, data_q, scale=10) - return 1, hdr_desc, data_q + return 128, hdr_desc, data_q - def test_write_simple(self): + def test_write(self): addr = Address('127.0.0.1', 7147) with closing(UDPSocket()) as sock: sock.connect(addr) # Get simple data op = UDPTransmit('simple', sock) - timetag0, hdr_desc, data = self._get_simple_data() + timetag0, hdr_desc, data = self._get_data() # Go! op.send(hdr_desc, timetag0, 1, 0, 1, data) - def test_read_simple(self): + def test_read(self): # Setup the ring ring = Ring(name="capture_simple") @@ -650,7 +650,7 @@ def test_read_simple(self): accumu.start() # Get simple data and send it off - timetag0, hdr_desc, data = self._get_simple_data() + timetag0, hdr_desc, data = self._get_data() for p in range(data.shape[0]): oop.send(hdr_desc, timetag0+p*1, 1, 0, 1, data[[p],...]) time.sleep(0.001) @@ -659,7 +659,6 @@ def test_read_simple(self): # Compare for seq_timetag,seq_data in zip(times, final): - print(seq_timetag) seq_data = np.array(seq_data, dtype=np.uint16) seq_data = seq_data.reshape(-1,2048,1,2) seq_data = seq_data.transpose(0,2,1,3).copy() From e32a32b1ed8b01c440c67f35a2a7fb35ac17b2b6 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 19 Mar 2024 15:13:50 -0600 Subject: [PATCH 388/424] Nice. --- configure.ac | 9 --------- 1 file changed, 9 deletions(-) diff --git a/configure.ac b/configure.ac index 6344dc53c..2033cc92f 100644 --- a/configure.ac +++ b/configure.ac @@ -139,14 +139,6 @@ AS_IF([test x$enable_verbs != xno], [AC_SUBST([HAVE_VERBS], [1]) LIBS="$LIBS -libverbs"])]) -<<<<<<< HEAD -AC_ARG_WITH([verbs_npktbuf], - [AS_HELP_STRING([--with-verbs-npktbuf=N], - [default Infiniband verbs buffer size in packets (default=8192)])], - [], - [with_verbs_npktbuf=8192]) -AC_SUBST([VERBS_NPKTBUF], [$with_verbs_npktbuf]) -======= AC_ARG_WITH([rx-buffer-size], [AS_HELP_STRING([--with-rx-buffer-size=N], [default Infiniband verbs receive buffer size in packets (default=8192)])], @@ -188,7 +180,6 @@ AC_SUBST([VERBS_NPKTBUF], [$with_verbs_npktbuf]) [AC_SUBST([VERBS_SEND_PACING], [0]) AC_MSG_RESULT([no])]) ]) ->>>>>>> upstream/ibverb-support # # RDMA From 587044a37652b0822a6cbe149c4944824c4d4fd1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 22 Mar 2024 09:39:32 -0600 Subject: [PATCH 389/424] Don't shrink writer buffers. --- src/packet_writer.cpp | 2 +- src/packet_writer.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packet_writer.cpp b/src/packet_writer.cpp index 71fd1a3c0..6acf4fbce 100644 --- a/src/packet_writer.cpp +++ b/src/packet_writer.cpp @@ -59,7 +59,7 @@ BFstatus BFpacketwriter_impl::send(BFheaderinfo info, int data_size = (BF_DTYPE_NBIT(in->dtype)/8) * _nsamples; int npackets = in->shape[0]*in->shape[1]; - if( hdr_size != _last_size || npackets != _last_count ) { + if( hdr_size != _last_size || npackets > _last_count ) { if( _pkt_hdrs ) { ::munlock(_pkt_hdrs, _last_count*_last_size*sizeof(char)); free(_pkt_hdrs); diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index fe3f92c20..901db04c3 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -170,7 +170,7 @@ class UDPPacketSender : public PacketWriterMethod { int data_size, int npackets, int flags=0) { - if( npackets != _last_count ) { + if( npackets > _last_count ) { if( _mmsg ) { ::munlock(_mmsg, sizeof(struct mmsghdr)*_last_count); free(_mmsg); @@ -257,7 +257,7 @@ class UDPVerbsSender : public PacketWriterMethod { int data_size, int npackets, int flags=0) { - if( npackets != _last_count ) { + if( npackets > _last_count ) { if( _mmsg ) { ::munlock(_mmsg, sizeof(struct mmsghdr)*_last_count); free(_mmsg); From 607b20b734b451ab0423301efabb91d21145202a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 18 Apr 2024 15:54:12 -0600 Subject: [PATCH 390/424] Cleanups plus a switch to non-temporal stores for the SSE/AVX branches. --- src/formats/chips.hpp | 28 ++++++++++++++++------------ src/formats/ibeam.hpp | 27 +++++++++++++++++++++------ src/formats/pbeam.hpp | 15 +++++++++++++++ 3 files changed, 52 insertions(+), 18 deletions(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index e293667fa..83d91391a 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -109,17 +109,20 @@ class CHIPSProcessor : virtual public PacketProcessor { //cout << pkt->nchan << endl; for( ; channchan; ++chan ) { #if defined BF_AVX_ENABLED && BF_AVX_ENABLED - _mm256_store_si256(reinterpret_cast<__m256i*>(&out[pkt->src + pkt->nsrc*chan]), - _mm256_loadu_si256(reinterpret_cast(&in[chan]))); + const unaligned256_type* dsrc = (const unaligned256_type*) &in[chan]; + aligned256_type* ddst = (aligned256_type*) &out[pkt->src + pkt->nsrc*chan]; + + __m256 mtemp = _mm256_loadu_si256(dsrc); + _mm256_stream_si256(reinterpret_cast<__m256i*>(ddst), mtemp); #else #if defined BF_SSE_ENABLED && BF_SSE_ENABLED const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan]; aligned128_type* ddst = (aligned128_type*) &out[pkt->src + pkt->nsrc*chan]; - _mm_store_si128(reinterpret_cast<__m128i*>(ddst), - _mm_loadu_si128(reinterpret_cast(dsrc))); - _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_loadu_si128(reinterpret_cast(dsrc+1))); + __m128i mtemp = _mm_loadu_si128(reinterpret_cast(dsrc)); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); + mtemp = _mm_loadu_si128(reinterpret_cast(dsrc+1)); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst+1), mtemp); #else ::memcpy(&out[pkt->src + pkt->nsrc*chan], &in[chan], sizeof(otype)); @@ -138,16 +141,17 @@ class CHIPSProcessor : virtual public PacketProcessor { for( int t=0; t(&aligned_data[src + nsrc*(c + nchan*t)]), - _mm256_setzero_si256()); + aligned256_type* ddst = (aligned156_type*) &aligned_data[src + nsrc*(c + nchan*t)]; + + _m256i mtemp = _mm256_setzero_si256() + _mm256_stream_si256(reinterpret_cast<__m256i*>(ddst), mtemp); #else #if defined BF_SSE_ENABLED && BF_SSE_ENABLED aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nchan*t)]; - _mm_store_si128(reinterpret_cast<__m128i*>(ddst), - _mm_setzero_si128()); - _mm_store_si128(reinterpret_cast<__m128i*>(ddst+1), - _mm_setzero_si128()); + _m128i mtemp = _mm_setzero_si128(); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst+1), mtemp); #else ::memset(&aligned_data[src + nsrc*(c + nchan*t)], 0, sizeof(otype)); diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp index df81a9244..18a76f16d 100644 --- a/src/formats/ibeam.hpp +++ b/src/formats/ibeam.hpp @@ -112,9 +112,17 @@ class IBeamProcessor : virtual public PacketProcessor { int chan, beam; for(chan=0; channchan; ++chan ) { for(beam=0; beam<_nbeam; ++beam) { +#if defined BF_SSE_ENABLED && BF_SSE_ENABLED + const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan*_nbeam + beam]; + aligned128_type* ddst = (aligned128_type*) &out[pkt->src*pkt->nchan*_beam + chan*_nbeam + beam]; + + __m128i mtemp = _mm_loadu_si128(reinterpret_cast(dsrc)); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); +#else ::memcpy(&out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam], &in[chan*_nbeam + beam], sizeof(otype)); //out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam] = in[chan*_nbeam + beam]; +#endif } } } @@ -127,12 +135,19 @@ class IBeamProcessor : virtual public PacketProcessor { typedef aligned128_type otype; otype* __restrict__ aligned_data = (otype*)data; for( int t=0; t(ddst), mtemp); +#else + ::memset(&aligned_data[t*nsrc*nchan*_nbeam + src*nchan*_nbeam + c*_nbeam + b], + 0, sizeof(otype)); +#endif + } + } } } }; diff --git a/src/formats/pbeam.hpp b/src/formats/pbeam.hpp index a7dc966a7..fcfd91683 100644 --- a/src/formats/pbeam.hpp +++ b/src/formats/pbeam.hpp @@ -112,7 +112,15 @@ class PBeamProcessor : virtual public PacketProcessor { int chan; for(chan=0; chan(dsrc)); + _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); +#else ::memcpy(&out[beam_server*nchan + chan], &in[chan], sizeof(otype)); +#endif } } @@ -124,8 +132,15 @@ class PBeamProcessor : virtual public PacketProcessor { typedef aligned128_type otype; otype* __restrict__ aligned_data = (otype*)data; for( int t=0; t(ddst), mtemp); +#else ::memset(&aligned_data[t*nsrc*nchan + src*nchan], 0, nchan*sizeof(otype)); +#endif } } }; From ce766683c95bebfd24f2511d37701cb5f8971fc8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Thu, 18 Apr 2024 16:09:46 -0600 Subject: [PATCH 391/424] Copy real and complex at the same time. --- src/formats/tbn.hpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index 4679eb123..e760db8d1 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -129,13 +129,12 @@ class TBNProcessor : virtual public PacketProcessor { // Note: Using these SSE types allows the compiler to use SSE instructions // However, they require aligned memory (otherwise segfault) - uint8_t const* __restrict__ in = (uint8_t const*)pkt->payload_ptr; - uint8_t* __restrict__ out = (uint8_t* )&obufs[obuf_idx][obuf_offset]; + uint16_t const* __restrict__ in = (uint16_t const*)pkt->payload_ptr; + uint16_t* __restrict__ out = (uint16_t* )&obufs[obuf_idx][obuf_offset]; int samp = 0; for( ; samp<512; ++samp ) { // HACK TESTING - out[samp*pkt->nsrc*2 + pkt->src*2 + 0] = in[2*samp+0]; - out[samp*pkt->nsrc*2 + pkt->src*2 + 1] = in[2*samp+1]; + out[samp*pkt->nsrc + pkt->src] = in[samp]; } } @@ -144,11 +143,10 @@ class TBNProcessor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - uint8_t* __restrict__ aligned_data = (uint8_t*)data; + uint8_t* __restrict__ aligned_data = (uint16_t*)data; for( int t=0; t Date: Thu, 18 Apr 2024 16:26:48 -0600 Subject: [PATCH 392/424] Fixes. --- src/formats/chips.hpp | 4 ++-- src/formats/ibeam.hpp | 2 +- src/formats/tbn.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 83d91391a..0d1e704cc 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -143,13 +143,13 @@ class CHIPSProcessor : virtual public PacketProcessor { #if defined BF_AVX_ENABLED && BF_AVX_ENABLED aligned256_type* ddst = (aligned156_type*) &aligned_data[src + nsrc*(c + nchan*t)]; - _m256i mtemp = _mm256_setzero_si256() + __m256i mtemp = _mm256_setzero_si256() _mm256_stream_si256(reinterpret_cast<__m256i*>(ddst), mtemp); #else #if defined BF_SSE_ENABLED && BF_SSE_ENABLED aligned128_type* ddst = (aligned128_type*) &aligned_data[src + nsrc*(c + nchan*t)]; - _m128i mtemp = _mm_setzero_si128(); + __m128i mtemp = _mm_setzero_si128(); _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); _mm_stream_si128(reinterpret_cast<__m128i*>(ddst+1), mtemp); #else diff --git a/src/formats/ibeam.hpp b/src/formats/ibeam.hpp index 18a76f16d..02c5fd9cb 100644 --- a/src/formats/ibeam.hpp +++ b/src/formats/ibeam.hpp @@ -114,7 +114,7 @@ class IBeamProcessor : virtual public PacketProcessor { for(beam=0; beam<_nbeam; ++beam) { #if defined BF_SSE_ENABLED && BF_SSE_ENABLED const unaligned128_type* dsrc = (const unaligned128_type*) &in[chan*_nbeam + beam]; - aligned128_type* ddst = (aligned128_type*) &out[pkt->src*pkt->nchan*_beam + chan*_nbeam + beam]; + aligned128_type* ddst = (aligned128_type*) &out[pkt->src*pkt->nchan*_nbeam + chan*_nbeam + beam]; __m128i mtemp = _mm_loadu_si128(reinterpret_cast(dsrc)); _mm_stream_si128(reinterpret_cast<__m128i*>(ddst), mtemp); diff --git a/src/formats/tbn.hpp b/src/formats/tbn.hpp index e760db8d1..2a805c41f 100644 --- a/src/formats/tbn.hpp +++ b/src/formats/tbn.hpp @@ -143,7 +143,7 @@ class TBNProcessor : virtual public PacketProcessor { int nsrc, int nchan, int nseq) { - uint8_t* __restrict__ aligned_data = (uint16_t*)data; + uint16_t* __restrict__ aligned_data = (uint16_t*)data; for( int t=0; t Date: Thu, 18 Apr 2024 16:28:39 -0600 Subject: [PATCH 393/424] Another one. --- src/formats/chips.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/chips.hpp b/src/formats/chips.hpp index 0d1e704cc..fd9a371bb 100644 --- a/src/formats/chips.hpp +++ b/src/formats/chips.hpp @@ -112,7 +112,7 @@ class CHIPSProcessor : virtual public PacketProcessor { const unaligned256_type* dsrc = (const unaligned256_type*) &in[chan]; aligned256_type* ddst = (aligned256_type*) &out[pkt->src + pkt->nsrc*chan]; - __m256 mtemp = _mm256_loadu_si256(dsrc); + __m256 mtemp = _mm256_loadu_si256(reinterpret_cast(dsrc)); _mm256_stream_si256(reinterpret_cast<__m256i*>(ddst), mtemp); #else #if defined BF_SSE_ENABLED && BF_SSE_ENABLED From a360f0b92aa975479d6ed7d39f981b3a4c21c1e1 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 19 Apr 2024 09:32:51 -0600 Subject: [PATCH 394/424] Formatting. --- src/formats/snap2.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/formats/snap2.hpp b/src/formats/snap2.hpp index 2b9a85322..a1150727a 100644 --- a/src/formats/snap2.hpp +++ b/src/formats/snap2.hpp @@ -92,7 +92,7 @@ class SNAP2Decoder : virtual public PacketDecoder { int npol_blocks = (be16toh(pkt_hdr->npol_tot) / be16toh(pkt_hdr->npol)); int nchan_blocks = (be16toh(pkt_hdr->nchan_tot) / be16toh(pkt_hdr->nchan)); - pkt->tuning = be32toh(pkt_hdr->chan0); // Abuse this so we can use chan0 to reference channel within pipeline + pkt->tuning = be32toh(pkt_hdr->chan0); // Abuse this so we can use chan0 to reference channel within pipeline pkt->nsrc = npol_blocks * nchan_blocks;// _nsrc; pkt->nchan = be16toh(pkt_hdr->nchan); pkt->chan0 = be32toh(pkt_hdr->chan_block_id) * be16toh(pkt_hdr->nchan); From 3c6c91258af6c3fa0259fcc7c997eca9e11ad658 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 25 Apr 2024 13:54:47 -0400 Subject: [PATCH 395/424] clarify the README for the docs --- docs/Makefile | 2 +- docs/README.rst | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index f7d093d3f..c51d3a6a5 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -29,6 +29,6 @@ generate_python_reference: .PHONY: generate_python_reference generate_cpp_reference: - breathe-apidoc -o source -p bifrost --force ./doxygen/xml/ + breathe-apidoc -o source -p bifrost --force ./doxygen/xml/ rm -rf source/file .PHONY: generate_cpp_reference diff --git a/docs/README.rst b/docs/README.rst index f757e304f..4eec12cb8 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -10,3 +10,10 @@ Inside the `docs` folder, execute `./docker_build_docs.sh`, which will create a container called `bifrost_docs`, then run it, and have it complete the docs-building process for you, outputting the entire html documentation inside `docs/html`. + +If you are not using Docker, ensure that you have "sphinx" and +"doxygen" installed. In the parent directory run "doxygen Doxyfile." +Return to the docs directory, where you can run, for example, +"make singlehtml" where "singlehtml" can be replaced +by the format you wish the docs to be in. + From 774cb481f10d690782dd4b93517b3168c2025fd1 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 25 Apr 2024 14:16:23 -0400 Subject: [PATCH 396/424] include docs on writing packet formats --- docs/source/Cpp-Development.rst | 52 +++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/docs/source/Cpp-Development.rst b/docs/source/Cpp-Development.rst index 21f6a59bd..a0f8147f9 100644 --- a/docs/source/Cpp-Development.rst +++ b/docs/source/Cpp-Development.rst @@ -81,3 +81,55 @@ Create a Ring Buffer and Load Data bfRingSpanRelease(my_read_span); bfRingSequenceClose(my_read_sequence); bfRingDestroy(my_ring); //delete the ring from memory + +Adding New Packet Formats +------------------------ + +A wide variety of packet formats are already included in bifrost. +For simplicity, it is likely preferable to make use of these pre-existing +formats. In the case that this becomes infeasible, here are some of what +is necessary in order to add a new format to bifrost. + +Files to edit: + +1. python/bifrost/packet_capture.py + + * Add set_mypacket to the PacketCaptureCallback class. It will likely look very similar to the set_chips method. + +2. src/bifrost/packet_capture.h + + * This is for ctypesgen. Add a typedef for the sequence callback. This typedef corresponds to the sequence callback used in the packet reader, see the sections on test_udp_io.py and test_disk_io.py for examples of writing the packet reader. + * Also declare the capture callback. + +3. src/formats/format.hpp + + * Add a one-line #include "mypacket.hpp" + +4. src/formats/mypacket.hpp + + * This is the only file that will need to be fully written from scratch. The easiest way to proceed is to copy the most similar existing packet format and modify it accordingly. One will need to make sure that the header is defined properly and that the correct information is going into it, and one will need to make sure that the memcpy operation is properly filling the packet with data. + +5. src/packet_capture.cpp + + * Need to add a call to the packet capture callback. + +6. src/packet_capture.hpp + + * This is where you will spend most of your time. Add your packet capture sequence callback to the BFpacketcapture_callback_impl initialization list. Immediately after the initialization list, add the set_mypacket and get_mypacket methods. + * Add a new class: "BFpacketcapture_mypacket_impl." In the case of simpler packet formats, this may be very close to the already written "BFpacketcapture_chips_impl." It's probably best to start by copying the format that is closest to the format you are writing and modify it. + * In "BFpacketcapture_create," add the format to the first long if-else if statement. This section tells the disk writer the size of the packet to expect. Then add your packet to the second if-else if statement. + +7. src/packet_writer.hpp + + * After the BFpacketwriter_generic_impl, add a class "BFpacketwriter_mypacket_impl. Take care to choose the correct BF\_DTYPE\_???. + * In BFpacketwriter_create, add your packet to the first if-else if statement. Note that nsamples needs to correspond to the number elements in the data portion of the packet. Then add your packet to the third if-else if statement along all the other formats. + +8. test/test_disk_io.py + + * Add a reader for your packet format. This reader will be what is used in the actual code as well. It contains the sequence callback that we declared in the src/bifrost/packet_capture.h file. Note that the header in this sequence callback is the ring header not the packet header. + * You will also need to add a _get_mypacket_data, test_write_mypacket, and test_read_mypacket. + +9. test/test_udp_io.py + + * The udp version of test_disk_io. Once you have written the disk io test, this test is fairly simple to implement, provided you wrote it correctly. + From 7e97eba7569d65a99eec65d6b471c3f339fc34b3 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 3 May 2024 09:00:18 -0600 Subject: [PATCH 397/424] Cleanup whitespace --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index c51d3a6a5..f7d093d3f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -29,6 +29,6 @@ generate_python_reference: .PHONY: generate_python_reference generate_cpp_reference: - breathe-apidoc -o source -p bifrost --force ./doxygen/xml/ + breathe-apidoc -o source -p bifrost --force ./doxygen/xml/ rm -rf source/file .PHONY: generate_cpp_reference From 6445e696eaa885be9a7874de615e6535bd633e6f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 3 May 2024 09:22:42 -0600 Subject: [PATCH 398/424] Formatting. --- docs/source/Cpp-Development.rst | 85 +++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 31 deletions(-) diff --git a/docs/source/Cpp-Development.rst b/docs/source/Cpp-Development.rst index a0f8147f9..061c87ed5 100644 --- a/docs/source/Cpp-Development.rst +++ b/docs/source/Cpp-Development.rst @@ -85,51 +85,74 @@ Create a Ring Buffer and Load Data Adding New Packet Formats ------------------------ -A wide variety of packet formats are already included in bifrost. +A wide variety of packet formats are already included in Bifrost. For simplicity, it is likely preferable to make use of these pre-existing formats. In the case that this becomes infeasible, here are some of what -is necessary in order to add a new format to bifrost. +is necessary in order to add a new format to Bifrost. Files to edit: -1. python/bifrost/packet_capture.py +1. ``python/bifrost/packet_capture.py`` - * Add set_mypacket to the PacketCaptureCallback class. It will likely look very similar to the set_chips method. + * Add ``set_mypacket`` to the ``PacketCaptureCallback`` class. It will likely look + very similar to the ``set_chips`` method. -2. src/bifrost/packet_capture.h +2. ``src/bifrost/packet_capture.h`` - * This is for ctypesgen. Add a typedef for the sequence callback. This typedef corresponds to the sequence callback used in the packet reader, see the sections on test_udp_io.py and test_disk_io.py for examples of writing the packet reader. + * This is for ctypesgen. Add a typedef for the sequence callback. This typedef + corresponds to the sequence callback used in the packet reader, see the sections + on ``test_udp_io.py`` and ``test_disk_io.py`` for examples of writing the packet reader. * Also declare the capture callback. -3. src/formats/format.hpp +3. ``src/formats/format.hpp`` - * Add a one-line #include "mypacket.hpp" + * Add a one-line ``#include "mypacket.hpp"`` -4. src/formats/mypacket.hpp +4. `src/formats/mypacket.hpp` - * This is the only file that will need to be fully written from scratch. The easiest way to proceed is to copy the most similar existing packet format and modify it accordingly. One will need to make sure that the header is defined properly and that the correct information is going into it, and one will need to make sure that the memcpy operation is properly filling the packet with data. + * This is the only file that will need to be fully written from scratch. The + easiest way to proceed is to copy the most similar existing packet format and + modify it accordingly. One will need to make sure that the header is defined + properly and that the correct information is going into it, and one will need + to make sure that the `memcpy` operation is properly filling the packet with + data. -5. src/packet_capture.cpp +5. ``src/packet_capture.cpp`` * Need to add a call to the packet capture callback. -6. src/packet_capture.hpp - - * This is where you will spend most of your time. Add your packet capture sequence callback to the BFpacketcapture_callback_impl initialization list. Immediately after the initialization list, add the set_mypacket and get_mypacket methods. - * Add a new class: "BFpacketcapture_mypacket_impl." In the case of simpler packet formats, this may be very close to the already written "BFpacketcapture_chips_impl." It's probably best to start by copying the format that is closest to the format you are writing and modify it. - * In "BFpacketcapture_create," add the format to the first long if-else if statement. This section tells the disk writer the size of the packet to expect. Then add your packet to the second if-else if statement. - -7. src/packet_writer.hpp - - * After the BFpacketwriter_generic_impl, add a class "BFpacketwriter_mypacket_impl. Take care to choose the correct BF\_DTYPE\_???. - * In BFpacketwriter_create, add your packet to the first if-else if statement. Note that nsamples needs to correspond to the number elements in the data portion of the packet. Then add your packet to the third if-else if statement along all the other formats. - -8. test/test_disk_io.py - - * Add a reader for your packet format. This reader will be what is used in the actual code as well. It contains the sequence callback that we declared in the src/bifrost/packet_capture.h file. Note that the header in this sequence callback is the ring header not the packet header. - * You will also need to add a _get_mypacket_data, test_write_mypacket, and test_read_mypacket. - -9. test/test_udp_io.py - - * The udp version of test_disk_io. Once you have written the disk io test, this test is fairly simple to implement, provided you wrote it correctly. - +6. ``src/packet_capture.hpp`` + + * This is where you will spend most of your time. Add your packet capture sequence + callback to the ``BFpacketcapture_callback_impl`` initialization list. Immediately + after the initialization list, add the ``set_mypacket`` and ``get_mypacket`` methods. + * Add a new class: ``BFpacketcapture_mypacket_impl``. In the case of simpler packet + formats, this may be very close to the already written ``BFpacketcapture_chips_impl``. + It's probably best to start by copying the format that is closest to the format + you are writing and modify it. + * In ``BFpacketcapture_create``, add the format to the first long if-else if statement. + This section tells the disk writer the size of the packet to expect. Then add your + packet to the second if-else if statement. + +7. ``src/packet_writer.hpp`` + + * After the ``BFpacketwriter_generic_impl``, add a class ``BFpacketwriter_mypacket_impl``. + Take care to choose the correct BF\_DTYPE\_???. + * In ``BFpacketwriter_create``, add your packet to the first if-else if statement. + Note that nsamples needs to correspond to the number elements in the data portion + of the packet. Then add your packet to the third if-else if statement along all + the other formats. + +8. ``test/test_disk_io.py`` + + * Add a reader for your packet format. This reader will be what is used in the actual + code as well. It contains the sequence callback that we declared in the ``src/bifrost/packet_capture.h`` + file. Note that the header in this sequence callback is the ring header not the + packet header. + * You will also need to add a ``_get_mypacket_data``, ``test_write_mypacket``, + and ``test_read_mypacket``. + +9. ``test/test_udp_io.py`` + + * The UDP version of ``test_disk_io``. Once you have written the disk I/O test, this + test is fairly simple to implement, provided you wrote it correctly. From 3a2c4aa5e148e011fce65eef776fd13c7ddfe45e Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Fri, 3 May 2024 09:25:14 -0600 Subject: [PATCH 399/424] Also need breathe. --- docs/README.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/README.rst b/docs/README.rst index 4eec12cb8..f56d4f41c 100644 --- a/docs/README.rst +++ b/docs/README.rst @@ -11,9 +11,8 @@ which will create a container called `bifrost_docs`, then run it, and have it complete the docs-building process for you, outputting the entire html documentation inside `docs/html`. -If you are not using Docker, ensure that you have "sphinx" and -"doxygen" installed. In the parent directory run "doxygen Doxyfile." +If you are not using Docker, ensure that you have "sphinx", "breathe", +and "doxygen" installed. In the parent directory run "doxygen Doxyfile." Return to the docs directory, where you can run, for example, "make singlehtml" where "singlehtml" can be replaced by the format you wish the docs to be in. - From 0ae61e7e5d01f820ed4b4ff9b3473e0bb88a979f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:16:34 -0600 Subject: [PATCH 400/424] Added better documentation build environment detection. --- configure.ac | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index 062f52bca..e0304bffb 100644 --- a/configure.ac +++ b/configure.ac @@ -244,7 +244,18 @@ AS_IF([test x$enable_python != xno], [AC_MSG_RESULT([no]) AC_MSG_WARN([python module will not be built])], [AC_MSG_RESULT([yes]) - AC_SUBST(HAVE_PYTHON, 1)])])]) + AC_SUBST(HAVE_PYTHON, 1)]) + AC_MSG_CHECKING([whether $PYTHON as sphinx]) + AS_IF([! ${PYTHON} -c "import sphinx" 2>/dev/null], + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([yes]) + AC_SUBST(HAVE_PYTHON_SPHINX, 1)]) + AC_MSG_CHECKING([whether $PYTHON as breathe]) + AS_IF([! ${PYTHON} -c "import breathe" 2>/dev/null], + [AC_MSG_RESULT([no]) + AC_MSG_WARN([python documentation cannot not be built])], + [AC_MSG_RESULT([yes]) + AC_SUBST(HAVE_PYTHON_BREATHE, 1)])])]) AC_ARG_WITH([pybuild_flags], [AS_HELP_STRING([--with-pybuild-flags], [build flags for python (default='')])], @@ -271,6 +282,7 @@ AS_IF([test x${DOCKER} != xno], # Documentation # +DX_INIT_DOXYGEN([bifrost]) DX_DOT_FEATURE(OFF) DX_HTML_FEATURE(ON) DX_CHM_FEATURE(OFF) @@ -280,9 +292,16 @@ DX_RTF_FEATURE(OFF) DX_XML_FEATURE(OFF) DX_PDF_FEATURE(ON) DX_PS_FEATURE(ON) -DX_INIT_DOXYGEN([bifrost]) -# +AS_IF([test x${DX_DOXYGEN} == x], + [AC_MSG_WARN([missing doxygen, documentation cannot be built])], + [AS_IF([test x${PYTHON} != xno], + [AS_IF([test x${HAVE_PYTHON_SPHINX} != x1], + [AC_MSG_WARN([missing the sphinx module, python documentation cannot not be built])], + [AS_IF([test x${HAVE_PYTHON_BREATHE} != x1], + [AC_MSG_WARN([missing the breathe module, python documentation cannot not be built])])])])]) + + # Version splitting # From b2d56a67ce7fb018f2d6529245de9a616b69b4ca Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:21:29 -0600 Subject: [PATCH 401/424] Consolidate docs toggling flags into two. --- configure.ac | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e0304bffb..80f214f4a 100644 --- a/configure.ac +++ b/configure.ac @@ -293,13 +293,17 @@ DX_XML_FEATURE(OFF) DX_PDF_FEATURE(ON) DX_PS_FEATURE(ON) +AC_SUBST(HAVE_CXX_DOCS, 0) +AC_SUBST(HAVE_PYTHON_DOCS, 0) AS_IF([test x${DX_DOXYGEN} == x], [AC_MSG_WARN([missing doxygen, documentation cannot be built])], - [AS_IF([test x${PYTHON} != xno], + [AC_SUBST(HAVE_CXX_DOCS, 1) + AS_IF([test x${PYTHON} != xno], [AS_IF([test x${HAVE_PYTHON_SPHINX} != x1], [AC_MSG_WARN([missing the sphinx module, python documentation cannot not be built])], [AS_IF([test x${HAVE_PYTHON_BREATHE} != x1], - [AC_MSG_WARN([missing the breathe module, python documentation cannot not be built])])])])]) + [AC_MSG_WARN([missing the breathe module, python documentation cannot not be built])], + [AC_SUBST(HAVE_PYTHON_DOCS, 1)])])])]) # Version splitting From 6efaa739604f9b22c69eb626b7c814addb1b0699 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:28:48 -0600 Subject: [PATCH 402/424] Tie in the doc build flags with the top level Makefile. --- Makefile.in | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index 852b2f951..3ba8ac79b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,8 +7,12 @@ DAT_DIR = share SRC_DIR = src HAVE_PYTHON = @HAVE_PYTHON@ + HAVE_DOCKER = @HAVE_DOCKER@ +CAN_BUILD_CXX_DOCS = @HAVE_CXX_DOCS@ +CAN_BUILD_PYTHON_DOCS = @HAVE_PYTHON_DOCS@ + BIFROST_PYTHON_DIR = python all: libbifrost python @@ -63,8 +67,13 @@ ifeq ($(HAVE_PYTHON),1) endif .PHONY: uninstall -doc: $(INC_DIR)/bifrost/*.h Doxyfile +doc: $(INC_DIR)/bifrost/*.h Doxyfile docs/source/*.rst docs/source/*.py +ifeq ($(CAN_BUILD_CXX_DOCS),1) @DX_DOXYGEN@ Doxyfile +endif +ifeq ($(CAN_BUILD_PYTHON_DOCS),1) + $(MAKE) -C docs singlehtml +endif .PHONY: doc python: libbifrost From 2a1f8fe35008c5ad9ef615637f5a7ab112551edf Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:30:34 -0600 Subject: [PATCH 403/424] Rebuild configure. --- configure | 84 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/configure b/configure index b94108dcb..8fe7920a1 100755 --- a/configure +++ b/configure @@ -663,6 +663,8 @@ MAP_KERNEL_STDCXX PACKAGE_VERSION_MICRO PACKAGE_VERSION_MINOR PACKAGE_VERSION_MAJOR +HAVE_PYTHON_DOCS +HAVE_CXX_DOCS DX_RULES PAPER_SIZE DOXYGEN_PAPER_SIZE @@ -706,6 +708,8 @@ HAVE_DOCKER DOCKER PYINSTALLFLAGS PYBUILDFLAGS +HAVE_PYTHON_BREATHE +HAVE_PYTHON_SPHINX PYTHON3 PYTHON HAVE_PYTHON @@ -1535,7 +1539,7 @@ Optional Features: --disable-python disable building the Python bindings (default=no) --disable-doxygen-doc don't generate any doxygen documentation --enable-doxygen-dot generate graphics for doxygen documentation - --disable-doxygen-man don't generate doxygen manual pages + --enable-doxygen-man generate doxygen manual pages --enable-doxygen-rtf generate doxygen RTF documentation --enable-doxygen-xml generate doxygen XML documentation --enable-doxygen-chm generate doxygen compressed HTML help documentation @@ -22340,6 +22344,32 @@ else $as_nop printf "%s\n" "yes" >&6; } HAVE_PYTHON=1 +fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON as sphinx" >&5 +printf %s "checking whether $PYTHON as sphinx... " >&6; } + if ! ${PYTHON} -c "import sphinx" 2>/dev/null +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + HAVE_PYTHON_SPHINX=1 + +fi + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON as breathe" >&5 +printf %s "checking whether $PYTHON as breathe... " >&6; } + if ! ${PYTHON} -c "import breathe" 2>/dev/null +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: python documentation cannot not be built" >&2;} +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } + HAVE_PYTHON_BREATHE=1 + fi fi fi @@ -22526,15 +22556,6 @@ fi - - - - - - - - - # Files: DX_PROJECT=bifrost @@ -23033,7 +23054,7 @@ esac else $as_nop -DX_FLAG_man=1 +DX_FLAG_man=0 test "$DX_FLAG_doc" = "1" || DX_FLAG_man=0 @@ -24623,7 +24644,46 @@ DX_RULES="${DX_SNIPPET_doc}" #echo DX_ENV=$DX_ENV -# + + + + + + + + + +HAVE_CXX_DOCS=0 + +HAVE_PYTHON_DOCS=0 + +if test x${DX_DOXYGEN} == x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing doxygen, documentation cannot be built" >&5 +printf "%s\n" "$as_me: WARNING: missing doxygen, documentation cannot be built" >&2;} +else $as_nop + HAVE_CXX_DOCS=1 + + if test x${PYTHON} != xno +then : + if test x${HAVE_PYTHON_SPHINX} != x1 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the sphinx module, python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: missing the sphinx module, python documentation cannot not be built" >&2;} +else $as_nop + if test x${HAVE_PYTHON_BREATHE} != x1 +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the breathe module, python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: missing the breathe module, python documentation cannot not be built" >&2;} +else $as_nop + HAVE_PYTHON_DOCS=1 + +fi +fi +fi +fi + + # Version splitting # From 7b52298b54e7e854de35e9a3673291674f9ca4b5 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:45:27 -0600 Subject: [PATCH 404/424] Switch to detecting the scripts that are used to build the python docs. --- configure.ac | 24 +++++++++--------------- docs/{Makefile => Makefile.in} | 0 2 files changed, 9 insertions(+), 15 deletions(-) rename docs/{Makefile => Makefile.in} (100%) diff --git a/configure.ac b/configure.ac index 80f214f4a..59c52ef71 100644 --- a/configure.ac +++ b/configure.ac @@ -244,18 +244,7 @@ AS_IF([test x$enable_python != xno], [AC_MSG_RESULT([no]) AC_MSG_WARN([python module will not be built])], [AC_MSG_RESULT([yes]) - AC_SUBST(HAVE_PYTHON, 1)]) - AC_MSG_CHECKING([whether $PYTHON as sphinx]) - AS_IF([! ${PYTHON} -c "import sphinx" 2>/dev/null], - [AC_MSG_RESULT([no])], - [AC_MSG_RESULT([yes]) - AC_SUBST(HAVE_PYTHON_SPHINX, 1)]) - AC_MSG_CHECKING([whether $PYTHON as breathe]) - AS_IF([! ${PYTHON} -c "import breathe" 2>/dev/null], - [AC_MSG_RESULT([no]) - AC_MSG_WARN([python documentation cannot not be built])], - [AC_MSG_RESULT([yes]) - AC_SUBST(HAVE_PYTHON_BREATHE, 1)])])]) + AC_SUBST(HAVE_PYTHON, 1)])])]) AC_ARG_WITH([pybuild_flags], [AS_HELP_STRING([--with-pybuild-flags], [build flags for python (default='')])], @@ -293,15 +282,20 @@ DX_XML_FEATURE(OFF) DX_PDF_FEATURE(ON) DX_PS_FEATURE(ON) +AS_IF([test x${HAVE_PYTHON} == x1], + [AX_WITH_PROG(PYTHON_SPHINXB, sphinx-build) + AX_WITH_PROG(PYTHON_SPHINXA, sphinx-apidoc) + AX_WITH_PROG(PYTHON_BREATHE, breathe-apidoc)]) + AC_SUBST(HAVE_CXX_DOCS, 0) AC_SUBST(HAVE_PYTHON_DOCS, 0) AS_IF([test x${DX_DOXYGEN} == x], [AC_MSG_WARN([missing doxygen, documentation cannot be built])], [AC_SUBST(HAVE_CXX_DOCS, 1) AS_IF([test x${PYTHON} != xno], - [AS_IF([test x${HAVE_PYTHON_SPHINX} != x1], + [AS_IF([test x${PYTHON_SPHINXB} = x], [AC_MSG_WARN([missing the sphinx module, python documentation cannot not be built])], - [AS_IF([test x${HAVE_PYTHON_BREATHE} != x1], + [AS_IF([test x${PYTHON_BREATHE} = x], [AC_MSG_WARN([missing the breathe module, python documentation cannot not be built])], [AC_SUBST(HAVE_PYTHON_DOCS, 1)])])])]) @@ -370,7 +364,7 @@ AS_IF([test x$STDCXX_IS_SET != x1], CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" -AC_CONFIG_FILES([config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h]) +AC_CONFIG_FILES([config.mk Makefile src/Makefile python/Makefile docs/Makefile share/bifrost.pc src/bifrost/config.h]) AC_OUTPUT diff --git a/docs/Makefile b/docs/Makefile.in similarity index 100% rename from docs/Makefile rename to docs/Makefile.in From 712d3afa0e005bcfeea61d9201986fa8f952f57d Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:45:50 -0600 Subject: [PATCH 405/424] We should make sure this is consistent with the rest of the build. --- docs/Makefile.in | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/Makefile.in b/docs/Makefile.in index f7d093d3f..8d4d63995 100644 --- a/docs/Makefile.in +++ b/docs/Makefile.in @@ -3,7 +3,7 @@ # You can set these variables from the command line. SPHINXOPTS = -SPHINXBUILD = sphinx-build +SPHINXBUILD = @PYTHON_SPHINXB@ SPHINXPROJ = bifrost SOURCEDIR = source BUILDDIR = build @@ -20,15 +20,15 @@ help: @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) generate_python_reference: - sphinx-apidoc -o source -d 5 --force ../python/bifrost/ + @PYTHON_SPHINXA@ -o source -d 5 --force ../python/bifrost/ rm source/modules.rst - sed -i '1s/.*/Python Reference/' source/bifrost.rst - sed -i '2s/.*/================/' source/bifrost.rst - sed -i '1s/.*/Block Library Reference/' source/bifrost.blocks.rst - sed -i '2s/.*/=======================/' source/bifrost.blocks.rst + @SED@ -i '1s/.*/Python Reference/' source/bifrost.rst + @SED@ -i '2s/.*/================/' source/bifrost.rst + @SED@ -i '1s/.*/Block Library Reference/' source/bifrost.blocks.rst + @SED@ -i '2s/.*/=======================/' source/bifrost.blocks.rst .PHONY: generate_python_reference generate_cpp_reference: - breathe-apidoc -o source -p bifrost --force ./doxygen/xml/ + @PYTHON_BREATHE@ -o source -p bifrost --force ./doxygen/xml/ rm -rf source/file .PHONY: generate_cpp_reference From c064bf20a33b4898ccda636f01aa6c5a09985bcf Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:47:30 -0600 Subject: [PATCH 406/424] Rebuild configure. --- configure | 497 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 465 insertions(+), 32 deletions(-) diff --git a/configure b/configure index 8fe7920a1..56939a021 100755 --- a/configure +++ b/configure @@ -665,6 +665,9 @@ PACKAGE_VERSION_MINOR PACKAGE_VERSION_MAJOR HAVE_PYTHON_DOCS HAVE_CXX_DOCS +PYTHON_BREATHE +PYTHON_SPHINXA +PYTHON_SPHINXB DX_RULES PAPER_SIZE DOXYGEN_PAPER_SIZE @@ -708,8 +711,6 @@ HAVE_DOCKER DOCKER PYINSTALLFLAGS PYBUILDFLAGS -HAVE_PYTHON_BREATHE -HAVE_PYTHON_SPHINX PYTHON3 PYTHON HAVE_PYTHON @@ -882,6 +883,9 @@ enable_doxygen_chi enable_doxygen_html enable_doxygen_ps enable_doxygen_pdf +with_sphinx_build +with_sphinx_apidoc +with_breathe_apidoc ' ac_precious_vars='build_alias host_alias @@ -899,7 +903,10 @@ CXXCPP CTAGS PYTHON DOCKER -DOXYGEN_PAPER_SIZE' +DOXYGEN_PAPER_SIZE +PYTHON_SPHINXB +PYTHON_SPHINXA +PYTHON_BREATHE' # Initialize some variables set by options. @@ -1576,6 +1583,12 @@ Optional Packages: --with-pybuild-flags build flags for python (default='') --with-pyinstall-flags install flags for python (default='') --with-docker=[PATH] absolute path to docker executable + --with-sphinx-build=[PATH] + absolute path to sphinx-build executable + --with-sphinx-apidoc=[PATH] + absolute path to sphinx-apidoc executable + --with-breathe-apidoc=[PATH] + absolute path to breathe-apidoc executable Some influential environment variables: CC C compiler command @@ -1595,6 +1608,12 @@ Some influential environment variables: DOCKER Absolute path to docker executable DOXYGEN_PAPER_SIZE a4wide (default), a4, letter, legal or executive + PYTHON_SPHINXB + Absolute path to sphinx-build executable + PYTHON_SPHINXA + Absolute path to sphinx-apidoc executable + PYTHON_BREATHE + Absolute path to breathe-apidoc executable Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -22344,32 +22363,6 @@ else $as_nop printf "%s\n" "yes" >&6; } HAVE_PYTHON=1 -fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON as sphinx" >&5 -printf %s "checking whether $PYTHON as sphinx... " >&6; } - if ! ${PYTHON} -c "import sphinx" 2>/dev/null -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - HAVE_PYTHON_SPHINX=1 - -fi - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON as breathe" >&5 -printf %s "checking whether $PYTHON as breathe... " >&6; } - if ! ${PYTHON} -c "import breathe" 2>/dev/null -then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: python documentation cannot not be built" >&5 -printf "%s\n" "$as_me: WARNING: python documentation cannot not be built" >&2;} -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - HAVE_PYTHON_BREATHE=1 - fi fi fi @@ -24653,6 +24646,445 @@ DX_RULES="${DX_SNIPPET_doc}" +if test x${HAVE_PYTHON} == x1 +then : + + + + + + + + + + + if test -z "$PYTHON_SPHINXB" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sphinx-build executable path has been provided" >&5 +printf %s "checking whether sphinx-build executable path has been provided... " >&6; } + +# Check whether --with-sphinx-build was given. +if test ${with_sphinx_build+y} +then : + withval=$with_sphinx_build; + if test "$withval" != yes && test "$withval" != no +then : + + PYTHON_SPHINXB="$withval" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXB" >&5 +printf "%s\n" "$PYTHON_SPHINXB" >&6; } + +else $as_nop + + PYTHON_SPHINXB="" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + if test "$withval" != no +then : + + # Extract the first word of "sphinx-build", so it can be a program name with args. +set dummy sphinx-build; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_SPHINXB+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_SPHINXB in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_SPHINXB="$PYTHON_SPHINXB" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_SPHINXB="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_SPHINXB=$ac_cv_path_PYTHON_SPHINXB +if test -n "$PYTHON_SPHINXB"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXB" >&5 +printf "%s\n" "$PYTHON_SPHINXB" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + +fi + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + # Extract the first word of "sphinx-build", so it can be a program name with args. +set dummy sphinx-build; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_SPHINXB+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_SPHINXB in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_SPHINXB="$PYTHON_SPHINXB" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_SPHINXB="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_SPHINXB=$ac_cv_path_PYTHON_SPHINXB +if test -n "$PYTHON_SPHINXB"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXB" >&5 +printf "%s\n" "$PYTHON_SPHINXB" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + + +fi + + + + + + + + + + + + + + + + + if test -z "$PYTHON_SPHINXA" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether sphinx-apidoc executable path has been provided" >&5 +printf %s "checking whether sphinx-apidoc executable path has been provided... " >&6; } + +# Check whether --with-sphinx-apidoc was given. +if test ${with_sphinx_apidoc+y} +then : + withval=$with_sphinx_apidoc; + if test "$withval" != yes && test "$withval" != no +then : + + PYTHON_SPHINXA="$withval" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXA" >&5 +printf "%s\n" "$PYTHON_SPHINXA" >&6; } + +else $as_nop + + PYTHON_SPHINXA="" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + if test "$withval" != no +then : + + # Extract the first word of "sphinx-apidoc", so it can be a program name with args. +set dummy sphinx-apidoc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_SPHINXA+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_SPHINXA in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_SPHINXA="$PYTHON_SPHINXA" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_SPHINXA="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_SPHINXA=$ac_cv_path_PYTHON_SPHINXA +if test -n "$PYTHON_SPHINXA"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXA" >&5 +printf "%s\n" "$PYTHON_SPHINXA" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + +fi + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + # Extract the first word of "sphinx-apidoc", so it can be a program name with args. +set dummy sphinx-apidoc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_SPHINXA+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_SPHINXA in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_SPHINXA="$PYTHON_SPHINXA" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_SPHINXA="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_SPHINXA=$ac_cv_path_PYTHON_SPHINXA +if test -n "$PYTHON_SPHINXA"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SPHINXA" >&5 +printf "%s\n" "$PYTHON_SPHINXA" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + + +fi + + + + + + + + + + + + + + + + + if test -z "$PYTHON_BREATHE" +then : + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether breathe-apidoc executable path has been provided" >&5 +printf %s "checking whether breathe-apidoc executable path has been provided... " >&6; } + +# Check whether --with-breathe-apidoc was given. +if test ${with_breathe_apidoc+y} +then : + withval=$with_breathe_apidoc; + if test "$withval" != yes && test "$withval" != no +then : + + PYTHON_BREATHE="$withval" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BREATHE" >&5 +printf "%s\n" "$PYTHON_BREATHE" >&6; } + +else $as_nop + + PYTHON_BREATHE="" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + if test "$withval" != no +then : + + # Extract the first word of "breathe-apidoc", so it can be a program name with args. +set dummy breathe-apidoc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_BREATHE+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_BREATHE in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_BREATHE="$PYTHON_BREATHE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_BREATHE="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_BREATHE=$ac_cv_path_PYTHON_BREATHE +if test -n "$PYTHON_BREATHE"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BREATHE" >&5 +printf "%s\n" "$PYTHON_BREATHE" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + +fi + +else $as_nop + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } + # Extract the first word of "breathe-apidoc", so it can be a program name with args. +set dummy breathe-apidoc; ac_word=$2 +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +printf %s "checking for $ac_word... " >&6; } +if test ${ac_cv_path_PYTHON_BREATHE+y} +then : + printf %s "(cached) " >&6 +else $as_nop + case $PYTHON_BREATHE in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON_BREATHE="$PYTHON_BREATHE" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + case $as_dir in #((( + '') as_dir=./ ;; + */) ;; + *) as_dir=$as_dir/ ;; + esac + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON_BREATHE="$as_dir$ac_word$ac_exec_ext" + printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PYTHON_BREATHE=$ac_cv_path_PYTHON_BREATHE +if test -n "$PYTHON_BREATHE"; then + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON_BREATHE" >&5 +printf "%s\n" "$PYTHON_BREATHE" >&6; } +else + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi + + + +fi + + +fi + + + + + + +fi + HAVE_CXX_DOCS=0 HAVE_PYTHON_DOCS=0 @@ -24666,12 +25098,12 @@ else $as_nop if test x${PYTHON} != xno then : - if test x${HAVE_PYTHON_SPHINX} != x1 + if test x${PYTHON_SPHINXB} = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the sphinx module, python documentation cannot not be built" >&5 printf "%s\n" "$as_me: WARNING: missing the sphinx module, python documentation cannot not be built" >&2;} else $as_nop - if test x${HAVE_PYTHON_BREATHE} != x1 + if test x${PYTHON_BREATHE} = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the breathe module, python documentation cannot not be built" >&5 printf "%s\n" "$as_me: WARNING: missing the breathe module, python documentation cannot not be built" >&2;} @@ -24801,7 +25233,7 @@ fi CXXFLAGS="$CXXFLAGS $lt_prog_compiler_pic_CXX" NVCCFLAGS="$NVCCFLAGS -Xcompiler \"$lt_prog_compiler_pic_CXX\"" -ac_config_files="$ac_config_files config.mk Makefile src/Makefile python/Makefile share/bifrost.pc src/bifrost/config.h" +ac_config_files="$ac_config_files config.mk Makefile src/Makefile python/Makefile docs/Makefile share/bifrost.pc src/bifrost/config.h" cat >confcache <<\_ACEOF @@ -25901,6 +26333,7 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "python/Makefile") CONFIG_FILES="$CONFIG_FILES python/Makefile" ;; + "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "share/bifrost.pc") CONFIG_FILES="$CONFIG_FILES share/bifrost.pc" ;; "src/bifrost/config.h") CONFIG_FILES="$CONFIG_FILES src/bifrost/config.h" ;; From 27f28348a2424433b112fada78744c1815b4a716 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:50:18 -0600 Subject: [PATCH 407/424] More verbose about sphinix components. --- configure.ac | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 59c52ef71..48577c723 100644 --- a/configure.ac +++ b/configure.ac @@ -294,10 +294,12 @@ AS_IF([test x${DX_DOXYGEN} == x], [AC_SUBST(HAVE_CXX_DOCS, 1) AS_IF([test x${PYTHON} != xno], [AS_IF([test x${PYTHON_SPHINXB} = x], - [AC_MSG_WARN([missing the sphinx module, python documentation cannot not be built])], - [AS_IF([test x${PYTHON_BREATHE} = x], - [AC_MSG_WARN([missing the breathe module, python documentation cannot not be built])], - [AC_SUBST(HAVE_PYTHON_DOCS, 1)])])])]) + [AC_MSG_WARN([missing the sphinx-build, python documentation cannot not be built])], + [AS_IF([test x${PYTHON_SPHINXA} = x], + [AC_MSG_WARN([missing the sphinx-apidoc, python documentation cannot not be built])], + [AS_IF([test x${PYTHON_BREATHE} = x], + [AC_MSG_WARN([missing the breathe-apidoc, python documentation cannot not be built])], + [AC_SUBST(HAVE_PYTHON_DOCS, 1)])])])])]) # Version splitting From 9aab2f2f400a3882f7e2acbd36b5e565585aaeae Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 29 May 2024 15:50:35 -0600 Subject: [PATCH 408/424] Rebuild configure. --- configure | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/configure b/configure index 56939a021..158cca187 100755 --- a/configure +++ b/configure @@ -25100,13 +25100,18 @@ else $as_nop then : if test x${PYTHON_SPHINXB} = x then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the sphinx module, python documentation cannot not be built" >&5 -printf "%s\n" "$as_me: WARNING: missing the sphinx module, python documentation cannot not be built" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the sphinx-build, python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: missing the sphinx-build, python documentation cannot not be built" >&2;} +else $as_nop + if test x${PYTHON_SPHINXA} = x +then : + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the sphinx-apidoc, python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: missing the sphinx-apidoc, python documentation cannot not be built" >&2;} else $as_nop if test x${PYTHON_BREATHE} = x then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the breathe module, python documentation cannot not be built" >&5 -printf "%s\n" "$as_me: WARNING: missing the breathe module, python documentation cannot not be built" >&2;} + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: missing the breathe-apidoc, python documentation cannot not be built" >&5 +printf "%s\n" "$as_me: WARNING: missing the breathe-apidoc, python documentation cannot not be built" >&2;} else $as_nop HAVE_PYTHON_DOCS=1 @@ -25114,6 +25119,7 @@ fi fi fi fi +fi # Version splitting From 75edbcfed4de480c6fab348707356162456cddfc Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 16 Jul 2024 11:51:40 -0600 Subject: [PATCH 409/424] Update README.md clarify ctags install --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6bee4c149..6961bdcab 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,8 @@ go to the following [link](https://colab.research.google.com/github/ledatelescop ### C Dependencies +If using Ubuntu or another Debian-based linux distribution: + $ sudo apt-get install exuberant-ctags ### Python Dependencies From df2201124f38f562a95b62439b09496ad5ff1d48 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 16 Jul 2024 11:53:51 -0600 Subject: [PATCH 410/424] Update README.md Further clarification on ctags install --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6961bdcab..16d688790 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,8 @@ If using Ubuntu or another Debian-based linux distribution: $ sudo apt-get install exuberant-ctags +Otherwise check https://ctags.sourceforge.net/ for install instructions. + ### Python Dependencies * numpy From 1376fbbd750b2dcfa63a9c89b19469f15247d5d3 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Tue, 16 Jul 2024 12:01:43 -0600 Subject: [PATCH 411/424] Update README.md Clarifications to docs instructions --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 16d688790..558d14eaa 100644 --- a/README.md +++ b/README.md @@ -175,8 +175,17 @@ your machine. ### Building the Docs from Scratch -Install sphinx and breathe using pip, and also install Doxygen. +Install breathe using pip: + $ python -m pip install breathe sphinx + +Also install Doxygen using your package manager. +In Ubuntu, for example: + + $ sudo apt install Doxygen + +Otherwise check https://www.doxygen.nl/ for Doxygen install instructions. + Doxygen documentation can be generated by running: $ make doc From 23530b8b648fe3cdeb59f62f04ef17abf8af33d8 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 16 Jul 2024 12:13:08 -0600 Subject: [PATCH 412/424] Adjust commands to match. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 558d14eaa..955757048 100644 --- a/README.md +++ b/README.md @@ -177,12 +177,12 @@ your machine. Install breathe using pip: - $ python -m pip install breathe sphinx + $ sudo pip install breathe sphinx Also install Doxygen using your package manager. In Ubuntu, for example: - $ sudo apt install Doxygen + $ sudo apt-get install doxygen Otherwise check https://www.doxygen.nl/ for Doxygen install instructions. From 89c6d74b964b1072001769f6281f65ed3120cd3a Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 16 Jul 2024 12:16:19 -0600 Subject: [PATCH 413/424] See if numpy<2 helps. --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9386f2708..64ae9a060 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,7 +57,7 @@ jobs: - name: "Software Install - Python" run: python -m pip install \ setuptools \ - numpy \ + "numpy<2" \ matplotlib \ contextlib2 \ simplejson \ From b0a73e8914f0f7800e1108411f0cc6582a4cd969 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Tue, 16 Jul 2024 14:37:22 -0600 Subject: [PATCH 414/424] These need memory binding as well. --- src/packet_capture.hpp | 35 ++++++++++++++++++----------------- src/packet_writer.hpp | 27 ++++++++++++++------------- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/packet_capture.hpp b/src/packet_capture.hpp index d077485c4..077cb8a2c 100644 --- a/src/packet_capture.hpp +++ b/src/packet_capture.hpp @@ -147,15 +147,16 @@ class AlignedBuffer { inline T const& operator[](size_t i) const { return _buf[i]; } }; -class PacketCaptureMethod { +class PacketCaptureMethod: public BoundThread { protected: int _fd; size_t _pkt_size_max; - AlignedBuffer _buf; + AlignedBuffer _buf; BFiomethod _io_method; + int _core; public: - PacketCaptureMethod(int fd, size_t pkt_size_max=9000, BFiomethod io_method=BF_IO_GENERIC) - : _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max), _io_method(io_method) {} + PacketCaptureMethod(int fd, size_t pkt_size_max=9000, BFiomethod io_method=BF_IO_GENERIC, int core=-1) + : BoundThread(core), _fd(fd), _pkt_size_max(pkt_size_max), _buf(pkt_size_max), _io_method(io_method), _core(core) {} virtual int recv_packet(uint8_t** pkt_ptr, int flags=0) { return 0; } @@ -168,8 +169,8 @@ class PacketCaptureMethod { class DiskPacketReader : public PacketCaptureMethod { public: - DiskPacketReader(int fd, size_t pkt_size_max=9000) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_DISK) {} + DiskPacketReader(int fd, size_t pkt_size_max=9000, int core=-1) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_DISK, core) {} int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = &_buf[0]; return ::read(_fd, &_buf[0], _buf.size()); @@ -234,8 +235,8 @@ class UDPPacketReceiver : public PacketCaptureMethod { VMAReceiver _vma; #endif public: - UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP) + UDPPacketReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE, int core=-1) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_UDP, core) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -262,8 +263,8 @@ class UDPPacketSniffer : public PacketCaptureMethod { VMAReceiver _vma; #endif public: - UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_SNIFFER) + UDPPacketSniffer(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE, int core=-1) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_SNIFFER, core) #if BF_VMA_ENABLED , _vma(fd) #endif @@ -292,8 +293,8 @@ class UDPPacketSniffer : public PacketCaptureMethod { class UDPVerbsReceiver : public PacketCaptureMethod { Verbs _ibv; public: - UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE) - : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS), _ibv(fd, pkt_size_max) {} + UDPVerbsReceiver(int fd, size_t pkt_size_max=JUMBO_FRAME_SIZE, int core=-1) + : PacketCaptureMethod(fd, pkt_size_max, BF_IO_VERBS, core), _ibv(fd, pkt_size_max) {} inline int recv_packet(uint8_t** pkt_ptr, int flags=0) { *pkt_ptr = 0; return _ibv.recv_packet(pkt_ptr, flags); @@ -328,7 +329,7 @@ class PacketCaptureThread : public BoundThread { CAPTURE_NO_DATA = 1 << 3, CAPTURE_ERROR = 1 << 4 }; - PacketCaptureThread(PacketCaptureMethod* method, int nsrc, int core=0) + PacketCaptureThread(PacketCaptureMethod* method, int nsrc, int core=-1) : BoundThread(core), _method(method), _src_stats(nsrc), _have_pkt(false), _core(core) { this->reset_stats(); @@ -1446,14 +1447,14 @@ BFstatus BFpacketcapture_create(BFpacketcapture* obj, PacketCaptureMethod* method; if( backend == BF_IO_DISK ) { - method = new DiskPacketReader(fd, max_payload_size); + method = new DiskPacketReader(fd, max_payload_size, core); } else if( backend == BF_IO_UDP ) { - method = new UDPPacketReceiver(fd, max_payload_size); + method = new UDPPacketReceiver(fd, max_payload_size, core); } else if( backend == BF_IO_SNIFFER ) { - method = new UDPPacketSniffer(fd, max_payload_size); + method = new UDPPacketSniffer(fd, max_payload_size, core); #if defined BF_VERBS_ENABLED && BF_VERBS_ENABLED } else if( backend == BF_IO_VERBS ) { - method = new UDPVerbsReceiver(fd, max_payload_size); + method = new UDPVerbsReceiver(fd, max_payload_size, core); #endif } else { return BF_STATUS_UNSUPPORTED; diff --git a/src/packet_writer.hpp b/src/packet_writer.hpp index 03bd6d704..e5cd41c92 100644 --- a/src/packet_writer.hpp +++ b/src/packet_writer.hpp @@ -92,14 +92,15 @@ class RateLimiter { } }; -class PacketWriterMethod { +class PacketWriterMethod: public BoundThread { protected: int _fd; size_t _max_burst_size; RateLimiter _limiter; + int _core; public: - PacketWriterMethod(int fd, size_t max_burst_size=BF_SEND_NPKTBURST) - : _fd(fd), _max_burst_size(max_burst_size), _limiter(0) {} + PacketWriterMethod(int fd, size_t max_burst_size=BF_SEND_NPKTBURST, int core=-1) + : BoundThread(core), _fd(fd), _max_burst_size(max_burst_size), _limiter(0), _core(core) {} virtual ssize_t send_packets(char* hdrs, int hdr_size, char* data, @@ -116,8 +117,8 @@ class PacketWriterMethod { class DiskPacketWriter : public PacketWriterMethod { public: - DiskPacketWriter(int fd, size_t max_burst_size=BF_SEND_NPKTBURST) - : PacketWriterMethod(fd, max_burst_size) {} + DiskPacketWriter(int fd, size_t max_burst_size=BF_SEND_NPKTBURST, int core=-1) + : PacketWriterMethod(fd, max_burst_size, core) {} ssize_t send_packets(char* hdrs, int hdr_size, char* data, @@ -154,8 +155,8 @@ class UDPPacketSender : public PacketWriterMethod { mmsghdr* _mmsg; iovec* _iovs; public: - UDPPacketSender(int fd, size_t max_burst_size=BF_SEND_NPKTBURST) - : PacketWriterMethod(fd, max_burst_size), _last_count(0), _mmsg(NULL), _iovs(NULL) {} + UDPPacketSender(int fd, size_t max_burst_size=BF_SEND_NPKTBURST, int core=-1) + : PacketWriterMethod(fd, max_burst_size, core), _last_count(0), _mmsg(NULL), _iovs(NULL) {} ~UDPPacketSender() { if( _mmsg ) { free(_mmsg); @@ -240,8 +241,8 @@ class UDPVerbsSender : public PacketWriterMethod { mmsghdr* _mmsg; iovec* _iovs; public: - UDPVerbsSender(int fd, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST) - : PacketWriterMethod(fd, max_burst_size), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), + UDPVerbsSender(int fd, size_t max_burst_size=BF_VERBS_SEND_NPKTBURST, int core=-1) + : PacketWriterMethod(fd, max_burst_size, core), _ibv(fd, JUMBO_FRAME_SIZE), _last_size(0), _last_count(0), _mmsg(NULL), _iovs(NULL) {} ~UDPVerbsSender() { if( _mmsg ) { @@ -330,7 +331,7 @@ class PacketWriterThread : public BoundThread { int _core; public: - PacketWriterThread(PacketWriterMethod* method, int core=0) + PacketWriterThread(PacketWriterMethod* method, int core=-1) : BoundThread(core), _method(method), _core(core) { this->reset_stats(); } @@ -614,12 +615,12 @@ BFstatus BFpacketwriter_create(BFpacketwriter* obj, PacketWriterMethod* method; if( backend == BF_IO_DISK ) { - method = new DiskPacketWriter(fd); + method = new DiskPacketWriter(fd, core=core); } else if( backend == BF_IO_UDP ) { - method = new UDPPacketSender(fd); + method = new UDPPacketSender(fd, core=core); #if defined BF_VERBS_ENABLED && BF_VERBS_ENABLED } else if( backend == BF_IO_VERBS ) { - method = new UDPVerbsSender(fd); + method = new UDPVerbsSender(fd, core=core); #endif } else { return BF_STATUS_UNSUPPORTED; From d4e952ee61e79c80face2dfc47692c2f871cba11 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 18 Jul 2024 14:08:01 -0600 Subject: [PATCH 415/424] include CUDA version info in docs --- README.md | 6 +++++ docs/source/Getting-started-guide.rst | 33 +++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 955757048..1b62c5154 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,12 @@ print "All done" **For a quick demo which you can run in-browser without installation, go to the following [link](https://colab.research.google.com/github/ledatelescope/bifrost/blob/master/BifrostDemo.ipynb).** +### CUDA + +CUDA is available at [link](https://developer.nvidia.com/cuda-downloads). You can check +[link](http://ledatelescope.github.io/bifrost/Getting-started-guide.html) to see +which versions of the CUDA toolkit have been confirmed to work with Bifrost. + ### C Dependencies If using Ubuntu or another Debian-based linux distribution: diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index 7fb0fd7ad..efdfc6965 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -58,8 +58,37 @@ try out a CPU-only version of Bifrost. Then, once you have that first experience, you can come back here for a speedup. If you are ready to work with a GPU, you will want to get the newest -`CUDA toolkit `__. Follow -the operating system-specific instructions to install. +`CUDA toolkit `__. Follow +the operating system-specific instructions to install. Note +the table below indicating what CUDA versions have been tested with +Bifrost and confirmed to be working. + +.. csv-table:: + :header: "OS","Linux Kernel","Driver Verson","GPU","Toolkit","Status" + :widths: 15,18,12,18,12,35 + + "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.0.3","Working" + "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.1.1","Working" + "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.2.2","Likely working" + "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.3.1","Working" + "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.4.4","Likely Working" + "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.5.2","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" + "Ubuntu 20.04","5.4.0-186-generic","495.29.05","Quadro K2200","11.5.2","Likely Working" + "Ubuntu 18.04","4.15.0-88-generic","510.85.02","A4000","11.6.124","Working" + "Ubuntu 18.04","4.15.0-88-generic","510.85.02","RTX 2080Ti","11.6.124","Working" + "Ubuntu 20.04","4.4.0-174-generic","525.147.05","Titan RTX","11.6.55","Working" + "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","11.8.0","Won't Install CUDA" + "Ubuntu 20.04","5.4.0-186-generic","520.61.05","Quadro K2200","11.8.0","Likely Working" + "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.0.0","Likely Working" + "Ubuntu 20.04","5.4.0-147-generic","525.125.06","A5000","12.0.140","Working" + "Ubuntu 20.04","5.4.0-144-generic","525.125.06","A5000","12.0.140","Working" + "Ubuntu 20.04","5.4.0-144-generic","525.147.05","A4000","12.0.140","Working" + "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.1.0","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" + "Debian 12","6.1.0-21-amd64","530.30.02","Quadro K2200","12.1.1","Likely Working" + "Debian 12","6.1.0-21-amd64","535.104.05","Quadro K2200","12.2.2","FFT bug: zeroed out data" + "Debian 12","6.1.0-21-amd64","545.23.08","Quadro K2200","12.3.2","Likely Working" + "Debian 12","6.1.0-21-amd64","550.54.15","Quadro K2200","12.4.1","Likely Working" + "Ubuntu 22.04","5.15.0-106-generic","555.42.06","GTX 980","12.5","Working" Other Dependencies ^^^^^^^^^^^^^^^^^^ From a6b5a4517a8b4f77ffe184c4ca2c6186dba66457 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 18 Jul 2024 14:09:48 -0600 Subject: [PATCH 416/424] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b62c5154..5092fd461 100644 --- a/README.md +++ b/README.md @@ -97,9 +97,9 @@ go to the following [link](https://colab.research.google.com/github/ledatelescop ### CUDA -CUDA is available at [link](https://developer.nvidia.com/cuda-downloads). You can check -[link](http://ledatelescope.github.io/bifrost/Getting-started-guide.html) to see -which versions of the CUDA toolkit have been confirmed to work with Bifrost. +CUDA is available at https://developer.nvidia.com/cuda-downloads. You can check the +[Getting Started section](http://ledatelescope.github.io/bifrost/Getting-started-guide.html) +of the docs to see which versions of the CUDA toolkit have been confirmed to work with Bifrost. ### C Dependencies From 3d0a8c147f728fc263a3f032fd33725303e786ae Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Thu, 18 Jul 2024 14:10:25 -0600 Subject: [PATCH 417/424] Update README.md wording --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5092fd461..feda6c0d3 100644 --- a/README.md +++ b/README.md @@ -98,8 +98,8 @@ go to the following [link](https://colab.research.google.com/github/ledatelescop ### CUDA CUDA is available at https://developer.nvidia.com/cuda-downloads. You can check the -[Getting Started section](http://ledatelescope.github.io/bifrost/Getting-started-guide.html) -of the docs to see which versions of the CUDA toolkit have been confirmed to work with Bifrost. +["Getting Started guide"](http://ledatelescope.github.io/bifrost/Getting-started-guide.html) +in the docs to see which versions of the CUDA toolkit have been confirmed to work with Bifrost. ### C Dependencies From 61fbe382ad5fe54672a9a7da724098217fdc596f Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 22 Jul 2024 11:18:18 -0600 Subject: [PATCH 418/424] Upgrade 11.2.2 to 'working'. --- docs/source/Getting-started-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index efdfc6965..54d7e0d51 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -69,7 +69,7 @@ Bifrost and confirmed to be working. "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.0.3","Working" "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.1.1","Working" - "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.2.2","Likely working" + "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.2.2","Working" "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.3.1","Working" "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.4.4","Likely Working" "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.5.2","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" From a28591576a8cff61fa4cb13f071ae82547817b96 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 22 Jul 2024 11:19:17 -0600 Subject: [PATCH 419/424] Typo. --- docs/source/Getting-started-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index 54d7e0d51..b3e0d0508 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -64,7 +64,7 @@ the table below indicating what CUDA versions have been tested with Bifrost and confirmed to be working. .. csv-table:: - :header: "OS","Linux Kernel","Driver Verson","GPU","Toolkit","Status" + :header: "OS","Linux Kernel","Driver Version","GPU","Toolkit","Status" :widths: 15,18,12,18,12,35 "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.0.3","Working" From bb055d27f1efa83e5e6943685388621eea0ff2eb Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 22 Jul 2024 11:27:33 -0600 Subject: [PATCH 420/424] Wording. --- docs/source/Getting-started-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index b3e0d0508..31a979598 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -77,7 +77,7 @@ Bifrost and confirmed to be working. "Ubuntu 18.04","4.15.0-88-generic","510.85.02","A4000","11.6.124","Working" "Ubuntu 18.04","4.15.0-88-generic","510.85.02","RTX 2080Ti","11.6.124","Working" "Ubuntu 20.04","4.4.0-174-generic","525.147.05","Titan RTX","11.6.55","Working" - "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","11.8.0","Won't Install CUDA" + "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","11.8.0","CUDA Install Failed" "Ubuntu 20.04","5.4.0-186-generic","520.61.05","Quadro K2200","11.8.0","Likely Working" "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.0.0","Likely Working" "Ubuntu 20.04","5.4.0-147-generic","525.125.06","A5000","12.0.140","Working" From 9baceaaf594fff1f2cf7d286c636d94a0f27f8a0 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 22 Jul 2024 11:36:05 -0600 Subject: [PATCH 421/424] likely working -> working; Issue warning about CUDA 11.8. --- docs/source/Getting-started-guide.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index 31a979598..63575bcc2 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -71,23 +71,23 @@ Bifrost and confirmed to be working. "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.1.1","Working" "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.2.2","Working" "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.3.1","Working" - "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.4.4","Likely Working" + "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.4.4","Working" "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.5.2","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" - "Ubuntu 20.04","5.4.0-186-generic","495.29.05","Quadro K2200","11.5.2","Likely Working" + "Ubuntu 20.04","5.4.0-186-generic","495.29.05","Quadro K2200","11.5.2","Working" "Ubuntu 18.04","4.15.0-88-generic","510.85.02","A4000","11.6.124","Working" "Ubuntu 18.04","4.15.0-88-generic","510.85.02","RTX 2080Ti","11.6.124","Working" "Ubuntu 20.04","4.4.0-174-generic","525.147.05","Titan RTX","11.6.55","Working" "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","11.8.0","CUDA Install Failed" - "Ubuntu 20.04","5.4.0-186-generic","520.61.05","Quadro K2200","11.8.0","Likely Working" - "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.0.0","Likely Working" + "Ubuntu 20.04","5.4.0-186-generic","520.61.05","Quadro K2200","11.8.0","Known FIR and FFT Problems" + "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.0.0","Working" "Ubuntu 20.04","5.4.0-147-generic","525.125.06","A5000","12.0.140","Working" "Ubuntu 20.04","5.4.0-144-generic","525.125.06","A5000","12.0.140","Working" "Ubuntu 20.04","5.4.0-144-generic","525.147.05","A4000","12.0.140","Working" "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.1.0","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" - "Debian 12","6.1.0-21-amd64","530.30.02","Quadro K2200","12.1.1","Likely Working" + "Debian 12","6.1.0-21-amd64","530.30.02","Quadro K2200","12.1.1","Working" "Debian 12","6.1.0-21-amd64","535.104.05","Quadro K2200","12.2.2","FFT bug: zeroed out data" - "Debian 12","6.1.0-21-amd64","545.23.08","Quadro K2200","12.3.2","Likely Working" - "Debian 12","6.1.0-21-amd64","550.54.15","Quadro K2200","12.4.1","Likely Working" + "Debian 12","6.1.0-21-amd64","545.23.08","Quadro K2200","12.3.2","Working" + "Debian 12","6.1.0-21-amd64","550.54.15","Quadro K2200","12.4.1","Working" "Ubuntu 22.04","5.15.0-106-generic","555.42.06","GTX 980","12.5","Working" Other Dependencies From ac9b7ab31ba02333bf87d23cd5390fc8c0b28267 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Mon, 22 Jul 2024 14:38:18 -0600 Subject: [PATCH 422/424] Remove entries that are install/version mis-match problems. --- docs/source/Getting-started-guide.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index 63575bcc2..4f24cba3b 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -72,18 +72,15 @@ Bifrost and confirmed to be working. "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.2.2","Working" "Ubuntu 20.04","5.4.0-177-generic","520.61.05","RTX 2080Ti","11.3.1","Working" "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.4.4","Working" - "Ubuntu 20.04","5.4.0-186-generic","470.239.06","Quadro K2200","11.5.2","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" "Ubuntu 20.04","5.4.0-186-generic","495.29.05","Quadro K2200","11.5.2","Working" "Ubuntu 18.04","4.15.0-88-generic","510.85.02","A4000","11.6.124","Working" "Ubuntu 18.04","4.15.0-88-generic","510.85.02","RTX 2080Ti","11.6.124","Working" "Ubuntu 20.04","4.4.0-174-generic","525.147.05","Titan RTX","11.6.55","Working" - "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","11.8.0","CUDA Install Failed" "Ubuntu 20.04","5.4.0-186-generic","520.61.05","Quadro K2200","11.8.0","Known FIR and FFT Problems" "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.0.0","Working" "Ubuntu 20.04","5.4.0-147-generic","525.125.06","A5000","12.0.140","Working" "Ubuntu 20.04","5.4.0-144-generic","525.125.06","A5000","12.0.140","Working" "Ubuntu 20.04","5.4.0-144-generic","525.147.05","A4000","12.0.140","Working" - "Debian 12","6.1.0-21-amd64","525.147.05 ","Quadro K2200","12.1.0","CUDA_ERROR_UNSUPPORTED_PTX_VERSION" "Debian 12","6.1.0-21-amd64","530.30.02","Quadro K2200","12.1.1","Working" "Debian 12","6.1.0-21-amd64","535.104.05","Quadro K2200","12.2.2","FFT bug: zeroed out data" "Debian 12","6.1.0-21-amd64","545.23.08","Quadro K2200","12.3.2","Working" From 70eb3395b8c7f1c8787e1867e49ba32b14b35b38 Mon Sep 17 00:00:00 2001 From: jaycedowell Date: Wed, 24 Jul 2024 10:00:51 -0600 Subject: [PATCH 423/424] More wording. --- docs/source/Getting-started-guide.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index 4f24cba3b..a12cd80bb 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -59,9 +59,12 @@ experience, you can come back here for a speedup. If you are ready to work with a GPU, you will want to get the newest `CUDA toolkit `__. Follow -the operating system-specific instructions to install. Note -the table below indicating what CUDA versions have been tested with -Bifrost and confirmed to be working. +the operating system-specific instructions to install. Be sure to install a +kernel driver that works with the version of toolkit that you are using since +version mismatches can lead to runtime errors. + +The table below indicates which CUDA toolkit and kernel driver versions Bifrost +has been tested against. .. csv-table:: :header: "OS","Linux Kernel","Driver Version","GPU","Toolkit","Status" From 3adca06ce33b6ed46d9dba3dbd9f676e9f87da40 Mon Sep 17 00:00:00 2001 From: Sarah Chastain Date: Mon, 19 Aug 2024 10:15:05 -0600 Subject: [PATCH 424/424] Update Getting-started-guide.rst Update python requirements --- docs/source/Getting-started-guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Getting-started-guide.rst b/docs/source/Getting-started-guide.rst index a12cd80bb..c8189cf31 100644 --- a/docs/source/Getting-started-guide.rst +++ b/docs/source/Getting-started-guide.rst @@ -21,7 +21,7 @@ but higher ones should also work. Python dependencies ~~~~~~~~~~~~~~~~~~~ -*Bifrost is compatible with both in Python 2.7. and Python 3.x.* +*Bifrost is compatible with Python >3.6.* `pip `__ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^