diff options
author | Philip Balister <philip@opensdr.com> | 2010-04-01 12:44:19 +0000 |
---|---|---|
committer | Philip Balister <philip@opensdr.com> | 2010-04-01 12:44:19 +0000 |
commit | 93572731923e43bbb34a12db41170e56376ab03b (patch) | |
tree | a46c53d1695a211dac39e46abf60a8f517e8d287 /host/lib/transport | |
parent | 930755fce1e5d22a5ede0459dccd6c9501fc642c (diff) | |
parent | 03be4d0673c5e0f597db7d27f535956a591bbeb7 (diff) | |
download | uhd-93572731923e43bbb34a12db41170e56376ab03b.tar.gz uhd-93572731923e43bbb34a12db41170e56376ab03b.tar.bz2 uhd-93572731923e43bbb34a12db41170e56376ab03b.zip |
Merge branch 'usrp_e' of git@ettus.sourcerepo.com:ettus/uhd into usrp_e
Diffstat (limited to 'host/lib/transport')
-rwxr-xr-x | host/lib/transport/gen_vrt.py | 206 | ||||
-rw-r--r-- | host/lib/transport/if_addrs.cpp | 109 | ||||
-rw-r--r-- | host/lib/transport/udp_simple.cpp | 1 | ||||
-rw-r--r-- | host/lib/transport/udp_zero_copy_asio.cpp | 3 | ||||
-rw-r--r-- | host/lib/transport/vrt.cpp | 550 |
5 files changed, 812 insertions, 57 deletions
diff --git a/host/lib/transport/gen_vrt.py b/host/lib/transport/gen_vrt.py new file mode 100755 index 000000000..918de3ad7 --- /dev/null +++ b/host/lib/transport/gen_vrt.py @@ -0,0 +1,206 @@ +#!/usr/bin/env python +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +""" +The vrt packer/unpacker code generator: + +This script will generate the pack and unpack routines that convert +metatdata into vrt headers and vrt headers into metadata. + +The generated code infers jump tables to speed-up the parsing time. +""" + +TMPL_TEXT = """ +#import time + +######################################################################## +## setup predicates +######################################################################## +#set $sid_p = 0b00001 +#set $cid_p = 0b00010 +#set $tsi_p = 0b00100 +#set $tsf_p = 0b01000 +#set $tlr_p = 0b10000 + +/*********************************************************************** + * This file was generated by $file on $time.strftime("%c") + **********************************************************************/ + +\#include <uhd/transport/vrt.hpp> +\#include <boost/asio.hpp> //endianness conversion +\#include <stdexcept> + +using namespace uhd; +using namespace uhd::transport; + +void vrt::pack( + const tx_metadata_t &metadata, //input + boost::uint32_t *header_buff, //output + size_t &num_header_words32, //output + size_t num_payload_words32, //input + size_t &num_packet_words32, //output + size_t packet_count //input +){ + boost::uint32_t vrt_hdr_flags; + + boost::uint8_t pred = 0; + if (metadata.has_stream_id) pred |= $hex($sid_p); + if (metadata.has_time_spec) pred |= $hex($tsi_p | $tsf_p); + + switch(pred){ + #for $pred in range(2**5) + case $pred: + #set $num_header_words = 1 + #set $flags = 0 + ########## Stream ID ########## + #if $pred & $sid_p + header_buff[$num_header_words] = htonl(metadata.stream_id); + #set $num_header_words += 1 + #set $flags |= (0x1 << 28); + #end if + ########## Class ID ########## + #if $pred & $cid_p + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + #set $flags |= (0x1 << 27); + #end if + ########## Integer Time ########## + #if $pred & $tsi_p + header_buff[$num_header_words] = htonl(metadata.time_spec.secs); + #set $num_header_words += 1 + #set $flags |= (0x3 << 22); + #end if + ########## Fractional Time ########## + #if $pred & $tsf_p + header_buff[$num_header_words] = htonl(0); + #set $num_header_words += 1 + header_buff[$num_header_words] = htonl(metadata.time_spec.ticks); + #set $num_header_words += 1 + #set $flags |= (0x1 << 20); + #end if + ########## Trailer ########## + #if $pred & $tlr_p + #set $flags |= (0x1 << 26); + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if + ########## Variables ########## + num_header_words32 = $num_header_words; + num_packet_words32 = $($num_header_words + $num_trailer_words) + num_payload_words32; + vrt_hdr_flags = $hex($flags); + break; + #end for + } + + //set the burst flags + if (metadata.start_of_burst) vrt_hdr_flags |= $hex(0x1 << 25); + if (metadata.end_of_burst) vrt_hdr_flags |= $hex(0x1 << 24); + + //fill in complete header word + header_buff[0] = htonl(vrt_hdr_flags | + ((packet_count & 0xf) << 16) | + (num_packet_words32 & 0xffff) + ); +} + +void vrt::unpack( + rx_metadata_t &metadata, //output + const boost::uint32_t *header_buff, //input + size_t &num_header_words32, //output + size_t &num_payload_words32, //output + size_t num_packet_words32, //input + size_t &packet_count //output +){ + //clear the metadata + metadata = rx_metadata_t(); + + //extract vrt header + boost::uint32_t vrt_hdr_word = ntohl(header_buff[0]); + size_t packet_words32 = vrt_hdr_word & 0xffff; + packet_count = (vrt_hdr_word >> 16) & 0xf; + + //failure cases + if (packet_words32 == 0 or num_packet_words32 < packet_words32) + throw std::runtime_error("bad vrt header or packet fragment"); + if (vrt_hdr_word & (0x7 << 29)) + throw std::runtime_error("unsupported vrt packet type"); + + boost::uint8_t pred = 0; + if(vrt_hdr_word & $hex(0x1 << 28)) pred |= $hex($sid_p); + if(vrt_hdr_word & $hex(0x1 << 27)) pred |= $hex($cid_p); + if(vrt_hdr_word & $hex(0x3 << 22)) pred |= $hex($tsi_p); + if(vrt_hdr_word & $hex(0x3 << 20)) pred |= $hex($tsf_p); + if(vrt_hdr_word & $hex(0x1 << 26)) pred |= $hex($tlr_p); + + switch(pred){ + #for $pred in range(2**5) + case $pred: + #set $set_has_time_spec = False + #set $num_header_words = 1 + ########## Stream ID ########## + #if $pred & $sid_p + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Class ID ########## + #if $pred & $cid_p + #set $num_header_words += 1 + #set $num_header_words += 1 + #end if + ########## Integer Time ########## + #if $pred & $tsi_p + metadata.has_time_spec = true; + #set $set_has_time_spec = True + metadata.time_spec.secs = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Fractional Time ########## + #if $pred & $tsf_p + #if not $set_has_time_spec + metadata.has_time_spec = true; + #set $set_has_time_spec = True + #end if + #set $num_header_words += 1 + metadata.time_spec.ticks = ntohl(header_buff[$num_header_words]); + #set $num_header_words += 1 + #end if + ########## Trailer ########## + #if $pred & $tlr_p + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if + ########## Variables ########## + num_header_words32 = $num_header_words; + num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words); + break; + #end for + } +} +""" + +from Cheetah import Template +def parse_str(_tmpl_text, **kwargs): return str(Template.Template(_tmpl_text, kwargs)) + +if __name__ == '__main__': + from Cheetah import Template + print parse_str(TMPL_TEXT, file=__file__) diff --git a/host/lib/transport/if_addrs.cpp b/host/lib/transport/if_addrs.cpp new file mode 100644 index 000000000..5c8c8a176 --- /dev/null +++ b/host/lib/transport/if_addrs.cpp @@ -0,0 +1,109 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/transport/if_addrs.hpp> +#include <boost/asio/ip/address_v4.hpp> +#include <boost/cstdint.hpp> +#include <iostream> + +uhd::transport::if_addrs_t::if_addrs_t(void){ + /* NOP */ +} + +/*********************************************************************** + * Interface address discovery through ifaddrs api + **********************************************************************/ +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> + +static boost::asio::ip::address_v4 sockaddr_to_ip_addr(sockaddr *addr){ + return boost::asio::ip::address_v4(ntohl( + reinterpret_cast<sockaddr_in*>(addr)->sin_addr.s_addr + )); +} + +std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ + std::vector<if_addrs_t> if_addrs; + struct ifaddrs *ifap; + if (getifaddrs(&ifap) == 0){ + for (struct ifaddrs *iter = ifap; iter != NULL; iter = iter->ifa_next){ + //ensure that the entries are valid + if (iter->ifa_addr->sa_family != AF_INET) continue; + if (iter->ifa_netmask->sa_family != AF_INET) continue; + if (iter->ifa_broadaddr->sa_family != AF_INET) continue; + + //append a new set of interface addresses + if_addrs_t if_addr; + if_addr.inet = sockaddr_to_ip_addr(iter->ifa_addr).to_string(); + if_addr.mask = sockaddr_to_ip_addr(iter->ifa_netmask).to_string(); + if_addr.bcast = sockaddr_to_ip_addr(iter->ifa_broadaddr).to_string(); + if_addrs.push_back(if_addr); + } + freeifaddrs(ifap); + } + return if_addrs; +} + +/*********************************************************************** + * Interface address discovery through windows api (TODO) + **********************************************************************/ +#elif HAVE_WINSOCK2_H +#include <winsock2.h> + +std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ + std::vector<if_addrs_t> if_addrs; + SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0); + if (sd == SOCKET_ERROR) { + std::cerr << "Failed to get a socket. Error " << WSAGetLastError() << + std::endl; return if_addrs; + } + + INTERFACE_INFO InterfaceList[20]; + unsigned long nBytesReturned; + if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList, + sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) { + std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError() << + std::endl; + return if_addrs; + } + + int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO); + for (int i = 0; i < nNumInterfaces; ++i) { + boost::uint32_t iiAddress = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiAddress).sin_addr.s_addr); + boost::uint32_t iiNetmask = ntohl(reinterpret_cast<sockaddr_in&>(InterfaceList[i].iiNetmask).sin_addr.s_addr); + boost::uint32_t iiBroadcastAddress = (iiAddress & iiNetmask) | ~iiNetmask; + + if_addrs_t if_addr; + if_addr.inet = boost::asio::ip::address_v4(iiAddress).to_string(); + if_addr.mask = boost::asio::ip::address_v4(iiNetmask).to_string(); + if_addr.bcast = boost::asio::ip::address_v4(iiBroadcastAddress).to_string(); + if_addrs.push_back(if_addr); + } + + return if_addrs; +} + +/*********************************************************************** + * Interface address discovery not included + **********************************************************************/ +#else /* HAVE_IFADDRS_H */ + +std::vector<uhd::transport::if_addrs_t> uhd::transport::get_if_addrs(void){ + return std::vector<if_addrs_t>(); +} + +#endif /* HAVE_IFADDRS_H */ diff --git a/host/lib/transport/udp_simple.cpp b/host/lib/transport/udp_simple.cpp index 3c8ecb70d..f339127ad 100644 --- a/host/lib/transport/udp_simple.cpp +++ b/host/lib/transport/udp_simple.cpp @@ -16,6 +16,7 @@ // #include <uhd/transport/udp_simple.hpp> +#include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/format.hpp> #include <iostream> diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp index 219ae8720..1fc8ce14a 100644 --- a/host/lib/transport/udp_zero_copy_asio.cpp +++ b/host/lib/transport/udp_zero_copy_asio.cpp @@ -17,6 +17,7 @@ #include <uhd/transport/udp_zero_copy.hpp> #include <boost/cstdint.hpp> +#include <boost/asio.hpp> #include <boost/thread.hpp> #include <boost/format.hpp> #include <iostream> @@ -115,7 +116,7 @@ smart_buffer::sptr udp_zero_copy_impl::recv(void){ //implement timeout through polling and sleeping boost::asio::deadline_timer timer(_socket->get_io_service()); - timer.expires_from_now(boost::posix_time::milliseconds(50)); + timer.expires_from_now(boost::posix_time::milliseconds(100)); while (not ((available = _socket->available()) or timer.expires_from_now().is_negative())){ boost::this_thread::sleep(boost::posix_time::milliseconds(1)); } diff --git a/host/lib/transport/vrt.cpp b/host/lib/transport/vrt.cpp index a06b5bf21..bebca5db9 100644 --- a/host/lib/transport/vrt.cpp +++ b/host/lib/transport/vrt.cpp @@ -1,19 +1,9 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see <http://www.gnu.org/licenses/>. -// + + + +/*********************************************************************** + * This file was generated by ./gen_vrt.py on Fri Mar 26 15:33:00 2010 + **********************************************************************/ #include <uhd/transport/vrt.hpp> #include <boost/asio.hpp> //endianness conversion @@ -30,26 +20,274 @@ void vrt::pack( size_t &num_packet_words32, //output size_t packet_count //input ){ - boost::uint32_t vrt_hdr_flags = 0; - num_header_words32 = 1; + boost::uint32_t vrt_hdr_flags; - //load the vrt header and flags - if(metadata.has_stream_id){ - vrt_hdr_flags |= (0x1 << 28); //IF Data packet with Stream Identifier - header_buff[num_header_words32++] = htonl(metadata.stream_id); - } + boost::uint8_t pred = 0; + if (metadata.has_stream_id) pred |= 0x1; + if (metadata.has_time_spec) pred |= 0xc; - if(metadata.has_time_spec){ - vrt_hdr_flags |= (0x3 << 22) | (0x1 << 20); //TSI: Other, TSF: Sample Count Timestamp - header_buff[num_header_words32++] = htonl(metadata.time_spec.secs); - header_buff[num_header_words32++] = htonl(metadata.time_spec.ticks); - header_buff[num_header_words32++] = 0; //unused part of fractional seconds + switch(pred){ + case 0: + num_header_words32 = 1; + num_packet_words32 = 1 + num_payload_words32; + vrt_hdr_flags = 0x0; + break; + case 1: + header_buff[1] = htonl(metadata.stream_id); + num_header_words32 = 2; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0x10000000; + break; + case 2: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x8000000; + break; + case 3: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x18000000; + break; + case 4: + header_buff[1] = htonl(metadata.time_spec.secs); + num_header_words32 = 2; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0xc00000; + break; + case 5: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x10c00000; + break; + case 6: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x8c00000; + break; + case 7: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x18c00000; + break; + case 8: + header_buff[1] = htonl(0); + header_buff[2] = htonl(metadata.time_spec.ticks); + num_header_words32 = 3; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x100000; + break; + case 9: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x10100000; + break; + case 10: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x8100000; + break; + case 11: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x18100000; + break; + case 12: + header_buff[1] = htonl(metadata.time_spec.secs); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0xd00000; + break; + case 13: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x10d00000; + break; + case 14: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x8d00000; + break; + case 15: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + header_buff[5] = htonl(0); + header_buff[6] = htonl(metadata.time_spec.ticks); + num_header_words32 = 7; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0x18d00000; + break; + case 16: + num_header_words32 = 1; + num_packet_words32 = 2 + num_payload_words32; + vrt_hdr_flags = 0x4000000; + break; + case 17: + header_buff[1] = htonl(metadata.stream_id); + num_header_words32 = 2; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x14000000; + break; + case 18: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0xc000000; + break; + case 19: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x1c000000; + break; + case 20: + header_buff[1] = htonl(metadata.time_spec.secs); + num_header_words32 = 2; + num_packet_words32 = 3 + num_payload_words32; + vrt_hdr_flags = 0x4c00000; + break; + case 21: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x14c00000; + break; + case 22: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0xcc00000; + break; + case 23: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x1cc00000; + break; + case 24: + header_buff[1] = htonl(0); + header_buff[2] = htonl(metadata.time_spec.ticks); + num_header_words32 = 3; + num_packet_words32 = 4 + num_payload_words32; + vrt_hdr_flags = 0x4100000; + break; + case 25: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x14100000; + break; + case 26: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0xc100000; + break; + case 27: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0x1c100000; + break; + case 28: + header_buff[1] = htonl(metadata.time_spec.secs); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.ticks); + num_header_words32 = 4; + num_packet_words32 = 5 + num_payload_words32; + vrt_hdr_flags = 0x4d00000; + break; + case 29: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(metadata.time_spec.secs); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.ticks); + num_header_words32 = 5; + num_packet_words32 = 6 + num_payload_words32; + vrt_hdr_flags = 0x14d00000; + break; + case 30: + header_buff[1] = htonl(0); + header_buff[2] = htonl(0); + header_buff[3] = htonl(metadata.time_spec.secs); + header_buff[4] = htonl(0); + header_buff[5] = htonl(metadata.time_spec.ticks); + num_header_words32 = 6; + num_packet_words32 = 7 + num_payload_words32; + vrt_hdr_flags = 0xcd00000; + break; + case 31: + header_buff[1] = htonl(metadata.stream_id); + header_buff[2] = htonl(0); + header_buff[3] = htonl(0); + header_buff[4] = htonl(metadata.time_spec.secs); + header_buff[5] = htonl(0); + header_buff[6] = htonl(metadata.time_spec.ticks); + num_header_words32 = 7; + num_packet_words32 = 8 + num_payload_words32; + vrt_hdr_flags = 0x1cd00000; + break; } - vrt_hdr_flags |= (metadata.start_of_burst)? (0x1 << 25) : 0; - vrt_hdr_flags |= (metadata.end_of_burst)? (0x1 << 24) : 0; - - num_packet_words32 = num_header_words32 + num_payload_words32; + //set the burst flags + if (metadata.start_of_burst) vrt_hdr_flags |= 0x2000000; + if (metadata.end_of_burst) vrt_hdr_flags |= 0x1000000; //fill in complete header word header_buff[0] = htonl(vrt_hdr_flags | @@ -80,30 +318,230 @@ void vrt::unpack( if (vrt_hdr_word & (0x7 << 29)) throw std::runtime_error("unsupported vrt packet type"); - //parse the header flags - num_header_words32 = 1; - - if (vrt_hdr_word & (0x1 << 28)){ //stream id - metadata.has_stream_id = true; - metadata.stream_id = ntohl(header_buff[num_header_words32++]); - } - - if (vrt_hdr_word & (0x1 << 27)){ //class id (we dont use) - num_header_words32 += 2; - } - - if (vrt_hdr_word & (0x3 << 22)){ //integer time - metadata.has_time_spec = true; - metadata.time_spec.secs = ntohl(header_buff[num_header_words32++]); - } + boost::uint8_t pred = 0; + if(vrt_hdr_word & 0x10000000) pred |= 0x1; + if(vrt_hdr_word & 0x8000000) pred |= 0x2; + if(vrt_hdr_word & 0xc00000) pred |= 0x4; + if(vrt_hdr_word & 0x300000) pred |= 0x8; + if(vrt_hdr_word & 0x4000000) pred |= 0x10; - if (vrt_hdr_word & (0x3 << 20)){ //fractional time - metadata.has_time_spec = true; - metadata.time_spec.ticks = ntohl(header_buff[num_header_words32++]); - num_header_words32++; //unused part of fractional seconds + switch(pred){ + case 0: + num_header_words32 = 1; + num_payload_words32 = packet_words32 - 1; + break; + case 1: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 2; + break; + case 2: + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 3: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 4: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 2; + break; + case 5: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 6: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 7: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 8: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 3; + break; + case 9: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 10: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 11: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 6; + break; + case 12: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 4; + break; + case 13: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 5; + break; + case 14: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 6; + break; + case 15: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + metadata.time_spec.ticks = ntohl(header_buff[6]); + num_header_words32 = 7; + num_payload_words32 = packet_words32 - 7; + break; + case 16: + num_header_words32 = 1; + num_payload_words32 = packet_words32 - 2; + break; + case 17: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 3; + break; + case 18: + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 19: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 20: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + num_header_words32 = 2; + num_payload_words32 = packet_words32 - 3; + break; + case 21: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 22: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 23: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 24: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[2]); + num_header_words32 = 3; + num_payload_words32 = packet_words32 - 4; + break; + case 25: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 26: + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 27: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 7; + break; + case 28: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[1]); + metadata.time_spec.ticks = ntohl(header_buff[3]); + num_header_words32 = 4; + num_payload_words32 = packet_words32 - 5; + break; + case 29: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[2]); + metadata.time_spec.ticks = ntohl(header_buff[4]); + num_header_words32 = 5; + num_payload_words32 = packet_words32 - 6; + break; + case 30: + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[3]); + metadata.time_spec.ticks = ntohl(header_buff[5]); + num_header_words32 = 6; + num_payload_words32 = packet_words32 - 7; + break; + case 31: + metadata.has_stream_id = true; + metadata.stream_id = ntohl(header_buff[1]); + metadata.has_time_spec = true; + metadata.time_spec.secs = ntohl(header_buff[4]); + metadata.time_spec.ticks = ntohl(header_buff[6]); + num_header_words32 = 7; + num_payload_words32 = packet_words32 - 8; + break; } - - size_t num_trailer_words32 = (vrt_hdr_word & (0x1 << 26))? 1 : 0; - - num_payload_words32 = packet_words32 - num_header_words32 - num_trailer_words32; } + |