Projects
osmocom:latest
libosmocore
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 10
View file
libosmocore.spec
Changed
@@ -14,13 +14,13 @@ Name: libosmocore Requires: osmocom-latest -Version: 1.9.3 +Version: 1.10.0 Release: 0 Summary: The Open Source Mobile Communications Core Library License: GPL-2.0-only AND GPL-2.0-or-later AND LGPL-2.1-or-later AND AGPL-3.0-or-later Group: Productivity/Telephony/Utilities Url: https://osmocom.org/projects/libosmocore/wiki/Libosmocore -Source: libosmocore_1.9.3.tar.xz +Source: libosmocore_1.10.0.tar.xz Source1: rpmlintrc BuildRequires: automake >= 1.6 BuildRequires: libtool >= 2 @@ -122,14 +122,14 @@ This subpackage contains libraries and header files for developing applications that want to make use of libosmocoding. -%package -n libosmocore21 +%package -n libosmocore22 Requires: osmocom-latest Summary: Osmocom core library # crc16.c has GPL2-only clauses, the rest (*.c) is GPL-2.0+ License: GPL-2.0-only AND GPL-2.0-or-later Group: System/Libraries -%description -n libosmocore21 +%description -n libosmocore22 libosmocore is a library with various utility functions shared between OpenBSC and OsmocomBB. @@ -139,7 +139,7 @@ # crc16.h has GPL2-only clauses, the rest (*.h) is GPL-2.0+ License: GPL-2.0-only AND GPL-2.0-or-later Group: Development/Libraries/C and C++ -Requires: libosmocore21 = %version +Requires: libosmocore22 = %version Requires: libtalloc-devel Requires: lksctp-tools-devel @@ -390,8 +390,8 @@ %postun -n libosmocodec4 -p /sbin/ldconfig %post -n libosmocoding0 -p /sbin/ldconfig %postun -n libosmocoding0 -p /sbin/ldconfig -%post -n libosmocore21 -p /sbin/ldconfig -%postun -n libosmocore21 -p /sbin/ldconfig +%post -n libosmocore22 -p /sbin/ldconfig +%postun -n libosmocore22 -p /sbin/ldconfig %post -n libosmoctrl0 -p /sbin/ldconfig %postun -n libosmoctrl0 -p /sbin/ldconfig %post -n libosmogb14 -p /sbin/ldconfig @@ -435,9 +435,9 @@ %_libdir/libosmocoding.so %_libdir/pkgconfig/libosmocoding.pc -%files -n libosmocore21 +%files -n libosmocore22 %defattr(-,root,root) -%_libdir/libosmocore.so.21* +%_libdir/libosmocore.so.22* %files -n libosmocore-devel %defattr(-,root,root)
View file
libosmocore_1.9.3.dsc -> libosmocore_1.10.0.dsc
Changed
@@ -1,8 +1,8 @@ Format: 3.0 (native) Source: libosmocore -Binary: libosmocore, libosmocodec4, libosmocodec-doc, libosmocoding0, libosmocoding-doc, libosmocore21, libosmocore-doc, libosmogb14, libosmogb-doc, libosmogsm20, libosmogsm-doc, libosmoisdn0, libosmoisdn-doc, libosmovty13, libosmovty-doc, libosmoctrl0, libosmoctrl-doc, libosmosim2, libosmosim-doc, libosmousb0, libosmousb-doc, libosmocore-dev, libosmocore-utils, libosmocore-dbg +Binary: libosmocore, libosmocodec4, libosmocodec-doc, libosmocoding0, libosmocoding-doc, libosmocore22, libosmocore-doc, libosmogb14, libosmogb-doc, libosmogsm20, libosmogsm-doc, libosmoisdn0, libosmoisdn-doc, libosmovty13, libosmovty-doc, libosmoctrl0, libosmoctrl-doc, libosmosim2, libosmosim-doc, libosmousb0, libosmousb-doc, libosmocore-dev, libosmocore-utils, libosmocore-dbg Architecture: any all -Version: 1.9.3 +Version: 1.10.0 Maintainer: Osmocom team <openbsc@lists.osmocom.org> Homepage: https://projects.osmocom.org/projects/libosmocore Standards-Version: 3.9.8 @@ -19,7 +19,7 @@ libosmocore-dev deb libdevel optional arch=any libosmocore-doc deb doc optional arch=all libosmocore-utils deb utils optional arch=any - libosmocore21 deb libs optional arch=any + libosmocore22 deb libs optional arch=any libosmoctrl-doc deb doc optional arch=all libosmoctrl0 deb libs optional arch=any libosmogb-doc deb doc optional arch=all @@ -35,8 +35,8 @@ libosmovty-doc deb doc optional arch=all libosmovty13 deb libs optional arch=any Checksums-Sha1: - d9c48e5684c36098d91628898c348067132190fd 1073048 libosmocore_1.9.3.tar.xz + 25e7afd5e3862d4c010b1af68b5e6f8593502178 1115420 libosmocore_1.10.0.tar.xz Checksums-Sha256: - a646354ac9737d7a22f4ba1e292f055d770f9c0d5a2bde42fc952bf0ee9bb1d1 1073048 libosmocore_1.9.3.tar.xz + b1dcaf683726aac3da1a12654d511a015745828e7f01ad09ee5db1b8f757aa16 1115420 libosmocore_1.10.0.tar.xz Files: - 592d76e96f759a1707d2f611725963df 1073048 libosmocore_1.9.3.tar.xz + fd0bd2cda08082d51e414377c55e33fe 1115420 libosmocore_1.10.0.tar.xz
View file
libosmocore_1.10.0.tar.xz/.github
Added
+(directory)
View file
libosmocore_1.10.0.tar.xz/.github/FUNDING.yml
Added
@@ -0,0 +1 @@ +open_collective: osmocom
View file
libosmocore_1.9.3.tar.xz/.tarball-version -> libosmocore_1.10.0.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.9.3 +1.10.0
View file
libosmocore_1.9.3.tar.xz/README.md -> libosmocore_1.10.0.tar.xz/README.md
Changed
@@ -70,7 +70,7 @@ Our coding standards are described at <https://osmocom.org/projects/cellular-infrastructure/wiki/Coding_standards> -We us a gerrit based patch submission/review process for managing +We use a Gerrit based patch submission/review process for managing contributions. Please see <https://osmocom.org/projects/cellular-infrastructure/wiki/Gerrit> for more details
View file
libosmocore_1.9.3.tar.xz/TODO-RELEASE -> libosmocore_1.10.0.tar.xz/TODO-RELEASE
Changed
@@ -3,7 +3,7 @@ # In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info # LIBVERSION=c:r:a # If the library source code has changed at all since the last update, then increment revision: c:r + 1:a. -# If any interfaces have been added, removed, or changed since the last update: c + 1:0:0. +# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a. # If any interfaces have been added since the last public release: c:r:a + 1. # If any interfaces have been removed or changed since the last public release: c:r:0. #library what description / commit summary line
View file
libosmocore_1.9.3.tar.xz/configure.ac -> libosmocore_1.10.0.tar.xz/configure.ac
Changed
@@ -282,6 +282,11 @@ ENABLE_SCTP_TESTS=$enableval, ENABLE_SCTP_TESTS="yes") AM_CONDITIONAL(ENABLE_SCTP_TESTS, test x"$ENABLE_SCTP_TESTS" = x"yes") +AC_ARG_ENABLE(uring-tests, AS_HELP_STRING(--disable-uring-tests, Do not run io_uring tests), + ENABLE_URING_TESTS=$enableval, ENABLE_URING_TESTS="yes") +AM_CONDITIONAL(ENABLE_URING_TESTS, test x"$ENABLE_URING_TESTS" = x"yes") +AC_SUBST(ENABLE_URING_TESTS) + AC_ARG_ENABLE(plugin, AS_HELP_STRING( --disable-plugin,
View file
libosmocore_1.9.3.tar.xz/contrib/libosmocore.spec.in -> libosmocore_1.10.0.tar.xz/contrib/libosmocore.spec.in
Changed
@@ -121,14 +121,14 @@ This subpackage contains libraries and header files for developing applications that want to make use of libosmocoding. -%package -n libosmocore21 +%package -n libosmocore22 Requires: osmocom-latest Summary: Osmocom core library # crc16.c has GPL2-only clauses, the rest (*.c) is GPL-2.0+ License: GPL-2.0-only AND GPL-2.0-or-later Group: System/Libraries -%description -n libosmocore21 +%description -n libosmocore22 libosmocore is a library with various utility functions shared between OpenBSC and OsmocomBB. @@ -138,7 +138,7 @@ # crc16.h has GPL2-only clauses, the rest (*.h) is GPL-2.0+ License: GPL-2.0-only AND GPL-2.0-or-later Group: Development/Libraries/C and C++ -Requires: libosmocore21 = %version +Requires: libosmocore22 = %version Requires: libtalloc-devel Requires: lksctp-tools-devel @@ -389,8 +389,8 @@ %postun -n libosmocodec4 -p /sbin/ldconfig %post -n libosmocoding0 -p /sbin/ldconfig %postun -n libosmocoding0 -p /sbin/ldconfig -%post -n libosmocore21 -p /sbin/ldconfig -%postun -n libosmocore21 -p /sbin/ldconfig +%post -n libosmocore22 -p /sbin/ldconfig +%postun -n libosmocore22 -p /sbin/ldconfig %post -n libosmoctrl0 -p /sbin/ldconfig %postun -n libosmoctrl0 -p /sbin/ldconfig %post -n libosmogb14 -p /sbin/ldconfig @@ -434,9 +434,9 @@ %_libdir/libosmocoding.so %_libdir/pkgconfig/libosmocoding.pc -%files -n libosmocore21 +%files -n libosmocore22 %defattr(-,root,root) -%_libdir/libosmocore.so.21* +%_libdir/libosmocore.so.22* %files -n libosmocore-devel %defattr(-,root,root)
View file
libosmocore_1.9.3.tar.xz/debian/changelog -> libosmocore_1.10.0.tar.xz/debian/changelog
Changed
@@ -1,27 +1,252 @@ -libosmocore (1.9.3) unstable; urgency=medium +libosmocore (1.10.0) unstable; urgency=medium - * libosmosim: class_tables: Resolve conflicting CLA=8x INS=F2 definitions - * libosmosim: class_tables: Fix GlobalPlatform CLA=8x INS=CA/CB GET DATA + Mychaela N. Falconia + * gsm/protocol/gsm_04_11.h: add SMSC-address length limit definitions + * gsm0808: add knowledge of TW-TS-003 BSSMAP IE + * bts_features: add feature flags for TWTS001 and TWTS002 + * rsl: define RSL_IE_OSMO_RTP_EXTENSIONS + * include/osmocom/gsm: add rtp_extensions.h + * codec: make osmo_hr_check_sid() more efficient + + arehbein + * write_queue: Enable updating max_length field + * osmo_io: Clean up code + * gsmtap: Hide implementation of gsmtap_inst + * osmo_io_poll: Handle -EAGAIN in case of OSMO_FD_WRITE + * write_queue: Fix Doxygen comment + * gsmtap_util: Use Osmo IO instead of Osmo write queues + * gsmtap_util: Simplify sink + * gmstap_util: Fix sending out gsmtap messages + * ns2: Improve code consistency + + Manawyrm + * gsmtap.h: Add definitions for ISDN PPP sub-type + * gsm48_ie.c: add 3.1kHz audio bearer capability for CSD calls + * gsm48_ie.c: change bearer cap structure in outgoing CSD calls + * logging: ensure ANSI color escape is sent in same line/before newline - -- Harald Welte <laforge@osmocom.org> Thu, 06 Jun 2024 19:40:40 +0200 + Karsten Ohme + * APDU parsing support for GlobalPlatform GET RESPONSE -libosmocore (1.9.2) unstable; urgency=medium + Vadim Yanitskiy + * gsm: add gsm0502_fn_compare() for comparing TDMA FNs + * gsm: rename s/gsm0502_fn_compare/gsm0502_fncmp/ + * msgb: fix doxygen docs for msgb_pull_u{8,16,32): end -> front + * coding: gsm0503_tch_afhs_encode(): improve cmr/ft checks + * coding: gsm0503_tch_afhs_encode(): make *codec const + * tests/testsuite.at: remove copy-pasted 'touch experr' + * soft_uart: add osmo_soft_uart_free() + * soft_uart: add doxygen documentation + * soft_uart: split osmo_soft_uart_enable() + * soft_uart: make osmo_soft_uart_alloc() accept *cfg + * soft_uart: rework osmo_uart_rx_bit() to use flow state + * soft_uart: implement parity checking for the receiver + * soft_uart: implement the transmitter + * soft_uart: allow manually flushing the receive buffer + * soft_uart: add unit tests for the receiver and transmitter + * soft_uart: fix Rx buffer flushing logic in suart_rx_ch() + * soft_uart: fix handling of num_data_bits < 8 + * soft_uart: implement OSMO_SUART_PARITY_{MARK,SPACE} + * soft_uart: demonstrate a problem with osmo_soft_uart_tx_ubits() + * soft_uart: fix pulling a small number of Tx bits + * soft_uart: check n_bits against 0 in osmo_soft_uart_tx_ubits() + * soft_uart: fix spelling in doxygen docs + * soft_uart: add osmo_soft_uart_{get,set}_name() + * soft_uart: fix doxygen doc for osmo_soft_uart_tx_ubits() + * soft_uart: check Rx/Tx state once in osmo_soft_uart_{rx,tx}_ubits() + * soft_uart: cosmetic: do not use 'osmo_' prefix for static symbols + * soft_uart: improve doxygen documentation + * soft_uart: osmo_soft_uart_tx_ubits(): return number of bits pulled + * soft_uart: implement modem status lines and flow control + * coding: fix doxygen docs for gsm0503_pdtch_egprs_decode() + * coding: clarify the USF decoding for PDCH blocks + * coding: gsm0503_pdtch_decode(): implement USF decoding for CS1 + * tests/coding: fix -Wmaybe-uninitialized in test_pdtch() + * tests/it_q: add tc_enqueue/dequeue testcase + * core: fix wrong logic in _osmo_it_q_dequeue() + * tests/soft_uart: assert that osmo_soft_uart_rx_ubits() returns 0 + * tests/soft_uart: cosmetic: improve readability of the test output + * soft_uart: cosmetic: use consistent naming for the Rx buffer msgb + * logging: fix NULL pointer dereference in _output_buf() + * soft_uart: fix the Rx flushing logic, add a unit test + * soft_uart: demonstrate a problem with manual flush()ing + * soft_uart: demonstrate a problem with inefficient polling + * tests/lapd: fix wrong size passed in test_lapdm_contention_resolution() + * tests/gsm0808: fix assert()s in test_gsm0808_dec_cell_id_list_srvcc() + * tests/iuup: fix assert()s in test_decode_passive_init_2_rfci_no_iptis() + * tests/fsm: also test .onenter and .onleave callbacks + * tests: fix update-exp: soft_uart_test overwrites rlp_test.ok + * utils: fix OSMO_STRBUF_REMAIN to handle sb.pos == NULL correctly + * utils: improve readability of OSMO_STRBUF_CHAR_COUNT + * utils: fix -Wsign-compare in definition of OSMO_STRBUF_CHAR_COUNT + * utils: osmo_bcd2str(): fix applying non-zero offset to null pointer + * tests/utils: do not test strbuf_example2() with buf=NULL + * bitvec: bitvec_to_string_r(): drop unused variable + * tests/{gb,iuup}: also match stderr + * tests/tdef: also test OSMO_TDEF_US and negative T values + * tests/tdef: tune logging, also match stderr + * pseudotalloc: add talloc_memdup(), use it in talloc_strdup() + * gsm0808_utils: use osmo_strbuf API, drop APPEND_{THING,STR,CELL_ID_U} + * vty: suppress warnings about len being set but not used + * gsm48_ie: fix various issues in doxygen docs + * gsm: fix osmo_mobile_identity_decode(): init *mi on error + * core: osmo_tdef_fsm_inst_state_chg(): allow millisecond precision + * tests/tdef: improve test output (use OSMO_T_FMT_ARGS) + * fsm: fix OSMO_T_FMT_ARGS: add missing braces + * isdn: initial implementation of the V.110 TA + * isdn: add a lookup table with E1/E2/E3 bits from Table 5/V.110 + * tests/gsm0408: cosmetic: adjust coding style (make linter happy) + * tests/gsm0408: add two more samples to bcap_tests + * isdn/v110_ta: avoid redundant .status_update_cb() calls + * gsm: add more definitions from Table 10.5.112/3GPP TS 24.008 + * tests/iuup: fix duplicate assignment in def_configure_req + * tests/a5: fix bit-wise vs logical and in test_a534() + * tests/sockaddr_str: fix dead code, print some errno values + * tests/sockaddr_str: rc_name(): also handle -EAFNOSUPPORT + * osmo-release.sh: make it a bit more user friendly + * tests/Makefile.am: do not add files to EXTRA_DIST conditionally + * utils/conv_codes_gsm.py: fix inconsistent formatting + * coding: fix a typo in docs for gsm0503_pdtch_decode() + * coding: improve readability in osmo_conv_decode_ber_punctured() + * coding: fix artificial bit errors for PDTCH CS2 and CS3 + * coding: fix wrong n_bits_total reported for PDTCH CS2 and CS3 + * core: fix missing '\n' in iofd_uring_connected_cb() + * tests: do not copy *.cfg files to the build directory + * tests: rename logging_test_gsmtap -> logging_gsmtap_test + * vty: fix memleak in host_config_set() + * {fsm,vty}: add a VTY command to generate FSM state graphs + * core: fix LOGPIO(): add missing space after 'iofd(...)' + * README.md: cosmetic: fix a typo Pau Espin Pedrol * sockaddr_str.h Fix OSMO_SOCKADDR_STR_FMT_ARGS_NOT_NULL syntax error + * socket: Introduce APIs osmo_sock_multiaddr_{add,del}_local_addr() + * Fix typo in libosmocore.map + * socket.c: Fix compilation with --disable-libsctp + * tests/socket: Avoid keeping unneeded sockets open during next test cases + * socket: Reimplement osmo_sock_init2_multiaddr() + * socket: osmo_sock_init2_multiaddr2(): Apply params too if no OSMO_SOCK_F_BIND flag set + * socket: Introduce API osmo_sock_multiaddr_get_ip_and_port() + * socket: Introduce API osmo_sock_multiaddr_get_name_buf() + * socket: Fix uninitialized mem ptr free in osmo_sock_init2_multiaddr2() + * socket: Introduce API osmo_sock_sctp_get_peer_addr_info() + * socket: Introduce defines OSMO_SOCK_MULTIADDR_{PEER_STR,NAME}_MAXLEN + * ipa_ccm_tlv_to_unitdata(): free previous string if present before allocating new one + * cosmetic: gsup.h: fix whitespace formatting + * gsm_04_08_gprs.h: Introduce packed struct gsm48_pdp_address + * gsup: Fail decoding if len of PDP Type IE is less than 2 bytes + * gsup: Deprecate field pdp_type in favour of pdp_type_nr and pdp_type_org + * gsup: Convert PDP-Type IE to PDP-Address IE + * cosmetic: tests/gsup/gsup_test: Move send_e_send_end_signal_res to correct place + * socket: Support AF_UNIX in osmo_sock_get_name_buf() + * socket: Add remote PID and local FD to AF_UNIX sockname + * osmo_io: Add iofd param to segmentation_cb Daniel Willmann + * osmo_io: Init struct msghdr to zero + * osmo_io: Only allow reading/writing if the relevant callback is set * logging_gsmtap: Temporarily disable logging when sending the logs + * osmo_io: Assert that iofd mode is correct when calling *_write_msgb * Disable uring when building for embedded + * osmo_io: Factor out and use common send function from backend + * tests: Test gsmtap logging if write queue fills up - -- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 12:59:15 +0100 - -libosmocore (1.9.1) unstable; urgency=medium + Andreas Eversberg + * LAPDm: Correctly count expiry of T200 during estabishment/release + * ASCI: Add primitive to L1-SAP to switch uplink access detection on or off + * LAPD: Prepare lapd_send_i() for RTS support + * LAPD: Flush TX queue, if remote peer enters busy condition or rejects + * LAPD: Always update N(R) in pending TX frames if V(R) is incremented + * LAPD: Add support for RTS based polling and T200 + * LAPDm: Add support for RTS based polling + * LAPDm: Add an extra queue for UI frames + * LAPDm: Add a flag to enable suppression of subsequent REJ frame + * LAPD: Indicate sequence error after indicating received data + * coding: gsm0503_tch_{afs,ahs}_encode(): add ability to emit BFI + * Fix union abis_rsl_chan_nr and abis_rsl_link_id + * Add flag to enable RTS based polling + * Prevent poll() in select.c to timeout too early + * Make socket.c compile without libsctp support (--disable-libsctp) + * osmo_io: Move notify_connected function to backend + * osmo_io: Use poll/select to notify socket connection at osmo_io_uring.c + * osmo_io: Reject writing messages with length of 0 + * osmo_io_poll: Use -errno as result on read error + * osmo_io_uring: Cancel pending request, free msghdr on completion + * osmo_io_uring: Detach msghdr from iofd before calling iofd_handle_send_completion() + * osmo_io_poll: Declare local functions "static" + * osmo_io: Assign const name when stealing TX msg from iofd ctx + * osmo_io_uring: Check if osmo_fd_register fails at iofd_uring_notify_connected() + * osmo_io: do check_mode_callback_compat() only if ioops is set at osmo_iofd_setup() + * osmo_io_poll: Use -errno as result on write error + * Fix file descriptor that is passed to io_uring_register_eventfd() + * osmo_io_uring: Run check of tests/osmo_io with io_uring also + + Harald Welte + * core: Add software UART implementation + * add new osmo_sockaddr_from_str_and_uint() function + * io_uring: add some more source code comments/docs + * osmo_io: rename unsupported SCTP mode to OSMO_IO_FD_MODE_SCTP_RECVMSG_SEND + * osmo_io: Reject unknown/unsupported modes in osmo_iofd_setup() + * sim/class_tables: Prevent out-of-bounds access + * libosmosim: Support Microsoft smart card discovery process + * Add a GSM RLP decoder and encoder + * rlp: Add support for 576bit RLP frames + * osmo_io: Change struct osmo_io_ops to contain struct, not union + * osmo_io: sendmsg/recvmsg support + * osmo_io: Add osmo_io_get_ioops() function + * ctrl: Don't expose write_queue in ctrl_cmd_send() api + * cbsp: Add osmo_cbsp_segmentation_cb for message segmentation + * osmo_io: Guard osmo_iofd_register() with invalid file descriptor + * osmo_io: Log error message in case call-backs incompatible with mode + * osmo_io: Don't pretend to support backends without close_cb + * osmo_io: avoid OSMO_ASSERT one each API call + * osmo_io: Avoid implementing non-existant situations + * ctrl: re-introduce duplicate declaration of ctrl_cmd_send() + * io_uring: more verbose error messages if io_uring setup fails + * io_uring: check all operations in osmo_iofd_uring_init() + * osmo_io: Dont use __linux__ but !EMBEDDED + * osmo_io: Massive improvement of API documentation + * osmo_io: Make {write,sendto,sendmsg} completion callback optional + * Add funding link to github mirror + * libosmosim: class_tables: Resolve conflicting CLA=8x INS=F2 definitions + * libosmosim: class_tables: Fix GlobalPlatform CLA=8x INS=CA/CB GET DATA + * cosmetic libosmosim/class_tables: Add a quick reminder about the cases - Manawyrm - * logging: ensure ANSI color escape is sent in same line/before newline + Alexander Couzens + * gsup: add message type for osmo-epdg CEAI interface + * gsup: fix error log message + * gsup.h: define newly added PCO IE + + Neels Hofmeyr + * util: add OSMO_STRBUF_REMAIN() + * util: add osmo_strbuf macros to manipulate the strbuf tail + * logging: fix nul octets in log output / use osmo_strbuf + * comment: gsm_04_08.h: add a spec hint + * sockaddr_str: add conversion to,from osmo_sockaddr + * fix update_exp: s/soft_uart.ok/soft_uart_test.ok + * add jhash.h, copied from linux/jhash.h + + Philipp Maier + * ecu: fix alignment of fr_ecu_state + + Eric + * logging: add log level cache + + Hoernchen + * Revert "logging: add log level cache" + * Revert "Revert "logging: add log level cache"" + + Matan Perelman + * ctrl: Add lchan node + + Oliver Smith + * osmo-release: don't default to REL=patch + * osmo-release: use script from PWD if available + * osmo-release: use colored output + * osmo-release: rework cleaning of TODO-RELEASE + * osmo-release: fix libversion updating comment - -- Oliver Smith <osmith@sysmocom.de> Tue, 28 Nov 2023 11:21:41 +0100 + -- Oliver Smith <osmith@sysmocom.de> Wed, 24 Jul 2024 10:19:45 +0200 libosmocore (1.9.0) unstable; urgency=medium
View file
libosmocore_1.9.3.tar.xz/debian/control -> libosmocore_1.10.0.tar.xz/debian/control
Changed
@@ -33,7 +33,7 @@ Multi-Arch: foreign Depends: osmocom-latest, libosmocodec4 (= ${binary:Version}), libosmocoding0 (= ${binary:Version}), - libosmocore21 (= ${binary:Version}), + libosmocore22 (= ${binary:Version}), libosmogb14 (= ${binary:Version}), libosmogsm20 (= ${binary:Version}), libosmoisdn0 (= ${binary:Version}), @@ -118,7 +118,7 @@ . This package contains the documentation for the libosmocoding library. -Package: libosmocore21 +Package: libosmocore22 Section: libs Architecture: any Multi-Arch: same @@ -139,7 +139,7 @@ Architecture: all Section: doc Depends: osmocom-latest, ${misc:Depends}, - libosmocore21, + libosmocore22, libjs-jquery, libosmocodec-doc, libosmocoding-doc,
View file
libosmocore_1.10.0.tar.xz/debian/libosmocore22.install
Changed
(renamed from debian/libosmocore21.install)
View file
libosmocore_1.9.3.tar.xz/debian/rules -> libosmocore_1.10.0.tar.xz/debian/rules
Changed
@@ -30,6 +30,7 @@ set -x && \ CONFIGURE_FLAGS=" \ --disable-sctp-tests \ + --disable-uring-tests \ --enable-static \ --enable-systemd-logging \ "; \
View file
libosmocore_1.9.3.tar.xz/include/osmocom/coding/gsm0503_coding.h -> libosmocore_1.10.0.tar.xz/include/osmocom/coding/gsm0503_coding.h
Changed
@@ -56,7 +56,7 @@ int *n_errors, int *n_bits_total); int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len, - int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, + int codec_mode_req, const uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr); int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts, int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft, @@ -66,7 +66,7 @@ uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx); int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len, - int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr); + int codec_mode_req, const uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr); int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd, int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft, uint8_t *cmr, int *n_errors, int *n_bits_total);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/Makefile.am -> libosmocore_1.10.0.tar.xz/include/osmocom/core/Makefile.am
Changed
@@ -27,6 +27,7 @@ hashtable.h \ isdnhdlc.h \ it_q.h \ + jhash.h \ linuxlist.h \ linuxrbtree.h \ log2.h \ @@ -60,6 +61,7 @@ utils.h \ write_queue.h \ sockaddr_str.h \ + soft_uart.h \ time_cc.h \ use_count.h \ socket_compat.h \
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/fsm.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/fsm.h
Changed
@@ -200,7 +200,7 @@ fmt, ## args) #define OSMO_T_FMT "%c%u" -#define OSMO_T_FMT_ARGS(T) ((T) >= 0 ? 'T' : 'X'), ((T) >= 0 ? T : -T) +#define OSMO_T_FMT_ARGS(T) ((T) >= 0 ? 'T' : 'X'), ((T) >= 0 ? (T) : -(T)) int osmo_fsm_register(struct osmo_fsm *fsm); void osmo_fsm_unregister(struct osmo_fsm *fsm);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/gsmtap.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/gsmtap.h
Changed
@@ -185,6 +185,7 @@ #define GSMTAP_E1T1_V120 0x08 /* V.120 B-channel data */ #define GSMTAP_E1T1_V110 0x09 /* V.110 B-channel data */ #define GSMTAP_E1T1_H221 0x0a /* H.221 B-channel data */ +#define GSMTAP_E1T1_PPP 0x0b /* PPP */ /* flags for the ARFCN */ #define GSMTAP_ARFCN_F_PCS 0x8000
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/gsmtap_util.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/gsmtap_util.h
Changed
@@ -24,19 +24,12 @@ int8_t snr, const uint8_t *data, unsigned int len); /*! one gsmtap instance */ -struct gsmtap_inst { - int ofd_wq_mode; /*!< wait queue mode? */ - struct osmo_wqueue wq; /*!< the wait queue */ - struct osmo_fd sink_ofd;/*!< file descriptor */ -}; +struct gsmtap_inst; -/*! obtain the file descriptor associated with a gsmtap instance - * \paramin gti GSMTAP instance - * \returns file descriptor of GSMTAP instance */ -static inline int gsmtap_inst_fd(struct gsmtap_inst *gti) -{ - return gti->wq.bfd.fd; -} +int gsmtap_inst_fd(struct gsmtap_inst *gti) + OSMO_DEPRECATED("Use gsmtap_inst_fd2() instead"); + +int gsmtap_inst_fd2(const struct gsmtap_inst *gti); int gsmtap_source_init_fd(const char *host, uint16_t port); int gsmtap_source_init_fd2(const char *local_host, uint16_t local_port, const char *rem_host, uint16_t rem_port);
View file
libosmocore_1.10.0.tar.xz/include/osmocom/core/jhash.h
Added
@@ -0,0 +1,171 @@ +#pragma once +#include <osmocom/core/bit32gen.h> + +/* Below is a partial copy of + * https://raw.githubusercontent.com/torvalds/linux/3eb3c33c1d87029a3832e205eebd59cfb56ba3a4/tools/include/linux/bitops.h + * with an osmo_ prefix applied to avoid any collisions. + */ +/* SPDX-License-Identifier: GPL-2.0 */ +/** + * rol32 - rotate a 32-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline uint32_t osmo_rol32(uint32_t word, unsigned int shift) +{ + return (word << shift) | (word >> ((-shift) & 31)); +} + +/* Below is a partial copy of + * https://raw.githubusercontent.com/torvalds/linux/22c033989c3eb9731ad0c497dfab4231b8e367d6/include/linux/unaligned/packed_struct.h + * with an osmo_ prefix applied to avoid any collisions. + */ +struct osmo_unaligned_cpu32 { + uint32_t x; +} __attribute__((__packed__)); + +static inline uint32_t osmo_get_unaligned_cpu32(const void *p) +{ + const struct osmo_unaligned_cpu32 *ptr = (const struct osmo_unaligned_cpu32 *)p; + return ptr->x; +} + +/* Below is a partial copy of + * https://raw.githubusercontent.com/torvalds/linux/79e3ea5aab48c83de9410e43b52895406847eca7/tools/include/linux/jhash.h + * with an osmo_ prefix applied to avoid any collisions. + */ +/* jhash.h: Jenkins hash support. + * + * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net) + * + * https://burtleburtle.net/bob/hash/ + * + * These are the credits from Bob's sources: + * + * lookup3.c, by Bob Jenkins, May 2006, Public Domain. + * + * These are functions for producing 32-bit hashes for hash table lookup. + * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() + * are externally useful functions. Routines to test the hash are included + * if SELF_TEST is defined. You can use this free for any purpose. It's in + * the public domain. It has no warranty. + * + * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu) + * + * I've modified Bob's hash to be useful in the Linux kernel, and + * any bugs present are my fault. + * Jozsef + */ + +/* OSMO_JHASH_MIX -- mix 3 32-bit values reversibly. */ +#define OSMO_JHASH_MIX(a, b, c) \ +{ \ + a -= c; a ^= osmo_rol32(c, 4); c += b; \ + b -= a; b ^= osmo_rol32(a, 6); a += c; \ + c -= b; c ^= osmo_rol32(b, 8); b += a; \ + a -= c; a ^= osmo_rol32(c, 16); c += b; \ + b -= a; b ^= osmo_rol32(a, 19); a += c; \ + c -= b; c ^= osmo_rol32(b, 4); b += a; \ +} + +/* OSMO_JHASH_FINAL - final mixing of 3 32-bit values (a,b,c) into c */ +#define OSMO_JHASH_FINAL(a, b, c) \ +{ \ + c ^= b; c -= osmo_rol32(b, 14); \ + a ^= c; a -= osmo_rol32(c, 11); \ + b ^= a; b -= osmo_rol32(a, 25); \ + c ^= b; c -= osmo_rol32(b, 16); \ + a ^= c; a -= osmo_rol32(c, 4); \ + b ^= a; b -= osmo_rol32(a, 14); \ + c ^= b; c -= osmo_rol32(b, 24); \ +} + +/* An arbitrary initial parameter */ +#define JHASH_INITVAL 0xdeadbeef + +/* osmo_jhash - hash an arbitrary key + * @k: sequence of bytes as key + * @length: the length of the key + * @initval: the previous hash, or an arbitray value + * + * The generic version, hashes an arbitrary sequence of bytes. + * No alignment or length assumptions are made about the input key. + * + * Returns the hash value of the key. The result depends on endianness. + */ +static inline uint32_t osmo_jhash(const void *key, uint32_t length, uint32_t initval) +{ + uint32_t a, b, c; + const uint8_t *k = key; + + /* Set up the internal state */ + a = b = c = JHASH_INITVAL + length + initval; + + /* All but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) { + a += osmo_get_unaligned_cpu32(k); + b += osmo_get_unaligned_cpu32(k + 4); + c += osmo_get_unaligned_cpu32(k + 8); + OSMO_JHASH_MIX(a, b, c); + length -= 12; + k += 12; + } + /* Last block: affect all 32 bits of (c) */ + /* All the case statements fall through */ + switch (length) { + case 12: c += (uint32_t)k11<<24; + case 11: c += (uint32_t)k10<<16; + case 10: c += (uint32_t)k9<<8; + case 9: c += k8; + case 8: b += (uint32_t)k7<<24; + case 7: b += (uint32_t)k6<<16; + case 6: b += (uint32_t)k5<<8; + case 5: b += k4; + case 4: a += (uint32_t)k3<<24; + case 3: a += (uint32_t)k2<<16; + case 2: a += (uint32_t)k1<<8; + case 1: a += k0; + OSMO_JHASH_FINAL(a, b, c); + case 0: /* Nothing left to add */ + break; + } + + return c; +} + +/* osmo_jhash2 - hash an array of uint32_t's + * @k: the key which must be an array of uint32_t's + * @length: the number of uint32_t's in the key + * @initval: the previous hash, or an arbitray value + * + * Returns the hash value of the key. + */ +static inline uint32_t osmo_jhash2(const uint32_t *k, uint32_t length, uint32_t initval) +{ + uint32_t a, b, c; + + /* Set up the internal state */ + a = b = c = JHASH_INITVAL + (length<<2) + initval; + + /* Handle most of the key */ + while (length > 3) { + a += k0; + b += k1; + c += k2; + OSMO_JHASH_MIX(a, b, c); + length -= 3; + k += 3; + } + + /* Handle the last 3 uint32_t's: all the case statements fall through */ + switch (length) { + case 3: c += k2; + case 2: b += k1; + case 1: a += k0; + OSMO_JHASH_FINAL(a, b, c); + case 0: /* Nothing left to add */ + break; + } + + return c; +}
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/logging.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/logging.h
Changed
@@ -409,7 +409,8 @@ /* filter on the targets */ void log_set_all_filter(struct log_target *target, int); - +int log_cache_enable(void); +void log_cache_update(int mapped_subsys, uint8_t enabled, uint8_t level); void log_set_use_color(struct log_target *target, int); void log_set_print_extended_timestamp(struct log_target *target, int); void log_set_print_timestamp(struct log_target *target, int);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/msgb.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/msgb.h
Changed
@@ -442,7 +442,7 @@ /*! remove uint8 from front of message * \paramin msgb message buffer - * \returns 8bit value taken from end of msgb + * \returns 8bit value taken from the front of msgb */ static inline uint8_t msgb_pull_u8(struct msgb *msgb) { @@ -452,7 +452,7 @@ /*! remove uint16 from front of message * \paramin msgb message buffer - * \returns 16bit value taken from end of msgb + * \returns 16bit value taken from the front of msgb */ static inline uint16_t msgb_pull_u16(struct msgb *msgb) { @@ -462,7 +462,7 @@ /*! remove uint32 from front of message * \paramin msgb message buffer - * \returns 32bit value taken from end of msgb + * \returns 32bit value taken from the front of msgb */ static inline uint32_t msgb_pull_u32(struct msgb *msgb) {
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/osmo_io.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/osmo_io.h
Changed
@@ -4,75 +4,200 @@ #pragma once +#include <sys/socket.h> + #include <osmocom/core/linuxlist.h> #include <osmocom/core/logging.h> #include <osmocom/core/msgb.h> #include <osmocom/core/socket.h> #include <osmocom/core/utils.h> - +/*! \defgroup osmo_io Osmocom I/O interface + * @{ + * + * osmo_io is the new (2023) interface for performing asynchronous I/O. + * osmo_io encapsulates asynchronous, non-blocking I/O to sockets or other file descriptors + * with a submission/completion model. + * + * For writes, the API user submits write requests, and receives + * completion call-backs once the write completes. + * + * For reads, the API user specifies the size (and headroom) for message buffers, and osmo_io + * internally allocates msgb's accordingly. Whenever data arrives at the socket/file descriptor, + * osmo_io reads the data into such a msgb and hands it to a read-completion call-back provided + * by the API user. + * + * A given socket/file descriptor is represented by struct osmo_io_fd. osmo_io_fd are named, + * i.e. the API user can provide a meaningful name describing the purpose (such as protocol/interface or the + * name of the remote peer). This allows osmo_io to log any related error messages using this name as + * context. + * + * When implementing some SOCK_STREAM / SOCK_SEQPACKET based client/server transports (such as those on top + * of TCP or SCTP), you are most likely better off using the osmo_stream_cli / osmo_stream_srv abstractions + * provided by libosmo-netif. They in turn can be used in an osmo_io mode, see the respective documentation. + * + * If you use osmo_io_fd directly, the life-cycle usually will look as follows: + * + * 1. open some socket and bind and/or connect it + * 2. Allocate an osmo_io_fd using osmo_iofd_setup(), configuring the mode and specifying the call-backs + * 3. Registering it with osmo_iofd_register(), which enables reading + * 4. Handle inbound data via {read,recvfrom,recvmsg} call-backs; write to it using + * osmo_iofd_{write,sendto_sendmsg}_msg() + * 5. Eventually un-register it using osmo_iofd_unregister(). Afterwards, you can re-cycle the iofd by + * calling osmo_iofd_register() with a new file-descriptor, or free it using osmo_iofd_free(). + * + * \file osmo_io.h */ + +/*! log macro used for logging information related to the osmo_io_fd. + * \paramin iofd osmo_io_fd about which we're logging + * \paramin level log-level (LOGL_DEBUG, LOGL_INFO, LOGL_NOTICE, LOGL_ERROR, LOGL_FATAL) + * \paramin fmt printf-style format string + * \paramin args arguments to the format string + */ #define LOGPIO(iofd, level, fmt, args...) \ - LOGP(DLIO, level, "iofd(%s)" fmt, iofd->name, ## args) + LOGP(DLIO, level, "iofd(%s) " fmt, iofd->name, ## args) struct osmo_io_fd; +/*! The _mode_ of an osmo_io_fd determines if read/write, recvfrom/sendmsg or recvmsg/sendmsg semantics are + * used. */ enum osmo_io_fd_mode { - /*! use read() / write() calls */ + /*! use read() / write() semantics with read_cb/write_cb in osmo_io_ops */ OSMO_IO_FD_MODE_READ_WRITE, - /*! use recvfrom() / sendto() calls */ + /*! use recvfrom() / sendto() semantics with recvfrom_cb/sendto_cb in osmo_io_ops */ OSMO_IO_FD_MODE_RECVFROM_SENDTO, - /*! emulate sctp_recvmsg() and sctp_sendmsg() */ - OSMO_IO_FD_MODE_SCTP_RECVMSG_SENDMSG, + /*! emulate recvmsg() / sendmsg() semantics with recvmsg_cb/sendto_cb in osmo_io_ops */ + OSMO_IO_FD_MODE_RECVMSG_SENDMSG, }; +/*! The back-end used by osmo_io. There can be multiple different back-ends available on a given system; + * only one of it is used for all I/O performed via osmo_io in one given process. */ enum osmo_io_backend { + /*! classic back-end using poll(2) and direct read/write/recvfrom/sendto/recvmsg/sendmsg syscalls */ OSMO_IO_BACKEND_POLL, + /*! back-end using io_uring to perform efficient I/O and reduce syscall overhead */ OSMO_IO_BACKEND_IO_URING, }; extern const struct value_string osmo_io_backend_names; +/*! return the string name of an osmo_io_backend */ static inline const char *osmo_io_backend_name(enum osmo_io_backend val) { return get_value_string(osmo_io_backend_names, val); } +extern const struct value_string osmo_iofd_mode_names; +/*! return the string name of an osmo_io_mode */ +static inline const char *osmo_iofd_mode_name(enum osmo_io_fd_mode val) +{ return get_value_string(osmo_iofd_mode_names, val); } + +/*! I/O operations (call-back functions) related to an osmo_io_fd */ struct osmo_io_ops { - union { - /* mode OSMO_IO_FD_MODE_READ_WRITE: */ - struct { - /*! call-back function when something was read from fd */ - void (*read_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg); - /*! call-back function when write has completed on fd */ - void (*write_cb)(struct osmo_io_fd *iofd, int res, - struct msgb *msg); - /*! call-back function to segment the data at message boundaries. - * Needs to return the size of the next message. If it returns - * -EAGAIN or a value larger than msgb_length() (message is incomplete) - * osmo_io will wait for more data to be read. Other negative values - * cause the msg to be discarded. - * If a full message was received (segmentation_cb() returns a value <= msgb_length()) - * the msgb will be trimmed to size by osmo_io and forwarded to the read call-back. Any - * parsing done to the msgb by segmentation_cb() will be preserved for the read_cb() - * (e.g. setting lxh or msgb->cb). */ - int (*segmentation_cb)(struct msgb *msg); - }; - - /* mode OSMO_IO_FD_MODE_RECVFROM_SENDTO: */ - struct { - /*! call-back function emulating recvfrom */ - void (*recvfrom_cb)(struct osmo_io_fd *iofd, int res, - struct msgb *msg, - const struct osmo_sockaddr *saddr); - /*! call-back function emulating sendto */ - void (*sendto_cb)(struct osmo_io_fd *iofd, int res, - struct msgb *msg, - const struct osmo_sockaddr *daddr); - }; + /* mode OSMO_IO_FD_MODE_READ_WRITE: */ + struct { + /*! completion call-back function when something was read from fd. Only valid in + * OSMO_IO_FD_MODE_READ_WRITE. + * \paramin iofd osmo_io_fd for which read() has completed. + * \paramin res return value of the read() call, or -errno in case of error. + * \paramin msg message buffer containing the read data. Ownership is transferred to the + * call-back, and it must make sure to msgb_free() it eventually! */ + void (*read_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg); + + /*! completion call-back function when write issued via osmo_iofd_write_msgb() has completed + * on fd. Only valid in OSMO_IO_FD_MODE_READ_WRITE. + * \paramin iofd on which a write() has completed. + * \paramin res return value of the write() call, or -errno in case of error. + * \paramin msg message buffer whose write has completed. Ownership is *not* transferred to the + * call-back; it is automatically freed after the call-back terminates! */ + void (*write_cb)(struct osmo_io_fd *iofd, int res, + struct msgb *msg); + + /*! optional call-back function to segment the data at message boundaries. + * \paramin msg message buffer whose data is to be segmented + * \returns See full function description. + * + * This is useful when message boundaries are to be preserved over a SOCK_STREAM transport + * socket like TCP. Can be NULL for any application not requiring de-segmentation of + * received data. + * + * The call-back needs to return the size of the next message. If it returns + * -EAGAIN or a value larger than msgb_length() (message is incomplete) + * osmo_io will wait for more data to be read. Other negative values + * cause the msg to be discarded. + * If a full message was received (segmentation_cb() returns a value <= msgb_length()) + * the msgb will be trimmed to size by osmo_io and forwarded to the read call-back. Any + * parsing done to the msgb by segmentation_cb() will be preserved for the read_cb() + * (e.g. setting lxh or msgb->cb). + * + * Only one (or none) of both segmentation_cb and segmentation_cb2 shall be set. + * Having both set will be considered an error during iofd setup. */ + int (*segmentation_cb)(struct msgb *msg); + + /*! optional call-back function to segment the data at message boundaries. + * \paramin iofd handling msg + * \paramin msg message buffer whose data is to be segmented + * \returns See full function description. + * + * Same as segmentation_cb above, with an extra parameter to have access to the iofd and its + * related functionalities (eg data pointer). This is useful for users requiring to store + * global state or access external objects while segmenting. + * + * The provided iofd shall not be freed by the user during the callback. + * + * Only one (or none) of both segmentation_cb and segmentation_cb2 shall be set. + * Having both set will be considered an error during iofd setup. */ + int (*segmentation_cb2)(struct osmo_io_fd *iofd, struct msgb *msg); + }; + + /* mode OSMO_IO_FD_MODE_RECVFROM_SENDTO: */ + struct { + /*! completion call-back function when recvfrom(2) has completed. + * Only valid in OSMO_IO_FD_MODE_RECVFROM_SENDTO. + * \paramin iofd osmo_io_fd for which recvfrom() has completed. + * \paramin res return value of the recvfrom() call, or -errno in case of error. + * \paramin msg message buffer containing the read data. Ownership is transferred to the + * call-back, and it must make sure to msgb_free() it eventually! + * \paramin saddr socket-address of sender from which data was received. */ + void (*recvfrom_cb)(struct osmo_io_fd *iofd, int res, + struct msgb *msg, + const struct osmo_sockaddr *saddr); + /*! completion call-back function when sendto() issued via osmo_iofd_sendto_msgb() has + * completed on fd. Only valid in OSMO_IO_FD_MODE_RECVFROM_SENDTO. + * \paramin iofd on which a sendto() has completed. + * \paramin res return value of the sendto() call, or -errno in case of error. + * \paramin msg message buffer whose write has completed. Ownership is *not* transferred to the + * call-back; it is automatically freed after the call-back terminates! + * \paramin daddr socket-address of destination to which data was sent. */ + void (*sendto_cb)(struct osmo_io_fd *iofd, int res, + struct msgb *msg, + const struct osmo_sockaddr *daddr); + }; + + /* mode OSMO_IO_FD_MODE_RECVMSG_SENDMSG: */ + struct { + /*! completion call-back function when recvmsg(2) has completed. + * Only valid in OSMO_IO_FD_MODE_RECVMSG_SENDMSG. + * \paramin iofd osmo_io_fd for which recvmsg() has completed. + * \paramin res return value of the recvmsg() call, or -errno in case of error. + * \paramin msg message buffer containing the read data. Ownership is transferred to the + * call-back, and it must make sure to msgb_free() it eventually! + * \paramin msgh msghdr containing metadata related to the recvmsg call. Only valid until + * call-back ends. */ + void (*recvmsg_cb)(struct osmo_io_fd *iofd, int res, + struct msgb *msg, const struct msghdr *msgh); + /*! completion call-back function when sendmsg() issued via osmo_iofd_sendmsg_msgb() has + * completed on fd. Only valid in Only valid in OSMO_IO_FD_MODE_RECVMSG_SENDMSG. + * \paramin iofd on which a sendmsg() has completed. + * \paramin res return value of the sendmsg() call, or -errno in case of error. + * \paramin msg message buffer whose write has completed. Ownership is *not* transferred to the + * call-back; it is automatically freed after the call-back terminates! */ + void (*sendmsg_cb)(struct osmo_io_fd *iofd, int res, struct msgb *msg); }; }; -void osmo_io_init(void); +void osmo_iofd_init(void); struct osmo_io_fd *osmo_iofd_setup(const void *ctx, int fd, const char *name, enum osmo_io_fd_mode mode, const struct osmo_io_ops *ioops, void *data); +int osmo_iofd_set_cmsg_size(struct osmo_io_fd *iofd, size_t cmsg_size); int osmo_iofd_register(struct osmo_io_fd *iofd, int fd); int osmo_iofd_unregister(struct osmo_io_fd *iofd); unsigned int osmo_iofd_txqueue_len(struct osmo_io_fd *iofd); @@ -85,6 +210,8 @@ int osmo_iofd_write_msgb(struct osmo_io_fd *iofd, struct msgb *msg); int osmo_iofd_sendto_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendto_flags, const struct osmo_sockaddr *dest); +int osmo_iofd_sendmsg_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendmsg_flags, + const struct msghdr *msgh); void osmo_iofd_set_alloc_info(struct osmo_io_fd *iofd, unsigned int size, unsigned int headroom); void osmo_iofd_set_txqueue_max_length(struct osmo_io_fd *iofd, unsigned int size); @@ -98,4 +225,7 @@ const char *osmo_iofd_get_name(const struct osmo_io_fd *iofd); void osmo_iofd_set_name(struct osmo_io_fd *iofd, const char *name); -void osmo_iofd_set_ioops(struct osmo_io_fd *iofd, const struct osmo_io_ops *ioops); +int osmo_iofd_set_ioops(struct osmo_io_fd *iofd, const struct osmo_io_ops *ioops); +void osmo_iofd_get_ioops(struct osmo_io_fd *iofd, struct osmo_io_ops *ioops); + +/*! @} */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/sockaddr_str.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/sockaddr_str.h
Changed
@@ -34,6 +34,7 @@ struct sockaddr_storage; struct sockaddr_in; struct sockaddr_in6; +struct osmo_sockaddr; /*! \defgroup sockaddr_str IP address/port utilities. * @{ @@ -84,6 +85,7 @@ int osmo_sockaddr_str_from_sockaddr_in(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_in *src); int osmo_sockaddr_str_from_sockaddr_in6(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_in6 *src); int osmo_sockaddr_str_from_sockaddr(struct osmo_sockaddr_str *sockaddr_str, const struct sockaddr_storage *src); +int osmo_sockaddr_str_from_osa(struct osmo_sockaddr_str *sockaddr_str, const struct osmo_sockaddr *src); int osmo_sockaddr_str_to_in_addr(const struct osmo_sockaddr_str *sockaddr_str, struct in_addr *dst); int osmo_sockaddr_str_to_in6_addr(const struct osmo_sockaddr_str *sockaddr_str, struct in6_addr *dst); @@ -92,6 +94,7 @@ int osmo_sockaddr_str_to_sockaddr_in(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_in *dst); int osmo_sockaddr_str_to_sockaddr_in6(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_in6 *dst); int osmo_sockaddr_str_to_sockaddr(const struct osmo_sockaddr_str *sockaddr_str, struct sockaddr_storage *dst); +int osmo_sockaddr_str_to_osa(const struct osmo_sockaddr_str *sockaddr_str, struct osmo_sockaddr *dst); int osmo_sockaddr_str_from_32n(struct osmo_sockaddr_str *sockaddr_str, uint32_t ip, uint16_t port) OSMO_DEPRECATED("osmo_sockaddr_str_from_32n() actually uses *host* byte order. Use osmo_sockaddr_str_from_32h() instead");
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/socket.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/socket.h
Changed
@@ -16,12 +16,24 @@ #include <osmocom/core/defs.h> +/*! maximum number of local or remote addresses supported by an osmo_sock instance */ +#define OSMO_SOCK_MAX_ADDRS 32 + /*! maximum length of a socket name ("r=1.2.3.4:123<->l=5.6.7.8:987") */ #define OSMO_SOCK_NAME_MAXLEN (2 + INET6_ADDRSTRLEN + 1 + 5 + 3 + 2 + INET6_ADDRSTRLEN + 1 + 5 + 1) +/*! maximum length of a multi-address socket peer (endpoint) name: (5.6.7.8|::9):987 + * char '(' + OSMO_STREAM_MAX_ADDRS - 1 addr separators + chars "):" + port buffer + char '\0' + */ +#define OSMO_SOCK_MULTIADDR_PEER_STR_MAXLEN (INET6_ADDRSTRLEN * OSMO_SOCK_MAX_ADDRS + INET6_ADDRSTRLEN + 2 + 6 + 1) +/*! maximum length of a multia-address socket name ("r=(::2|1.2.3.4):123<->l=(5.6.7.8|::9):987") */ +#define OSMO_SOCK_MULTIADDR_NAME_MAXLEN (OSMO_SOCK_MULTIADDR_PEER_STR_MAXLEN + 7) + + struct sockaddr_in; struct sockaddr; struct osmo_fd; +struct sctp_paddrinfo; struct osmo_sockaddr { union { @@ -74,6 +86,7 @@ int osmo_sockaddr_to_octets(uint8_t *dst, size_t dst_maxlen, const struct osmo_sockaddr *os); int osmo_sockaddr_from_octets(struct osmo_sockaddr *os, const void *src, size_t src_len); +int osmo_sockaddr_from_str_and_uint(struct osmo_sockaddr *osa_out, const char *ipstr, uint16_t port); int osmo_sockaddr_netmask_to_prefixlen(const struct osmo_sockaddr *addr); @@ -106,9 +119,6 @@ #define GET_OSMO_SOCK_F_PRIO(f) (((f) >> 16) & 0xff) -/*! maximum number of local or remote addresses supported by an osmo_sock instance */ -#define OSMO_SOCK_MAX_ADDRS 32 - int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, const char *host, uint16_t port, unsigned int flags); @@ -154,7 +164,6 @@ const char **remote_hosts, size_t remote_hosts_cnt, uint16_t remote_port, unsigned int flags, struct osmo_sock_init2_multiaddr_pars *pars); - int osmo_sock_init_osa(uint16_t type, uint8_t proto, const struct osmo_sockaddr *local, const struct osmo_sockaddr *remote, @@ -191,6 +200,14 @@ int osmo_sock_get_remote_ip(int fd, char *host, size_t len); int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len); +int osmo_sock_multiaddr_get_ip_and_port(int fd, int ip_proto, char *ip, size_t *ip_cnt, size_t ip_len, + char *port, size_t port_len, bool local); +int osmo_multiaddr_ip_and_port_snprintf(char *str, size_t str_len, + const char *ip, size_t ip_cnt, size_t ip_len, + const char *portbuf); +int osmo_sock_multiaddr_get_name_buf(char *str, size_t str_len, int fd, int sk_proto); +int osmo_sock_multiaddr_add_local_addr(int sfd, const char **addrs, size_t addrs_cnt); +int osmo_sock_multiaddr_del_local_addr(int sfd, const char **addrs, size_t addrs_cnt); int osmo_sock_mcast_loop_set(int fd, bool enable); int osmo_sock_mcast_ttl_set(int fd, uint8_t ttl); @@ -203,5 +220,7 @@ int osmo_sock_set_dscp(int fd, uint8_t dscp); int osmo_sock_set_priority(int fd, int prio); +int osmo_sock_sctp_get_peer_addr_info(int fd, struct sctp_paddrinfo *pinfo, size_t *pinfo_cnt); + #endif /* (!EMBEDDED) */ /*! @} */
View file
libosmocore_1.10.0.tar.xz/include/osmocom/core/soft_uart.h
Added
@@ -0,0 +1,149 @@ +#pragma once + +/*! \file soft_uart.h + * Software UART implementation. */ +/* + * (C) 2022 by Harald Welte <laforge@gnumonks.org> + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 2 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. + * + */ + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/bits.h> +#include <osmocom/core/msgb.h> + +/*! Parity mode. + * https://en.wikipedia.org/wiki/Parity_bit */ +enum osmo_soft_uart_parity_mode { + OSMO_SUART_PARITY_NONE, /*!< No parity bit */ + OSMO_SUART_PARITY_EVEN, /*!< Even parity */ + OSMO_SUART_PARITY_ODD, /*!< Odd parity */ + OSMO_SUART_PARITY_MARK, /*!< Always 1 */ + OSMO_SUART_PARITY_SPACE, /*!< Always 0 */ + _OSMO_SUART_PARITY_NUM +}; + +/*! Flags passed to the application. */ +enum osmo_soft_uart_flags { + OSMO_SUART_F_FRAMING_ERROR = (1 << 0), /*!< Framing error occurred */ + OSMO_SUART_F_PARITY_ERROR = (1 << 1), /*!< Parity error occurred */ + OSMO_SUART_F_BREAK = (1 << 2), /*!< Break condition (not implemented) */ +}; + +/*! Modem status "line" flags. + * https://en.wikipedia.org/wiki/RS-232#Data_and_control_signals */ +enum osmo_soft_uart_status { + OSMO_SUART_STATUS_F_DTR = (1 << 0), /*!< Data Terminal Ready */ + OSMO_SUART_STATUS_F_DCD = (1 << 1), /*!< Data Carrier Detect */ + OSMO_SUART_STATUS_F_DSR = (1 << 2), /*!< Data Set Ready */ + OSMO_SUART_STATUS_F_RI = (1 << 3), /*!< Ring Indicator */ + OSMO_SUART_STATUS_F_RTS_RTR = (1 << 4), /*!< Request To Send or Ready To Receive */ + OSMO_SUART_STATUS_F_CTS = (1 << 5), /*!< Clear To Send */ +}; + +/*! Flow control mode. + * https://en.wikipedia.org/wiki/Flow_control_(data)#Hardware_flow_control */ +enum osmo_soft_uart_flow_ctrl_mode { + /*! No flow control */ + OSMO_SUART_FLOW_CTRL_NONE, + /*! DTR/DSR flow control: Tx if DSR is active and drop DTR if cannot Rx anymore. */ + OSMO_SUART_FLOW_CTRL_DTR_DSR, + /*! RTS/CTS flow control: Tx if CTS is active and drop RTS if cannot Rx anymore. + * The technically correct name would be RTR/CTS, because the RTS signal actually + * indicates readiness to *receive* data (Ready To Receive), and not really used + * to request a transmission (Request To Send) nowadays. Alternatively, the RTS + * signal can be interpreted as "Request To Send to me". */ + OSMO_SUART_FLOW_CTRL_RTS_CTS, +}; + +/*! Configuration for a soft-UART. */ +struct osmo_soft_uart_cfg { + /*! Number of data bits (typically 5, 6, 7 or 8). */ + uint8_t num_data_bits; + /*! Number of stop bits (typically 1 or 2). */ + uint8_t num_stop_bits; + /*! Parity mode (none, even, odd, space, mark). */ + enum osmo_soft_uart_parity_mode parity_mode; + /*! Size of the receive buffer; UART will buffer up to that number + * of characters before calling the receive call-back. */ + unsigned int rx_buf_size; + /*! Receive timeout; UART will flush the receive buffer via the receive call-back + * after indicated number of milliseconds, even if it is not full yet. */ + unsigned int rx_timeout_ms; + + /*! Opaque application-private data; passed to call-backs. */ + void *priv; + + /*! Receive call-back of the application. + * + * Called if at least one of the following conditions is met: + * a) rx_buf_size characters were received (Rx buffer is full); + * b) rx_timeout_ms expired and Rx buffer is not empty; + * c) a parity or framing error is occurred. + * + * \paramin priv opaque application-private data. + * \paramin rx_data msgb holding the received data. + * Must be free()ed by the application. + * \paramin flags bit-mask of OSMO_SUART_F_*. */ + void (*rx_cb)(void *priv, struct msgb *rx_data, unsigned int flags); + + /*! Transmit call-back of the application. + * + * The implementation is expected to provide at most tx_data->data_len + * characters (the actual amount is determined by the number of requested + * bits and the effective UART configuration). + * + * \paramin priv opaque application-private data. + * \paraminout tx_data msgb for writing to be transmitted data. */ + void (*tx_cb)(void *priv, struct msgb *tx_data); + + /*! Modem status line change call-back. + * \paramin priv opaque application-private data. + * \paramin status updated status; bit-mask of OSMO_SUART_STATUS_F_*. */ + void (*status_change_cb)(void *priv, unsigned int status); + + /*! "Hardware" flow control mode. */ + enum osmo_soft_uart_flow_ctrl_mode flow_ctrl_mode; +}; + +extern const struct osmo_soft_uart_cfg osmo_soft_uart_default_cfg; + +struct osmo_soft_uart; + +struct osmo_soft_uart *osmo_soft_uart_alloc(void *ctx, const char *name, + const struct osmo_soft_uart_cfg *cfg); +void osmo_soft_uart_free(struct osmo_soft_uart *suart); +int osmo_soft_uart_configure(struct osmo_soft_uart *suart, const struct osmo_soft_uart_cfg *cfg); + +const char *osmo_soft_uart_get_name(const struct osmo_soft_uart *suart); +void osmo_soft_uart_set_name(struct osmo_soft_uart *suart, const char *name); + +int osmo_soft_uart_set_rx(struct osmo_soft_uart *suart, bool enable); +int osmo_soft_uart_set_tx(struct osmo_soft_uart *suart, bool enable); + +int osmo_soft_uart_rx_ubits(struct osmo_soft_uart *suart, const ubit_t *ubits, size_t n_ubits); +int osmo_soft_uart_tx_ubits(struct osmo_soft_uart *suart, ubit_t *ubits, size_t n_ubits); + +unsigned int osmo_soft_uart_get_status(const struct osmo_soft_uart *suart); +int osmo_soft_uart_set_status(struct osmo_soft_uart *suart, unsigned int status); +void osmo_soft_uart_set_status_line(struct osmo_soft_uart *suart, + enum osmo_soft_uart_status line, + bool active); + +void osmo_soft_uart_flush_rx(struct osmo_soft_uart *suart);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/tdef.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/tdef.h
Changed
@@ -121,11 +121,13 @@ const struct osmo_tdef_state_timeout *osmo_tdef_get_state_timeout(uint32_t state, const struct osmo_tdef_state_timeout *timeouts_array); -/*! Call osmo_fsm_inst_state_chg() or osmo_fsm_inst_state_chg_keep_timer(), depending on the timeouts_array, tdefs and - * default_timeout. +/*! Call osmo_fsm_inst_state_chg_ms() or osmo_fsm_inst_state_chg_keep_timer_ms(), + * depending on the timeouts_array, tdefs and default_timeout. * - * A T timer configured in sub-second precision is rounded up to the next full second. A timer in unit = - * OSMO_TDEF_CUSTOM is applied as if the unit is in seconds (i.e. this macro does not make sense for custom units!). + * A timer defined with sub-millisecond precision (e.g OSMO_TDEF_US) is rounded up to the next full millisecond. + * A timer value defined in units higher than millisecond (e.g. OSMO_TDEF_S, OSMO_TDEF_M) is converted to milliseconds. + * A timer in unit = OSMO_TDEF_CUSTOM is applied as if the unit is in seconds (i.e. this macro does not make sense + * for custom units!). * * See osmo_tdef_get_state_timeout() and osmo_tdef_get(). * @@ -153,9 +155,10 @@ * \paramin state State number to transition to. * \paramin timeouts_array Array of struct osmo_tdef_state_timeout32 to look up state in. * \paramin tdefs Array of struct osmo_tdef (last entry zero initialized) to look up T in. - * \paramin default_timeout If a T is set in timeouts_array, but no timeout value is configured for T, then use this - * default timeout value as fallback, or pass -1 to abort the program. - * \return Return value from osmo_fsm_inst_state_chg() or osmo_fsm_inst_state_chg_keep_timer(). + * \paramin default_timeout If a T is set in timeouts_array, but no timeout value is configured for T, + * then use this default timeout value (in seconds) as fallback, + * or pass a negative number to abort the program. + * \return Return value from osmo_fsm_inst_state_chg_ms() or osmo_fsm_inst_state_chg_keep_timer_ms(). */ #define osmo_tdef_fsm_inst_state_chg(fi, state, timeouts_array, tdefs, default_timeout) \ _osmo_tdef_fsm_inst_state_chg(fi, state, timeouts_array, tdefs, default_timeout, \
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/utils.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/utils.h
Changed
@@ -249,7 +249,7 @@ #define OSMO_STRBUF_APPEND(STRBUF, func, args...) do { \ if (!(STRBUF).pos) \ (STRBUF).pos = (STRBUF).buf; \ - size_t _sb_remain = (STRBUF).buf ? (STRBUF).len - ((STRBUF).pos - (STRBUF).buf) : 0; \ + size_t _sb_remain = OSMO_STRBUF_REMAIN(STRBUF); \ int _sb_l = func((STRBUF).pos, _sb_remain, ##args); \ if (_sb_l < 0 || (size_t)_sb_l > _sb_remain) \ (STRBUF).pos = (STRBUF).buf + (STRBUF).len; \ @@ -281,6 +281,38 @@ #define OSMO_STRBUF_PRINTF(STRBUF, fmt, args...) \ OSMO_STRBUF_APPEND(STRBUF, snprintf, fmt, ##args) +/*! Get remaining space for characters and terminating nul in the given struct osmo_strbuf. + * \paramin sb the string buffer to get the remaining space for. + * \returns remaining space in the given struct osmo_strbuf. */ +static inline size_t _osmo_strbuf_remain(const struct osmo_strbuf *sb) +{ + if (OSMO_UNLIKELY(sb == NULL || sb->buf == NULL)) + return 0; + if (sb->pos == NULL) + return sb->len; + return sb->len - (sb->pos - sb->buf); +} + +/*! Return remaining space for characters and terminating nul in the given struct osmo_strbuf. */ +#define OSMO_STRBUF_REMAIN(STRBUF) \ + _osmo_strbuf_remain(&(STRBUF)) + +/*! Get number of actual characters (without terminating nul) in the given struct osmo_strbuf. + * \paramin sb the string buffer to get the number of characters for. + * \returns number of actual characters (without terminating nul). */ +static inline size_t _osmo_strbuf_char_count(const struct osmo_strbuf *sb) +{ + if (OSMO_UNLIKELY(sb == NULL || sb->buf == NULL)) + return 0; + if (sb->pos == NULL || sb->pos <= sb->buf) + return 0; + return OSMO_MIN((size_t)(sb->pos - sb->buf), sb->len - 1); +} + +/*! Return number of actual characters contained in struct osmo_strbuf (without terminating nul). */ +#define OSMO_STRBUF_CHAR_COUNT(STRBUF) \ + _osmo_strbuf_char_count(&(STRBUF)) + /*! Like OSMO_STRBUF_APPEND(), but for function signatures that return the char* buffer instead of a length. * When using this function, the final STRBUF.chars_needed may not reflect the actual number of characters needed, since * that number cannot be obtained from this kind of function signature. @@ -292,7 +324,7 @@ #define OSMO_STRBUF_APPEND_NOLEN(STRBUF, func, args...) do { \ if (!(STRBUF).pos) \ (STRBUF).pos = (STRBUF).buf; \ - size_t _sb_remain = (STRBUF).buf ? (STRBUF).len - ((STRBUF).pos - (STRBUF).buf) : 0; \ + size_t _sb_remain = OSMO_STRBUF_REMAIN(STRBUF); \ if (_sb_remain) { \ func((STRBUF).pos, _sb_remain, ##args); \ } \ @@ -304,6 +336,16 @@ (STRBUF).chars_needed += _sb_l; \ } while(0) +void osmo_strbuf_drop_tail(struct osmo_strbuf *sb, size_t n_chars); +/* Convenience macro. struct osmo_strbuf are typically static to a function scope. Avoid having to type '&', same as + * with all the other OSMO_STRBUF_* API. */ +#define OSMO_STRBUF_DROP_TAIL(STRBUF, N_CHARS) osmo_strbuf_drop_tail(&(STRBUF), N_CHARS) + +void osmo_strbuf_added_tail(struct osmo_strbuf *sb, size_t n_chars); +/* Convenience macro. struct osmo_strbuf are typically static to a function scope. Avoid having to type '&', same as + * with all the other OSMO_STRBUF_* API. */ +#define OSMO_STRBUF_ADDED_TAIL(STRBUF, N_CHARS) osmo_strbuf_added_tail(&(STRBUF), N_CHARS) + bool osmo_str_startswith(const char *str, const char *startswith_str); int osmo_float_str_to_int(int64_t *val, const char *str, unsigned int precision);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/core/write_queue.h -> libosmocore_1.10.0.tar.xz/include/osmocom/core/write_queue.h
Changed
@@ -50,6 +50,7 @@ void osmo_wqueue_clear(struct osmo_wqueue *queue); int osmo_wqueue_enqueue(struct osmo_wqueue *queue, struct msgb *data); int osmo_wqueue_enqueue_quiet(struct osmo_wqueue *queue, struct msgb *data); +size_t osmo_wqueue_set_maxlen(struct osmo_wqueue *queue, unsigned int len); int osmo_wqueue_bfd_cb(struct osmo_fd *fd, unsigned int what); /*! @} */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/ctrl/control_cmd.h -> libosmocore_1.10.0.tar.xz/include/osmocom/ctrl/control_cmd.h
Changed
@@ -24,6 +24,7 @@ CTRL_NODE_TS, /* TS specific (net.btsN.trxM.tsI.) */ CTRL_NODE_FSM, /* Finite State Machine (description) */ CTRL_NODE_FSM_INST, /* Finite State Machine (instance) */ + CTRL_NODE_LCHAN, /* LCHAN specific (net.btsN.trxM.tsI.lchanL) */ _LAST_CTRL_NODE }; @@ -123,6 +124,7 @@ int ctrl_cmd_exec(vector vline, struct ctrl_cmd *command, vector node, void *data); int ctrl_cmd_install(enum ctrl_node_type node, struct ctrl_cmd_element *cmd); +/* ctrl_cmd_send is also declared in control_if.h, but legacy openbsc.git expects it here */ int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd); int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd); struct ctrl_cmd *ctrl_cmd_parse3(void *ctx, struct msgb *msg, bool *parse_failed);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/ctrl/control_if.h -> libosmocore_1.10.0.tar.xz/include/osmocom/ctrl/control_if.h
Changed
@@ -28,7 +28,8 @@ }; -int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd); +int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd) OSMO_DEPRECATED("Use ctrl_cmd_send2() instead."); +int ctrl_cmd_send2(struct ctrl_connection *ccon, struct ctrl_cmd *cmd); int ctrl_cmd_send_trap(struct ctrl_handle *ctrl, const char *name, char *value); struct ctrl_handle *ctrl_handle_alloc(void *ctx, void *data, ctrl_cmd_lookup lookup); struct ctrl_handle *ctrl_handle_alloc2(void *ctx, void *data,
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/Makefile.am -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/Makefile.am
Changed
@@ -48,7 +48,9 @@ l1sap.h \ oap.h \ oap_client.h \ + rlp.h \ rsl.h \ + rtp_extensions.h \ rxlev_stat.h \ sysinfo.h \ tlv.h \
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/bts_features.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/bts_features.h
Changed
@@ -36,6 +36,8 @@ BTS_FEAT_OSMUX, /* Osmux (Osmocom RTP muxing) support */ BTS_FEAT_VBS, /* Voice Broadcast Service support, 3GPP TS 43.069 */ BTS_FEAT_VGCS, /* Voice Group Call Service support, 3GPP TS 44.068 */ + BTS_FEAT_TWTS001, /* TW-TS-001: enhanced RTP transport for FR & EFR */ + BTS_FEAT_TWTS002, /* TW-TS-002: enhanced RTP transport for HRv1 */ _NUM_BTS_FEAT };
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/cbsp.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/cbsp.h
Changed
@@ -312,3 +312,4 @@ struct osmo_cbsp_decoded *osmo_cbsp_decoded_alloc(void *ctx, enum cbsp_msg_type msg_type); int osmo_cbsp_recv_buffered(void *ctx, int fd, struct msgb **rmsg, struct msgb **tmp_msg); +int osmo_cbsp_segmentation_cb(struct msgb *msg);
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/gsm0502.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/gsm0502.h
Changed
@@ -64,6 +64,25 @@ #define GSM_NBITS_AB_GMSK_TAIL GSM_NBITS_NB_GMSK_TAIL #define GSM_NBITS_AB_GMSK_BURST GSM_NBITS_NB_GMSK_BURST +/*! Compare the given TDMA FNs, taking the wrapping into account. + * \paramin fn1 First TDMA Fn value to compare. + * \paramin fn2 Second TDMA Fn value to compare. + * \returns similarly to memcmp(), -1 if fn1 goes before fn2; + * 0 if fn1 equals fn2; + * 1 if fn1 goes after fn2. */ +static inline int gsm0502_fncmp(uint32_t fn1, uint32_t fn2) +{ + const uint32_t thresh = GSM_TDMA_HYPERFRAME / 2; + + if (fn1 == fn2) + return 0; + if ((fn1 < fn2 && (fn2 - fn1) < thresh) || + (fn1 > fn2 && (fn1 - fn2) > thresh)) + return -1; + + return 1; +} + /* Table 5 Clause 7 TS 05.02 */ static inline unsigned int gsm0502_get_n_pag_blocks(const struct gsm48_control_channel_descr *chan_desc)
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/gsup.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/gsup.h
Changed
@@ -37,9 +37,13 @@ * */ #pragma once +#if (!EMBEDDED) #include <stdint.h> #include <osmocom/core/msgb.h> +#include <osmocom/core/defs.h> +#include <osmocom/core/endian.h> +#include <osmocom/core/socket.h> #include <osmocom/gsm/gsup_sms.h> #include <osmocom/gsm/protocol/gsm_23_003.h> #include <osmocom/gsm/protocol/gsm_03_40.h> @@ -57,8 +61,7 @@ /*! Maximum number of octets encoding MSISDN in BCD format */ #define OSMO_GSUP_MAX_MSISDN_LEN 9 #define OSMO_GSUP_MAX_CALLED_PARTY_BCD_LEN 43 /* TS 24.008 10.5.4.7 */ - -#define OSMO_GSUP_PDP_TYPE_SIZE 2 +#define OSMO_GSUP_MAX_PCO_LEN 251 /*! Information Element Identifiers for GSUP IEs */ enum osmo_gsup_iei { @@ -71,12 +74,14 @@ OSMO_GSUP_FREEZE_PTMSI_IE = 0x07, OSMO_GSUP_MSISDN_IE = 0x08, OSMO_GSUP_HLR_NUMBER_IE = 0x09, - OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a, + OSMO_GSUP_MESSAGE_CLASS_IE = 0x0a, OSMO_GSUP_PDP_CONTEXT_ID_IE = 0x10, - OSMO_GSUP_PDP_TYPE_IE = 0x11, + OSMO_GSUP_PDP_ADDRESS_IE = 0x11, +#define OSMO_GSUP_PDP_TYPE_IE OSMO_GSUP_PDP_ADDRESS_IE /* Backward compat */ OSMO_GSUP_ACCESS_POINT_NAME_IE = 0x12, OSMO_GSUP_PDP_QOS_IE = 0x13, OSMO_GSUP_CHARG_CHAR_IE = 0x14, + OSMO_GSUP_PCO_IE = 0x15, OSMO_GSUP_RAND_IE = 0x20, OSMO_GSUP_SRES_IE = 0x21, OSMO_GSUP_KC_IE = 0x22, @@ -198,6 +203,10 @@ OSMO_GSUP_MSGT_E_ABORT = 0b01001011, OSMO_GSUP_MSGT_ROUTING_ERROR = 0b01001110, + + OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST = 0b01010000, + OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR = 0b01010001, + OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT = 0b01010010, }; #define OSMO_GSUP_MSGT_E_ROUTING_ERROR OSMO_GSUP_MSGT_ROUTING_ERROR @@ -256,8 +265,20 @@ struct osmo_gsup_pdp_info { unsigned int context_id; int have_info; - /*! Type of PDP context */ - uint16_t pdp_type; + /*! Type of PDP context, 3GPP TS 29.060, 7.7.27 */ + union { + uint16_t pdp_type OSMO_DEPRECATED("use pdp_type_org and pdp_type_nr instead"); + struct { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */ + uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */ +#elif OSMO_IS_BIG_ENDIAN + uint8_t pdp_type_org; /* enum gsm48_pdp_type_org */ + uint8_t pdp_type_nr; /* enum gsm48_pdp_type_nr */ +#endif + }; + }; + struct osmo_sockaddr pdp_address2; /*! APN information, still in encoded form. Can be NULL if no * APN information included */ const uint8_t *apn_enc; @@ -281,6 +302,7 @@ OSMO_GSUP_MESSAGE_CLASS_SMS = 2, OSMO_GSUP_MESSAGE_CLASS_USSD = 3, OSMO_GSUP_MESSAGE_CLASS_INTER_MSC = 4, + OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG = 5, /* Keep this as last entry with a value of max(enum osmo_gsup_message_class) + 1. * This value shall serve as the size for an array to aid de-muxing all known GSUP classes. */ OSMO_GSUP_MESSAGE_CLASS_ARRAYSIZE @@ -386,6 +408,12 @@ enum osmo_rat_type current_rat_type; enum osmo_rat_type supported_rat_types8; /*!< arbitrary choice */ size_t supported_rat_types_len; + + /*! PCO protocol option 3GPP TS 24.008 10.5.6.3 / Table 10.5.136. PCO contains Octet 3-ZA */ + const uint8_t *pco; + /*! Number of bytes of the PCO. */ + size_t pco_len; + }; int osmo_gsup_decode(const uint8_t *data, size_t data_len, @@ -394,4 +422,5 @@ int osmo_gsup_get_err_msg_type(enum osmo_gsup_message_type type_in) OSMO_DEPRECATED("Use OSMO_GSUP_TO_MSGT_ERROR() instead"); +#endif /* (!EMBEDDED) */ /*! @} */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/l1sap.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/l1sap.h
Changed
@@ -27,6 +27,8 @@ PRIM_INFO_MODIFY, /*!< Mode Modify of channel */ PRIM_INFO_ACT_CIPH, /*!< Activation of ciphering */ PRIM_INFO_DEACT_CIPH, /*!< Deactivation of ciphering */ + PRIM_INFO_ACT_UL_ACC, /*!< Activation of uplink access detection */ + PRIM_INFO_DEACT_UL_ACC, /*!< Deactivation of uplink access detection */ }; /*! PH-DATA presence information */ @@ -142,6 +144,11 @@ uint8_t uplink; /*!< Apply to uplink */ }; +/*! for {ACT_UL_ACC,DEACT_UL_ACC} MPH-INFO.req */ +struct info_ulacc_req_param { + uint8_t chan_nr; /*!< Channel Number (Like RSL) */ +}; + /*! for MPH-INFO.ind */ struct mph_info_param { enum osmo_mph_info_type type; /*!< Info message type */ @@ -151,6 +158,7 @@ struct info_act_req_param act_req; struct info_act_cnf_param act_cnf; struct info_ciph_req_param ciph_req; + struct info_ulacc_req_param ulacc_req; } u; };
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/lapdm.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/lapdm.h
Changed
@@ -33,6 +33,10 @@ struct lapdm_msg_ctx mctx; /*!< context of established connection */ struct lapdm_entity *entity; /*!< LAPDm entity we are part of */ + + struct llist_head tx_ui_queue; /*!< UI frames to L1 */ + uint32_t t200_fn; /*!< T200 timer in frames */ + uint32_t t200_timeout; /*!< T200 timeout frame number */ }; /*! LAPDm datalink SAPIs */ @@ -46,6 +50,8 @@ #define LAPDM_ENT_F_EMPTY_FRAME 0x0001 #define LAPDM_ENT_F_POLLING_ONLY 0x0002 +#define LAPDM_ENT_F_DROP_2ND_REJ 0x0004 +#define LAPDM_ENT_F_RTS 0x0008 /*! a LAPDm Entity */ struct lapdm_entity { @@ -119,6 +125,11 @@ void lapdm_entity_set_flags(struct lapdm_entity *le, unsigned int flags); void lapdm_channel_set_flags(struct lapdm_channel *lc, unsigned int flags); +void lapdm_entity_set_t200_fn(struct lapdm_entity *le, const uint32_t *t200_fn); +void lapdm_channel_set_t200_fn(struct lapdm_channel *lc, const uint32_t *t200_fn_dcch, const uint32_t *t200_fn_acch); + int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp); +int lapdm_phsap_dequeue_prim_fn(struct lapdm_entity *le, struct osmo_phsap_prim *pp, uint32_t fn); +void lapdm_t200_fn(struct lapdm_entity *le, uint32_t fn); /*! @} */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/protocol/gsm_04_08.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/protocol/gsm_04_08.h
Changed
@@ -2210,8 +2210,31 @@ GSM48_BCAP_MT_AUTO_1 = 8, }; +/*! Table 10.5.112/3GPP TS 24.008: Other modem type (octet 6d) */ +enum gsm48_bcap_other_modem_type { + GSM48_BCAP_OTHER_MT_NONE = 0, /*!< No other modem type specified */ + GSM48_BCAP_OTHER_MT_V34 = 2, /*!< According to ITU-T Rec. V.34 */ +}; + +/*! Table 10.5.112/3GPP TS 24.008: Fixed network user rate (octet 6d) */ +enum gsm48_bcap_fixed_net_user_rate { + GSM48_BCAP_FNUR_NONE = 0, /*!< FNUR not applicable / No meaning associated */ + GSM48_BCAP_FNUR_X1_V110_9600 = 1, /*!< 9.6 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_14400 = 2, /*!< 14.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_19200 = 3, /*!< 19.2 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_28800 = 4, /*!< 28.8 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_38400 = 5, /*!< 38.4 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_48000 = 6, /*!< 48.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_X1_V110_56000 = 7, /*!< 56.0 kbit/s (according to ITU-T Rec. X.1 and V.110) */ + GSM48_BCAP_FNUR_BT_64000 = 8, /*!< 64.0 kbit/s bit transparent */ + GSM48_BCAP_FNUR_BT_33600 = 9, /*!< 33.6 kbit/s bit transparent */ + GSM48_BCAP_FNUR_I460_32000 = 10, /*!< 32.0 kbit/s (according to ITU-T Rec. I.460) */ + GSM48_BCAP_FNUR_V34_31200 = 11, /*!< 31.2 kbit/s (according to ITU-T Rec. V.34) */ +}; + /*! GSM 04.08 Bearer Capability: Speech Version Indication - * (See also 3GPP TS 24.008, Table 10.5.103) */ + * (See also 3GPP TS 24.008, Table 10.5.103 + * and 3GPP TS 26.103, Table 4.1 "Support of Codec Types in Radio Access Technologies") */ enum gsm48_bcap_speech_ver { GSM48_BCAP_SV_FR = 0, /*!< GSM FR V1 (GSM FR) */ GSM48_BCAP_SV_HR = 1, /*!< GSM HR V1 (GSM HR) */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/protocol/gsm_04_08_gprs.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/protocol/gsm_04_08_gprs.h
Changed
@@ -294,10 +294,11 @@ PDP_S_MODIFY_PENDING, }; -/* Table 10.5.155/3GPP TS 24.008 */ +/* TS 24.008 Table 10.5.155/3GPP */ enum gsm48_pdp_type_org { PDP_TYPE_ORG_ETSI = 0x00, PDP_TYPE_ORG_IETF = 0x01, + PDP_TYPE_ORG_EMPTY = 0x0f, }; enum gsm48_pdp_type_nr { PDP_TYPE_N_ETSI_RESERVED = 0x00, @@ -306,6 +307,39 @@ PDP_TYPE_N_IETF_IPv6 = 0x57, PDP_TYPE_N_IETF_IPv4v6 = 0x8D, }; +/* TS 24.008 10.5.6.4 "Packet data protocol address" value + * Note: This can be reused for 3GPP TS 29.060 7.7.27 "End User Address" + * with minor changes in the values, like spare being 1111 instead. +*/ +struct gsm48_pdp_address { +#if OSMO_IS_LITTLE_ENDIAN +uint8_t organization:4, /* enum gsm48_pdp_type_org */ + spare:4; /* 0000 */ +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ +uint8_t spare:4, organization:4; +#endif +uint8_t type; /* enum gsm48_pdp_type_nr */ + union { + /* PDP_TYPE_ORG_ETSI */ + union { + } etsi; + /* PDP_TYPE_ORG_IETF */ + union { + /* PDP_TYPE_N_IETF_IPv4 */ + uint32_t v4; + + /* PDP_TYPE_N_IETF_IPv6 */ + uint8_t v616; + + /* PDP_TYPE_N_IETF_IPv4v6 */ + struct { + uint32_t v4; + uint8_t v616; + } __attribute__ ((packed)) v4v6; + } ietf; + }; +} __attribute__ ((packed)); /* Figure 10.5.138/24.008 / Chapter 10.5.6.5 */ enum gsm48_qos_reliab_class {
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/protocol/gsm_04_11.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/protocol/gsm_04_11.h
Changed
@@ -62,6 +62,16 @@ GSM411_IE_RP_CAUSE = 0x42, /* 8.2.5.4 */ }; +/* Sections 8.2.5.1 and 8.2.5.2 set limits on the length of an SMSC-address. + * The spec states these limits in terms of min and max values of the length + * octet in type 4 IEs SM-RP-OA and SM-RP-DA; these IE length limits translate + * into a minimum of 1 digit and a maximum of 20 digits. + */ +#define GSM411_SMSC_ADDR_MIN_OCTETS 2 +#define GSM411_SMSC_ADDR_MAX_OCTETS 11 +#define GSM411_SMSC_ADDR_MIN_DIGITS 1 +#define GSM411_SMSC_ADDR_MAX_DIGITS 20 + /* Chapter 8.2.5.4 Table 8.4 */ enum gsm411_rp_cause { /* valid only for MO */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/protocol/gsm_08_08.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/protocol/gsm_08_08.h
Changed
@@ -332,9 +332,10 @@ GSM0808_IE_PS_REGISTERED_OPERATOR = 0x99, GSM0808_IE_CS_REGISTERED_OPERATOR = 0x9a, - /* Osmocom extensions: */ + /* Osmocom and Themyscira extensions: */ GSM0808_IE_OSMO_OSMUX_SUPPORT = 0xf0, GSM0808_IE_OSMO_OSMUX_CID = 0xf1, + GSM0808_IE_THEMWI_RTP_EXTENSIONS = 0xf2, }; /* 3GPP TS 48.008 3.2.3 Signalling Field Element Coding.
View file
libosmocore_1.9.3.tar.xz/include/osmocom/gsm/protocol/gsm_08_58.h -> libosmocore_1.10.0.tar.xz/include/osmocom/gsm/protocol/gsm_08_58.h
Changed
@@ -29,6 +29,7 @@ /* Channel Number 9.3.1 */ union abis_rsl_chan_nr { + struct { #if OSMO_IS_BIG_ENDIAN uint8_t cbits:5, tn:3; @@ -36,7 +37,8 @@ uint8_t tn:3, cbits:5; #endif - uint8_t chan_nr; + } __attribute__ ((packed)); + uint8_t chan_nr; } __attribute__ ((packed)); #define ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs 0x01 #define ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(ss) (0x02 + (ss)) @@ -55,6 +57,7 @@ /* Link Identifier 9.3.2 */ union abis_rsl_link_id { + struct { #if OSMO_IS_BIG_ENDIAN uint8_t cbits:2, na:1, @@ -66,7 +69,8 @@ na:1, cbits:2; #endif - uint8_t link_id; + } __attribute__ ((packed)); + uint8_t link_id; } __attribute__ ((packed)); #define ABIS_RSL_LINK_ID_CBITS_FACCH_SDCCH 0x00 #define ABIS_RSL_LINK_ID_CBITS_SACCH 0x01 @@ -369,6 +373,7 @@ RSL_IE_OSMO_TRAINING_SEQUENCE = 0x61, RSL_IE_OSMO_TEMP_OVP_ACCH_CAP = 0x62, RSL_IE_OSMO_OSMUX_CID = 0x63, + RSL_IE_OSMO_RTP_EXTENSIONS = 0x64, /* ip.access */ RSL_IE_IPAC_SRTP_CONFIG = 0xe0,
View file
libosmocore_1.10.0.tar.xz/include/osmocom/gsm/rlp.h
Added
@@ -0,0 +1,81 @@ +/* + * GSM RLP (Radio Link Protocol) as used in CSD (3GPP TS 44.022) + * + * Copyright (C) 2022-2023 Harald Welte <laforge@osmocom.org> + * + * All Rights Reserved + * + * 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 2 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. + */ + + + +#pragma once +#include <stdint.h> +#include <stdbool.h> +#include <osmocom/core/utils.h> + +/*! \defgroup rlp GSM RLP (Radio Link Protocol) as used in CSD (3GPP TS 24.022) + * @{ + * \file rlp.h */ + +/*! RLP frame type as per 3GPP TS 24.022 Section 5.2.1 */ +enum osmo_rlp_ftype { + OSMO_RLP_FT_U, + OSMO_RLP_FT_S, + OSMO_RLP_FT_IS, +}; +extern const struct value_string osmo_rlp_ftype_vals; + +/*! RLP U-Frame Type as per 3GPP TS 24.022 Section 5.2.1 */ +enum osmo_rlp_u_ftype { + OSMO_RLP_U_FT_SABM = 0x07, + OSMO_RLP_U_FT_UA = 0x0c, + OSMO_RLP_U_FT_DISC = 0x08, + OSMO_RLP_U_FT_DM = 0x03, + OSMO_RLP_U_FT_NULL = 0x0f, + OSMO_RLP_U_FT_UI = 0x00, + OSMO_RLP_U_FT_XID = 0x17, + OSMO_RLP_U_FT_TEST = 0x1c, + OSMO_RLP_U_FT_REMAP = 0x11, +}; +extern const struct value_string osmo_rlp_ftype_u_vals; + +/*! RLP S-Frame type as per 3GPP TS 24.022 Section 5.2.1 */ +enum osmo_rlp_s_ftype { + OSMO_RLP_S_FT_RR = 0, + OSMO_RLP_S_FT_REJ = 2, + OSMO_RLP_S_FT_RNR = 1, + OSMO_RLP_S_FT_SREJ = 3, +}; +extern const struct value_string osmo_rlp_ftype_s_vals; + +/*! Data structure representing one decoded RLP frame */ +struct osmo_rlp_frame_decoded { + uint8_t version; + enum osmo_rlp_ftype ftype; + enum osmo_rlp_u_ftype u_ftype; + enum osmo_rlp_s_ftype s_ftype; + bool c_r; + bool p_f; + uint8_t s_bits; + uint16_t n_s; + uint16_t n_r; + uint32_t fcs; + uint8_t info536/8; + uint16_t info_len; +}; + +int osmo_rlp_decode(struct osmo_rlp_frame_decoded *out, uint8_t version, const uint8_t *data, size_t data_len); +int osmo_rlp_encode(uint8_t *out, size_t out_size, const struct osmo_rlp_frame_decoded *in); +uint32_t osmo_rlp_fcs_compute(const uint8_t *in, size_t in_len); + +/*! @} */
View file
libosmocore_1.10.0.tar.xz/include/osmocom/gsm/rtp_extensions.h
Added
@@ -0,0 +1,23 @@ +/* + * Themyscira Wireless Technical Specification TW-TS-003 defines a BSSMAP + * extension whereby a CN implementation and a BSS implementation can + * negotiate the use of non-3GPP-standard extensions to RTP user plane, + * extensions that modify RTP formats counter to the stipulations of + * 3GPP TS 48.103. There is also a private Osmocom-defined IE in Abis RSL + * that communicates the same RTP extensions from OsmoBSC to OsmoBTS. + * + * This header file defines the meaning of the bits in the first (and currently + * only) value octet of the TLV IE added to BSSMAP and RSL interfaces, + * namely, GSM0808_IE_THEMWI_RTP_EXTENSIONS and RSL_IE_OSMO_RTP_EXTENSIONS. + * It is based on this authoritative definition: + * + * https://www.freecalypso.org/specs/tw-ts-003-v010002.txt + * + * Section 5.3 in the above specification defines the assignment of + * individual bits in the single value octet. + */ + +#pragma once + +#define OSMO_RTP_EXT_TWTS001 0x01 +#define OSMO_RTP_EXT_TWTS002 0x02
View file
libosmocore_1.9.3.tar.xz/include/osmocom/isdn/Makefile.am -> libosmocore_1.10.0.tar.xz/include/osmocom/isdn/Makefile.am
Changed
@@ -2,6 +2,7 @@ i460_mux.h \ lapd_core.h \ v110.h \ + v110_ta.h \ $(NULL) osmoisdndir = $(includedir)/osmocom/isdn
View file
libosmocore_1.9.3.tar.xz/include/osmocom/isdn/lapd_core.h -> libosmocore_1.10.0.tar.xz/include/osmocom/isdn/lapd_core.h
Changed
@@ -84,6 +84,17 @@ LAPD_STATE_TIMER_RECOV, }; +/*! lapd_flags */ +#define LAPD_F_RTS 0x0001 +#define LAPD_F_DROP_2ND_REJ 0x0002 + +/*! LAPD T200 state in RTS mode */ +enum lapd_t200_rts { + LAPD_T200_RTS_OFF = 0, + LAPD_T200_RTS_PENDING, + LAPD_T200_RTS_RUNNING, +}; + /*! LAPD message format (I / S / U) */ enum lapd_format { LAPD_FORM_UKN = 0, @@ -133,6 +144,7 @@ struct lapd_cr_ent rem2loc; } cr; enum lapd_mode mode; /*!< current mode of link */ + unsigned int lapd_flags; /*!< \ref lapd_flags to change processing */ int use_sabme; /*!< use SABME instead of SABM */ int reestablish; /*!< enable reestablish support */ int n200, n200_est_rel; /*!< number of retranmissions */ @@ -149,6 +161,7 @@ uint8_t peer_busy; /*!< receiver busy on remote side */ int t200_sec, t200_usec; /*!< retry timer (default 1 sec) */ int t203_sec, t203_usec; /*!< retry timer (default 10 secs) */ + enum lapd_t200_rts t200_rts; /*!< state of T200 in RTS mode */ struct osmo_timer_list t200; /*!< T200 timer */ struct osmo_timer_list t203; /*!< T203 timer */ uint8_t retrans_ctr; /*!< re-transmission counter */ @@ -169,8 +182,11 @@ void lapd_dl_set_name(struct lapd_datalink *dl, const char *name); void lapd_dl_exit(struct lapd_datalink *dl); void lapd_dl_reset(struct lapd_datalink *dl); +int lapd_dl_set_flags(struct lapd_datalink *dl, unsigned int flags); int lapd_set_mode(struct lapd_datalink *dl, enum lapd_mode mode); int lapd_ph_data_ind(struct msgb *msg, struct lapd_msg_ctx *lctx); +int lapd_ph_rts_ind(struct lapd_msg_ctx *lctx); int lapd_recv_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); +int lapd_t200_timeout(struct lapd_datalink *dl); /*! @} */
View file
libosmocore_1.9.3.tar.xz/include/osmocom/isdn/v110.h -> libosmocore_1.10.0.tar.xz/include/osmocom/isdn/v110.h
Changed
@@ -39,6 +39,13 @@ _NUM_OSMO_V110_SYNC_RA1 }; +extern const ubit_t osmo_v110_e1e2e3_NUM_OSMO_V110_SYNC_RA13; + +#define osmo_v110_e1e2e3_set(e_bits, rate) \ + memcpy(e_bits, osmo_v110_e1e2e3rate, 3) +#define osmo_v110_e1e2e3_cmp(e_bits, rate) \ + memcmp(e_bits, osmo_v110_e1e2e3rate, 3) + int osmo_v110_sync_ra1_get_user_data_chunk_bitlen(enum osmo_v100_sync_ra1_rate rate); int osmo_v110_sync_ra1_get_user_data_rate(enum osmo_v100_sync_ra1_rate rate); int osmo_v110_sync_ra1_get_intermediate_rate(enum osmo_v100_sync_ra1_rate rate);
View file
libosmocore_1.10.0.tar.xz/include/osmocom/isdn/v110_ta.h
Added
@@ -0,0 +1,113 @@ +#pragma once + +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/bits.h> +#include <osmocom/isdn/v110.h> + +/* Definition of this struct is intentionally kept private */ +struct osmo_v110_ta; + +/*! V.110 5.4.1 Local flow control (DTE-DCE or TE-TA) mode */ +enum osmo_v110_local_flow_ctrl_mode { + OSMO_V110_LOCAL_FLOW_CTRL_NONE, /*!< No local flow control */ + OSMO_V110_LOCAL_FLOW_CTRL_133_106, /*!< 5.4.1.1 133/106 operation */ + OSMO_V110_LOCAL_FLOW_CTRL_105_106, /*!< 5.4.1.2 105/106 operation */ + OSMO_V110_LOCAL_FLOW_CTRL_XON_XOFF, /*!< 5.4.1.3 XON/XOFF operation */ +}; + +/*! Configuration for a V.110 TA instance */ +struct osmo_v110_ta_cfg { + /*! Configuration flags (behavior switches and quirks) */ + unsigned int flags; + /*! Synchronous user rate */ + enum osmo_v100_sync_ra1_rate rate; + + /*! Flow control configuration */ + struct { + /*! Local TA-TE (DTE-DCE) flow control mode */ + enum osmo_v110_local_flow_ctrl_mode local; + /*! End-to-end (TA-to-TA) flow control state */ + bool end_to_end; + } flow_ctrl; + + /*! Opaque application-private data; passed to call-backs. */ + void *priv; + + /*! Receive call-back of the application. + * \paramin priv opaque application-private data. + * \paramin buf output buffer for writing to be transmitted data. + * \paramin buf_size size of the output buffer. */ + void (*rx_cb)(void *priv, const ubit_t *buf, size_t buf_size); + + /*! Transmit call-back of the application. + * \paramin priv opaque application-private data. + * \paramout buf output buffer for writing to be transmitted data. + * \paramin buf_size size of the output buffer. */ + void (*tx_cb)(void *priv, ubit_t *buf, size_t buf_size); + + /*! Modem status line update call-back (optional). + * \paramin priv opaque application-private data. + * \paramin status updated status; bit-mask of OSMO_V110_TA_C_*. */ + void (*status_update_cb)(void *priv, unsigned int status); +}; + +struct osmo_v110_ta *osmo_v110_ta_alloc(void *ctx, const char *name, + const struct osmo_v110_ta_cfg *cfg); +void osmo_v110_ta_free(struct osmo_v110_ta *ta); + +/*! Various timers for a V.110 TA instance */ +enum osmo_v110_ta_timer { + /*! 7.1.5 Loss of frame synchronization: sync recovery timer. + * T-number is not assigned in V.110, so we call it X1. */ + OSMO_V110_TA_TIMER_X1 = -1, + /*! 7.1.2 Connect TA to line: sync establishment timer */ + OSMO_V110_TA_TIMER_T1 = 1, + /*! 7.1.4 Disconnect mode: disconnect confirmation timer */ + OSMO_V110_TA_TIMER_T2 = 2, +}; + +int osmo_v110_ta_set_timer_val_ms(struct osmo_v110_ta *ta, + enum osmo_v110_ta_timer timer, + unsigned long val_ms); + +int osmo_v110_ta_frame_in(struct osmo_v110_ta *ta, const struct osmo_v110_decoded_frame *in); +int osmo_v110_ta_frame_out(struct osmo_v110_ta *ta, struct osmo_v110_decoded_frame *out); + +int osmo_v110_ta_sync_ind(struct osmo_v110_ta *ta); +int osmo_v110_ta_desync_ind(struct osmo_v110_ta *ta); + +/*! ITU-T Table 9 "Interchange circuit" (see also ITU-T V.24 Chapter 3). + * XXX: Not all circuits are present here, only those which we actually use. + * TODO: add human-friendly abbreviated circuit names. */ +enum osmo_v110_ta_circuit { + OSMO_V110_TA_C_105, /*!< DTE->DCE | RTS (Request to Send) */ + OSMO_V110_TA_C_106, /*!< DTE<-DCE | CTS (Clear to Send) */ + OSMO_V110_TA_C_107, /*!< DTE<-DCE | DSR (Data Set Ready) */ + OSMO_V110_TA_C_108, /*!< DTE->DCE | DTR (Data Terminal Ready) */ + OSMO_V110_TA_C_109, /*!< DTE<-DCE | DCD (Data Carrier Detect) */ + OSMO_V110_TA_C_133, /*!< DTE->DCE | Ready for receiving */ +}; + +extern const struct value_string osmo_v110_ta_circuit_names; +extern const struct value_string osmo_v110_ta_circuit_descs; + +/*! Get a short name of the given TA's circuit (format: NNN/ABBR). */ +static inline const char *osmo_v110_ta_circuit_name(enum osmo_v110_ta_circuit circuit) +{ + return get_value_string(osmo_v110_ta_circuit_names, circuit); +} + +/*! Get a brief description of the given TA's circuit. */ +static inline const char *osmo_v110_ta_circuit_desc(enum osmo_v110_ta_circuit circuit) +{ + return get_value_string(osmo_v110_ta_circuit_descs, circuit); +} + +unsigned int osmo_v110_ta_get_status(const struct osmo_v110_ta *ta); +bool osmo_v110_ta_get_circuit(const struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit); +int osmo_v110_ta_set_circuit(struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit, bool active);
View file
libosmocore_1.9.3.tar.xz/osmo-release.mk -> libosmocore_1.10.0.tar.xz/osmo-release.mk
Changed
@@ -1,9 +1,2 @@ -ifndef REL - REL := patch -endif - release: -ifeq ($(origin REL), file) - @echo "No REL value specified, defaulting to 'patch' release" -endif - @osmo-release.sh $(VERSION) $(REL) + @PATH="$$PWD:$$PATH" osmo-release.sh $(VERSION) $(REL)
View file
libosmocore_1.9.3.tar.xz/osmo-release.sh -> libosmocore_1.10.0.tar.xz/osmo-release.sh
Changed
@@ -3,8 +3,17 @@ REL=$2 if "z$REL" = "z" ; then - echo "No REL value specified, defaulting to 'patch' release" - REL="patch" + echo "usage: make REL=patch|minor|major release" + echo + echo "optional environment variables:" + echo " DRY_RUN=1 run checks but make no modifications" + echo " ALLOW_NO_LIBVERSION_CHANGE=1 skip LIBVERSION in Makefile.am fchecks" + echo " ALLOW_NO_LIBVERSION_DEB_MATCH=1 skip LIBVERSION in debian packaging checks" + echo " ALLOW_NO_LIBVERSION_RPM_MATCH=1 skip LIBVERSION in rpm packaging checks" + echo + echo "See also:" + echo "https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release" + exit 1 fi ALLOW_NO_LIBVERSION_CHANGE="${ALLOW_NO_LIBVERSION_CHANGE:-0}" @@ -13,6 +22,23 @@ # Test stuff but don't modify stuff: DRY_RUN="${DRY_RUN:-0}" +RESET="\0331;0m" +RED="\0331;31m" +GREEN="\0331;32m" +YELLOW="\0331;33m" + +ok() { + echo "${GREEN}OK:${RESET} $@" +} + +warn() { + echo "${YELLOW}WARN:${RESET} $@" +} + +error() { + echo "${RED}ERROR:${RESET} $@" +} + libversion_to_lib_major() { libversion="$1" current="$(echo "$libversion" | cut -d ":" -f 1)" @@ -43,16 +69,16 @@ if "z$debctrl_match_count" != "z0" ; then #echo "Dependency <$dep, $ver> from configure.ac matched in debian/control! ($debctrl_match_count)" if "z$debctrl_match_count" != "z1" ; then - echo "WARN: configure.ac <$dep, $ver> matches debian/control $debctrl_match_count times, manual check required!" + warn "configure.ac <$dep, $ver> matches debian/control $debctrl_match_count times, manual check required!" else # 1 match: parsed_match=$(echo "$debctrl_match" | tr -d "(" | tr -d ")" | tr -d "," | tr -d " " | tr -d "\t" | sed "s/>=/ /g") debctrl_dep=$(echo "$parsed_match" | cut -d " " -f 1 | sed "s/-dev//g") debctrl_ver=$(echo "$parsed_match" | cut -d " " -f 2) if "z$dep" != "z$debctrl_dep" || "z$ver" != "z$debctrl_ver" ; then - echo "ERROR: configure.ac <$dep, $ver> does NOT match debian/control <$debctrl_dep, $debctrl_ver>!" + error "configure.ac <$dep, $ver> does NOT match debian/control <$debctrl_dep, $debctrl_ver>!" return_error=1 #else - # echo "OK: configure.ac <$dep, $ver> matches debian/control <$debctrl_dep, $debctrl_ver>" + # ok "configure.ac <$dep, $ver> matches debian/control <$debctrl_dep, $debctrl_ver>" fi fi fi @@ -64,10 +90,10 @@ # catch and forward exit from pipe subshell "while read": if $? -ne 0 ; then - echo "ERROR: exiting due to previous errors" + error "exiting due to previous errors" exit 1 fi - echo "OK: dependency specific versions in configure.ac and debian/control match" + ok "dependency specific versions in configure.ac and debian/control match" } # Make sure that depedency requirement versions match in configure.ac vs contrib/*.spec.in. @@ -88,16 +114,16 @@ if "z$rpmspecin_match_count" != "z0" ; then #echo "Dependency <$dep, $ver> from configure.ac matched in contrib/*.spec.in! ($rpmspecin_match_count)" if "z$rpmspecin_match_count" != "z1" ; then - echo "WARN: configure.ac <$dep, $ver> matches contrib/*.spec.in $rpmspecin_match_count times, manual check required!" + warn "configure.ac <$dep, $ver> matches contrib/*.spec.in $rpmspecin_match_count times, manual check required!" else # 1 match: parsed_match=$(echo "$rpmspecin_match" | tr -d "(" | tr -d ")" | tr -d ":" | tr -d " " | tr -d "\t" | sed "s/BuildRequires//g" | sed "s/pkgconfig//g" |sed "s/>=/ /g") rpmspecin_dep=$(echo "$parsed_match" | cut -d " " -f 1) rpmspecin_ver=$(echo "$parsed_match" | cut -d " " -f 2) if "z$dep" != "z$rpmspecin_dep" || "z$ver" != "z$rpmspecin_ver" ; then - echo "ERROR: configure.ac <$dep, $ver> does NOT match contrib/*.spec.in <$rpmspecin_dep, $rpmspecin_ver>!" + error "configure.ac <$dep, $ver> does NOT match contrib/*.spec.in <$rpmspecin_dep, $rpmspecin_ver>!" return_error=1 #else - # echo "OK: configure.ac <$dep, $ver> matches contrib/*.spec.in <$debctrl_dep, $debctrl_ver>" + # ok "configure.ac <$dep, $ver> matches contrib/*.spec.in <$debctrl_dep, $debctrl_ver>" fi fi fi @@ -109,10 +135,10 @@ # catch and forward exit from pipe subshell "while read": if $? -ne 0 ; then - echo "ERROR: exiting due to previous errors" + error "exiting due to previous errors" exit 1 fi - echo "OK: dependency specific versions in configure.ac and contrib/*.spec.in match" + ok "dependency specific versions in configure.ac and contrib/*.spec.in match" } # Make sure that patches under debian/patches/ apply: @@ -123,10 +149,10 @@ for patch in ${GIT_TOPDIR}/debian/patches/*.patch; do git apply --check $patch if $? -ne 0 ; then - echo "ERROR: patch no longer applies! $patch" + error "patch no longer applies! $patch" exit 1 else - echo "OK: patch applies: $patch" + ok "patch applies: $patch" fi done } @@ -137,34 +163,34 @@ major="$(libversion_to_lib_major "$libversion")" file_matches="$(find "${GIT_TOPDIR}/debian" -name "lib*${major}.install" | wc -l)" if "z$file_matches" = "z0" ; then - echo "ERROR: Found no matching debian/lib*$major.install file for LIBVERSION=$libversion" + error "Found no matching debian/lib*$major.install file for LIBVERSION=$libversion" exit 1 elif "z$file_matches" = "z1" ; then - echo "OK: Found matching debian/lib*$major.install for LIBVERSION=$libversion" + ok "Found matching debian/lib*$major.install for LIBVERSION=$libversion" else - echo "WARN: Found $file_matches files matching debian/lib*$major.install for LIBVERSION=$libversion, manual check required!" + warn "Found $file_matches files matching debian/lib*$major.install for LIBVERSION=$libversion, manual check required!" fi control_matches="$(grep -e "Package" "${GIT_TOPDIR}/debian/control" | grep "lib" | grep "$major$" | wc -l)" if "z$control_matches" = "z0" ; then - echo "ERROR: Found no matching Package lib*$major in debian/control for LIBVERSION=$libversion" + error "Found no matching Package lib*$major in debian/control for LIBVERSION=$libversion" exit 1 elif "z$control_matches" = "z1" ; then - echo "OK: Found 'Package: lib*$major' in debian/control for LIBVERSION=$libversion" + ok "Found 'Package: lib*$major' in debian/control for LIBVERSION=$libversion" else - echo "WARN: Found $file_matches files matching 'Package: lib*$major' in debian/control for LIBVERSION=$libversion, manual check required!" + warn "Found $file_matches files matching 'Package: lib*$major' in debian/control for LIBVERSION=$libversion, manual check required!" fi dhstrip_lib_total="$(grep -e "dh_strip" "${GIT_TOPDIR}/debian/rules" | grep "\-plib" | wc -l)" dhstrip_lib_matches="$(grep -e "dh_strip" "${GIT_TOPDIR}/debian/rules" | grep "\-plib" | grep "$major" | wc -l)" if "z$dhstrip_lib_total" != "z0" ; then if "z$dhstrip_lib_matches" = "z0" ; then - echo "ERROR: Found no matching 'dh_strip -plib*$major' line in debian/rules for LIBVERSION=$libversion" + error "Found no matching 'dh_strip -plib*$major' line in debian/rules for LIBVERSION=$libversion" exit 1 elif "z$dhstrip_lib_total" = "z1" ; then - echo "OK: Found 'dh_strip -plib*$major' in debian/rules for LIBVERSION=$libversion" + ok "Found 'dh_strip -plib*$major' in debian/rules for LIBVERSION=$libversion" else - echo "WARN: Found $dhstrip_lib_matches/$dhstrip_lib_total dh_strip matches 'dh_strip -plib*$major' in debian/rules for LIBVERSION=$libversion, manual check required!" + warn "Found $dhstrip_lib_matches/$dhstrip_lib_total dh_strip matches 'dh_strip -plib*$major' in debian/rules for LIBVERSION=$libversion, manual check required!" fi fi done @@ -187,22 +213,22 @@ control_matches="$(grep -e "%files" "${GIT_TOPDIR}/contrib/"*.spec.in | grep "lib" | grep "$major$" | wc -l)" if "z$control_matches" = "z0" ; then - echo "ERROR: Found no matching '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion" + error "Found no matching '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion" exit 1 elif "z$control_matches" = "z1" ; then - echo "OK: Found '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion" + ok "Found '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion" else - echo "WARN: Found $file_matches files matching '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion, manual check required!" + warn "Found $file_matches files matching '%files -n lib*$major' in contrib/*.spec.in for LIBVERSION=$libversion, manual check required!" fi control_matches="$(grep -e "_libdir" "${GIT_TOPDIR}/contrib/"*.spec.in | grep "/lib" | grep "so.$major" | wc -l)" if "z$control_matches" = "z0" ; then - echo "ERROR: Found no matching '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion" + error "Found no matching '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion" exit 1 elif "z$control_matches" = "z1" ; then - echo "OK: Found '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion" + ok "Found '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion" else - echo "WARN: Found $file_matches files matching '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion, manual check required!" + warn "Found $file_matches files matching '%_libdir/lib*.so.$major*' in contrib/*.spec.in for LIBVERSION=$libversion, manual check required!" fi done # catch and forward exit from pipe subshell "while read": @@ -211,6 +237,20 @@ fi } +clean_todo_release() { + rm -f TODO-RELEASE + echo "# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install" >> TODO-RELEASE + echo "# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release" >> TODO-RELEASE + echo "# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info" >> TODO-RELEASE + echo "# LIBVERSION=c:r:a" >> TODO-RELEASE + echo "# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a." >> TODO-RELEASE + echo "# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a." >> TODO-RELEASE + echo "# If any interfaces have been added since the last public release: c:r:a + 1." >> TODO-RELEASE + echo "# If any interfaces have been removed or changed since the last public release: c:r:0." >> TODO-RELEASE + echo "#library what description / commit summary line" >> TODO-RELEASE + git add TODO-RELEASE +} + BUMPVER=`command -v bumpversion` if "z$BUMPVER" = "z" ; then @@ -235,7 +275,9 @@ if "z$LIBVERS" != "z" ; then if "z$MAKEMOD" = "z" && "z$ALLOW_NO_LIBVERSION_CHANGE" = "z0" ; then - echo "ERROR: Before releasing, please modify some of the libversions: $LIBVERS" + error "Before releasing, please modify some of the libversions:" + for l in $LIBVERS; do echo " $l"; done + echo "After making changes, add modified file(s) to the index using git-add." echo "You should NOT be doing this unless you've read and understood following article:" echo "https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info" exit 1 @@ -253,10 +295,9 @@ fi set -e + if -f "TODO-RELEASE" ; then - grep '#' TODO-RELEASE > TODO-RELEASE.clean || true - mv TODO-RELEASE.clean TODO-RELEASE - git add TODO-RELEASE + clean_todo_release fi # Add missing epoch (OS#5046)
View file
libosmocore_1.9.3.tar.xz/src/codec/Makefile.am -> libosmocore_1.10.0.tar.xz/src/codec/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=4:0:0 +LIBVERSION=4:1:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
View file
libosmocore_1.9.3.tar.xz/src/codec/ecu_fr.c -> libosmocore_1.10.0.tar.xz/src/codec/ecu_fr.c
Changed
@@ -71,6 +71,7 @@ #include <osmocom/codec/codec.h> #include <osmocom/codec/ecu.h> +#include <osmocom/core/linuxlist.h> /* See TS 46.011, Chapter 6 Example solution */ #define GSM611_XMAXC_REDUCE 4 @@ -89,6 +90,7 @@ }; struct fr_ecu_state { + struct osmo_ecu_state ecu_state; enum ecu_principal_state pr_state; uint8_t speech_frameGSM_FR_BYTES; uint8_t sid_prefixSID_PREFIX_LEN; @@ -283,27 +285,25 @@ static struct osmo_ecu_state *ecu_fr_init(void *ctx, enum osmo_ecu_codec codec) { - struct osmo_ecu_state *st; struct fr_ecu_state *fr; - size_t size = sizeof(*st) + sizeof(*fr); - st = talloc_named_const(ctx, size, "ecu_state_FR"); - if (!st) - return NULL; - - memset(st, 0, size); - st->codec = codec; - fr = (struct fr_ecu_state *) &st->data; + fr = talloc_zero(ctx, struct fr_ecu_state); + fr->ecu_state.codec = codec; fr->pr_state = STATE_NO_DATA; osmo_prbs_state_init(&fr->prng, &osmo_prbs15); - return st; + return (struct osmo_ecu_state *) fr; +} + +static inline struct fr_ecu_state *_osmo_ecu_state_get_fr(struct osmo_ecu_state *st) +{ + return (struct fr_ecu_state *)container_of(st, struct fr_ecu_state, ecu_state); } static int ecu_fr_frame_in(struct osmo_ecu_state *st, bool bfi, const uint8_t *frame, unsigned int frame_bytes) { - struct fr_ecu_state *fr = (struct fr_ecu_state *) &st->data; + struct fr_ecu_state *fr = _osmo_ecu_state_get_fr(st); if (bfi) return 0; @@ -318,7 +318,7 @@ static int ecu_fr_frame_out(struct osmo_ecu_state *st, uint8_t *frame_out) { - struct fr_ecu_state *fr = (struct fr_ecu_state *) &st->data; + struct fr_ecu_state *fr = _osmo_ecu_state_get_fr(st); fr_ecu_output(fr, frame_out); return GSM_FR_BYTES; @@ -326,7 +326,7 @@ static bool ecu_fr_is_dtx_pause(struct osmo_ecu_state *st) { - struct fr_ecu_state *fr = (struct fr_ecu_state *) &st->data; + struct fr_ecu_state *fr = _osmo_ecu_state_get_fr(st); return fr->last_input_was_sid; }
View file
libosmocore_1.9.3.tar.xz/src/codec/gsm620.c -> libosmocore_1.10.0.tar.xz/src/codec/gsm620.c
Changed
@@ -23,8 +23,6 @@ #include <stdbool.h> #include <string.h> -#include <osmocom/core/bitvec.h> -#include <osmocom/core/utils.h> #include <osmocom/codec/codec.h> /* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */ @@ -270,21 +268,32 @@ * \paramin rtp_payload Buffer with RTP payload * \paramin payload_len Length of payload * \returns true if code word is found, false otherwise + * + * Note that this function checks only for a perfect, error-free SID. + * Unlike GSM 06.31 for FR or GSM 06.81 for EFR, GSM 06.41 spec for HR + * does not prescribe exact bit counting rules, hence detection of + * partially corrupted SID frames in downstream network elements + * without out-of-band indication is not possible. */ bool osmo_hr_check_sid(const uint8_t *rtp_payload, size_t payload_len) { - struct bitvec bv = { - .data = (uint8_t *)rtp_payload, - .data_len = payload_len, - }; + static const uint8_t all_ff_bytes9 = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF}; - /* A SID frame is identified by a SID codeword consisting of 79 bits which are all 1, - * so we basically check if all bits in range r34..r112 (inclusive) are 1. */ - for (bv.cur_bit = 33; bv.cur_bit < bv.data_len * 8; bv.cur_bit++) - if (bitvec_get_bit_pos(&bv, bv.cur_bit) != ONE) - return false; + if (payload_len < GSM_HR_BYTES) + return false; - return true; + /* A SID frame is identified by a SID codeword consisting of 79 bits + * which are all 1, so we basically check if all bits in range + * r34..r112 (inclusive) are 1. However, given the position of + * these bits in the frame, the most efficient way to perform + * this check does not use any bit-level operations. */ + if ((rtp_payload4 & 0x7F) != 0x7F) + return false; + if (memcmp(rtp_payload + 5, all_ff_bytes, 9) == 0) + return true; + else + return false; } /*! Reset the SID field of a potentially corrupted, but still valid GSM-HR
View file
libosmocore_1.9.3.tar.xz/src/coding/Makefile.am -> libosmocore_1.10.0.tar.xz/src/coding/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read Chapter 6 "Library interface versions" of the libtool # documentation before making any modification -LIBVERSION=3:0:3 +LIBVERSION=3:1:3 AM_CPPFLAGS = \ -I"$(top_srcdir)/include" \
View file
libosmocore_1.9.3.tar.xz/src/coding/gsm0503_coding.c -> libosmocore_1.10.0.tar.xz/src/coding/gsm0503_coding.c
Changed
@@ -536,7 +536,7 @@ int *n_errors, int *n_bits_total, const uint8_t *data_punc) { - int res, i, coded_len; + int res, coded_len; ubit_t recodedEGPRS_DATA_C_MAX; res = osmo_conv_decode(code, input, output); @@ -550,11 +550,15 @@ /* Count bit errors */ if (n_errors) { *n_errors = 0; - for (i = 0; i < coded_len; i++) { - if (((!data_punc) || (data_punc && !data_punci)) && - !((recodedi && inputi < 0) || - (!recodedi && inputi > 0)) ) - *n_errors += 1; + for (unsigned int i = 0; i < coded_len; i++) { + /* punctured bits do not count as bit errors */ + if (data_punc != NULL && data_punci) + continue; + if (recodedi == 1 && inputi < 0) + continue; + if (recodedi == 0 && inputi > 0) + continue; + *n_errors += 1; } } @@ -921,10 +925,10 @@ * \paramout l2_data caller-allocated buffer for L2 Frame * \paramin bursts burst input data as soft unpacked bits * \paramin nbits number of bits in \a bursts - * \param usf_p unused argument ?!? + * \param usf_p Uplink State Flag, FIXME: not implemented * \paramout n_errors number of detected bit-errors * \paramout n_bits_total total number of decoded bits - * \returns 0 on success; negative on error */ + * \returns number of bytes decoded; negative on error */ int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t nbits, uint8_t *usf_p, int *n_errors, int *n_bits_total) { @@ -1010,10 +1014,10 @@ /*! Decode GPRS PDTCH * \paramout l2_data caller-allocated buffer for L2 Frame * \paramin bursts burst input data as soft unpacked bits - * \paramout usf_p uplink stealing flag + * \paramout usf_p Uplink State Flag, only relevant for DL blocks * \paramout n_errors number of detected bit-errors - * \paramout n_bits_total total number of dcoded bits - * \returns 0 on success; negative on error */ + * \paramout n_bits_total total number of decoded bits + * \returns number of bytes decoded; negative on error */ int gsm0503_pdtch_decode(uint8_t *l2_data, const sbit_t *bursts, uint8_t *usf_p, int *n_errors, int *n_bits_total) { @@ -1042,6 +1046,10 @@ osmo_conv_decode_ber(&gsm0503_xcch, cB, conv, n_errors, n_bits_total); + /* the three USF bits d(0),d(1),d(2) are *not* precoded */ + if (usf_p) + *usf_p = (conv0 << 2) | (conv1 << 1) | (conv2 << 0); + rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40, conv, 184, conv + 184); if (rv) @@ -1051,6 +1059,7 @@ return 23; case 2: + /* reorder, set punctured bits to 0 (unknown state) */ for (i = 587, j = 455; i >= 0; i--) { if (!gsm0503_puncture_cs2i) cBi = cBj--; @@ -1058,9 +1067,15 @@ cBi = 0; } - osmo_conv_decode_ber(&gsm0503_cs2_np, cB, - conv, n_errors, n_bits_total); + /* decode as if puncturing was not employed (note '_np') */ + osmo_conv_decode_ber_punctured(&gsm0503_cs2_np, cB, conv, + n_errors, NULL, + gsm0503_puncture_cs2); + /* indicate the actual amount of coded bits (excluding punctured ones) */ + if (n_bits_total != NULL) + *n_bits_total = 456; + /* 5.1.2.2 a) the three USF bits d(0),d(1),d(2) are precoded into six bits */ for (i = 0; i < 8; i++) { for (j = 0, k = 0; j < 6; j++) k += abs(((int)gsm0503_usf2sixij) - ((int)convj)); @@ -1086,6 +1101,7 @@ return 34; case 3: + /* reorder, set punctured bits to 0 (unknown state) */ for (i = 675, j = 455; i >= 0; i--) { if (!gsm0503_puncture_cs3i) cBi = cBj--; @@ -1093,9 +1109,15 @@ cBi = 0; } - osmo_conv_decode_ber(&gsm0503_cs3_np, cB, - conv, n_errors, n_bits_total); + /* decode as if puncturing was not employed (note '_np') */ + osmo_conv_decode_ber_punctured(&gsm0503_cs3_np, cB, conv, + n_errors, NULL, + gsm0503_puncture_cs3); + /* indicate the actual amount of coded bits (excluding punctured ones) */ + if (n_bits_total != NULL) + *n_bits_total = 456; + /* 5.1.3.2 a) the three USF bits d(0),d(1),d(2) are precoded into six bits */ for (i = 0; i < 8; i++) { for (j = 0, k = 0; j < 6; j++) k += abs(((int)gsm0503_usf2sixij) - ((int)convj)); @@ -1124,6 +1146,7 @@ for (i = 12; i < 456; i++) convi = (cBi < 0) ? 1 : 0; + /* 5.1.4.2 a) the three USF bits d(0),d(1),d(2) are precoded into twelve bits */ for (i = 0; i < 8; i++) { for (j = 0, k = 0; j < 12; j++) k += abs(((int)gsm0503_usf2twelve_sbitij) - ((int)cBj)); @@ -2439,7 +2462,7 @@ /*! Perform channel encoding on a TCH/AFS channel according to TS 05.03 * \paramout bursts caller-allocated output buffer for bursts bits * \paramin tch_data Codec input data in RTP payload format - * \paramin len Length of \a tch_data in bytes + * \paramin len Length of \a tch_data in bytes or 0 to generate a bad frame * \paramin codec_mode_req Use CMR (1) or FT (0) * \paramin codec Array of codecs (active codec set) * \paramin codecs Number of entries in \a codec @@ -2447,7 +2470,7 @@ * \paramin cmr Codec Mode Request (used in codec_mode_req = 1 only) * \returns 0 in case of success; negative on error */ int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len, - int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, + int codec_mode_req, const uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr) { ubit_t iB912, cB456, h; @@ -2465,28 +2488,27 @@ h = 0; - if (codec_mode_req) { - if (cmr >= codecs) { - /* FIXME: CMR ID is not in codec list! */ - return -1; - } - id = cmr; - } else { - if (ft >= codecs) { - /* FIXME: FT ID is not in codec list! */ - return -1; - } - id = ft; - } + id = codec_mode_req ? cmr : ft; + if (OSMO_UNLIKELY(id >= ARRAY_SIZE(gsm0503_afs_ic_ubit))) + return -1; + if (OSMO_UNLIKELY(ft >= codecs)) + return -1; switch (codecft) { case 7: /* TCH/AFS12.2 */ - if (len != 31) - goto invalid_length; + if (!len) { + /* No data, induce BFI in the receiver by inverted CRC bits. + * The data bit are all 0, so the correct parity bits would be 111111. */ + memset(d, 0, 244); + memset(p, 0, 6); + } else { + if (len != 31) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 244); + tch_amr_disassemble(d, tch_data, 244); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p); + } tch_amr_merge(conv, d, p, 244, 81); @@ -2494,12 +2516,18 @@ break; case 6: /* TCH/AFS10.2 */ - if (len != 26) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 204); + memset(p, 0, 6); + } else { + if (len != 26) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 204); + tch_amr_disassemble(d, tch_data, 204); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p); + } tch_amr_merge(conv, d, p, 204, 65); @@ -2507,12 +2535,18 @@ break; case 5: /* TCH/AFS7.95 */ - if (len != 20) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 159); + memset(p, 0, 6); + } else { + if (len != 20) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 159); + tch_amr_disassemble(d, tch_data, 159); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p); + } tch_amr_merge(conv, d, p, 159, 75); @@ -2520,12 +2554,18 @@ break; case 4: /* TCH/AFS7.4 */ - if (len != 19) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 148); + memset(p, 0, 6); + } else { + if (len != 19) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 148); + tch_amr_disassemble(d, tch_data, 148); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p); + } tch_amr_merge(conv, d, p, 148, 61); @@ -2533,12 +2573,18 @@ break; case 3: /* TCH/AFS6.7 */ - if (len != 17) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 134); + memset(p, 0, 6); + } else { + if (len != 17) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 134); + tch_amr_disassemble(d, tch_data, 134); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + } tch_amr_merge(conv, d, p, 134, 55); @@ -2546,12 +2592,18 @@ break; case 2: /* TCH/AFS5.9 */ - if (len != 15) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 118); + memset(p, 0, 6); + } else { + if (len != 15) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 118); + tch_amr_disassemble(d, tch_data, 118); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + } tch_amr_merge(conv, d, p, 118, 55); @@ -2559,12 +2611,18 @@ break; case 1: /* TCH/AFS5.15 */ - if (len != 13) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 103); + memset(p, 0, 6); + } else { + if (len != 13) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 103); + tch_amr_disassemble(d, tch_data, 103); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p); + } tch_amr_merge(conv, d, p, 103, 49); @@ -2572,12 +2630,18 @@ break; case 0: /* TCH/AFS4.75 */ - if (len != 12) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 95); + memset(p, 0, 6); + } else { + if (len != 12) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 95); + tch_amr_disassemble(d, tch_data, 95); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p); + } tch_amr_merge(conv, d, p, 95, 39); @@ -2935,7 +2999,7 @@ /*! Perform channel encoding on a TCH/AHS channel according to TS 05.03 * \paramout bursts caller-allocated output buffer for bursts bits * \paramin tch_data Codec input data in RTP payload format - * \paramin len Length of \a tch_data in bytes + * \paramin len Length of \a tch_data in bytes or 0 to generate a bad frame * \paramin codec_mode_req Use CMR (1) or FT (0) * \paramin codec Array of codecs (active codec set) * \paramin codecs Number of entries in \a codec @@ -2943,7 +3007,7 @@ * \paramin cmr Codec Mode Request (used in codec_mode_req = 1 only) * \returns 0 in case of success; negative on error */ int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len, - int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, + int codec_mode_req, const uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr) { ubit_t iB912, cB456, h; @@ -2970,28 +3034,27 @@ h = 0; - if (codec_mode_req) { - if (cmr >= codecs) { - /* FIXME: CMR ID %d not in codec list */ - return -1; - } - id = cmr; - } else { - if (ft >= codecs) { - /* FIXME: FT ID %d not in codec list */ - return -1; - } - id = ft; - } + id = codec_mode_req ? cmr : ft; + if (OSMO_UNLIKELY(id >= ARRAY_SIZE(gsm0503_ahs_ic_ubit))) + return -1; + if (OSMO_UNLIKELY(ft >= codecs)) + return -1; switch (codecft) { case 5: /* TCH/AHS7.95 */ - if (len != 20) - goto invalid_length; + if (!len) { + /* No data, induce BFI in the receiver by inverted CRC bits. + * The data bit are all 0, so the correct parity bits would be 111111. */ + memset(d, 0, 159); + memset(p, 0, 6); + } else { + if (len != 20) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 159); + tch_amr_disassemble(d, tch_data, 159); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p); + } tch_amr_merge(conv, d, p, 123, 67); @@ -3001,12 +3064,18 @@ break; case 4: /* TCH/AHS7.4 */ - if (len != 19) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 148); + memset(p, 0, 6); + } else { + if (len != 19) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 148); + tch_amr_disassemble(d, tch_data, 148); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p); + } tch_amr_merge(conv, d, p, 120, 61); @@ -3016,12 +3085,18 @@ break; case 3: /* TCH/AHS6.7 */ - if (len != 17) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 134); + memset(p, 0, 6); + } else { + if (len != 17) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 134); + tch_amr_disassemble(d, tch_data, 134); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + } tch_amr_merge(conv, d, p, 110, 55); @@ -3031,12 +3106,18 @@ break; case 2: /* TCH/AHS5.9 */ - if (len != 15) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 118); + memset(p, 0, 6); + } else { + if (len != 15) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 118); + tch_amr_disassemble(d, tch_data, 118); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p); + } tch_amr_merge(conv, d, p, 102, 55); @@ -3046,12 +3127,18 @@ break; case 1: /* TCH/AHS5.15 */ - if (len != 13) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 103); + memset(p, 0, 6); + } else { + if (len != 13) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 103); + tch_amr_disassemble(d, tch_data, 103); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p); + } tch_amr_merge(conv, d, p, 91, 49); @@ -3061,12 +3148,18 @@ break; case 0: /* TCH/AHS4.75 */ - if (len != 12) - goto invalid_length; + if (!len) { + /* See comment above. */ + memset(d, 0, 95); + memset(p, 0, 6); + } else { + if (len != 12) + goto invalid_length; - tch_amr_disassemble(d, tch_data, 95); + tch_amr_disassemble(d, tch_data, 95); - osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p); + osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p); + } tch_amr_merge(conv, d, p, 83, 39);
View file
libosmocore_1.9.3.tar.xz/src/core/Makefile.am -> libosmocore_1.10.0.tar.xz/src/core/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=21:2:0 +LIBVERSION=22:0:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) AM_CFLAGS = -Wall $(TALLOC_CFLAGS) $(PTHREAD_CFLAGS) $(LIBSCTP_CFLAGS) $(LIBMNL_CFLAGS) $(URING_CFLAGS) @@ -63,6 +63,7 @@ signal.c \ sockaddr_str.c \ socket.c \ + soft_uart.c \ stat_item.c \ stats.c \ stats_statsd.c \
View file
libosmocore_1.9.3.tar.xz/src/core/bitvec.c -> libosmocore_1.10.0.tar.xz/src/core/bitvec.c
Changed
@@ -540,13 +540,11 @@ */ void bitvec_to_string_r(const struct bitvec *bv, char *str) { - unsigned i, pos = 0; char *cur = str; - for (i = 0; i < bv->cur_bit; i++) { + for (unsigned int i = 0; i < bv->cur_bit; i++) { if (0 == i % 8) *cur++ = ' '; *cur++ = bit_value_to_char(bitvec_get_bit_pos(bv, i)); - pos++; } *cur = 0; }
View file
libosmocore_1.9.3.tar.xz/src/core/gsmtap_util.c -> libosmocore_1.10.0.tar.xz/src/core/gsmtap_util.c
Changed
@@ -29,6 +29,7 @@ #include <osmocom/core/select.h> #include <osmocom/core/socket.h> #include <osmocom/core/byteswap.h> +#include <osmocom/core/utils.h> #include <osmocom/gsm/protocol/gsm_04_08.h> #include <osmocom/gsm/rsl.h> @@ -46,6 +47,43 @@ * * \file gsmtap_util.c */ +/*! one gsmtap instance + * Until gsmtap_inst_fd() is removed from the API at some point in the future, we have to keep the first member as + * 'int' and the second as 'struct osmo_wqueue' (this effectively makes sure that the struct member wq.bfd.fd maintains + * the same memory offset from the start of the struct) to ensure that inlined static 'instances' of gsmtap_inst_fd() in + * old binaries keep working the way they used to even with gsmtap_inst objects obtained from newer versions of libosmocore */ +struct gsmtap_inst { + int osmo_io_mode; /*!< Indicates whether or not to use Osmo IO mode for message output (thus enabling use of tx queues). + * This field member may not be changed or moved (backwards compatibility) */ + struct osmo_wqueue wq; /*!< the wait queue. This field member may not be changed or moved (backwards compatibility) */ + + struct osmo_io_fd *out; /*!< Used when osmo_io_mode is nonzero */ + int sink_fd; +}; + +struct _gsmtap_inst_legacy { + int ofd_wq_mode; + struct osmo_wqueue wq; + struct osmo_fd sink_ofd; +}; +osmo_static_assert(offsetof(struct gsmtap_inst, wq) == offsetof(struct _gsmtap_inst_legacy, wq), + gsmtap_inst_new_wq_offset_equals_legacy_wq_offset); + +/*! Deprecated, use gsmtap_inst_fd2() instead + * \paramin gti GSMTAP instance + * \returns file descriptor of GSMTAP instance */ +int gsmtap_inst_fd(struct gsmtap_inst *gti) +{ + return gsmtap_inst_fd2(gti); +} + +/*! obtain the file descriptor associated with a gsmtap instance + * \paramin gti GSMTAP instance + * \returns file descriptor of GSMTAP instance */ +int gsmtap_inst_fd2(const struct gsmtap_inst *gti) +{ + return gti->wq.bfd.fd; +} /*! convert RSL channel number to GSMTAP channel type * \paramin rsl_chantype RSL channel type @@ -231,6 +269,7 @@ #include <sys/socket.h> #include <netinet/in.h> +#include <osmocom/core/osmo_io.h> /*! Create a new (sending) GSMTAP source socket * \paramin host host name or IP address in string format @@ -324,13 +363,13 @@ if (!gti) return -ENODEV; - if (gti->ofd_wq_mode) - return osmo_wqueue_enqueue(>i->wq, msg); + if (gti->osmo_io_mode) + return osmo_iofd_write_msgb(gti->out, msg); else { /* try immediate send and return error if any */ int rc; - rc = write(gsmtap_inst_fd(gti), msg->data, msg->len); + rc = write(gsmtap_inst_fd2(gti), msg->data, msg->len); if (rc < 0) { return rc; } else if (rc >= msg->len) { @@ -394,40 +433,6 @@ signal_dbm, snr, data, len); } -/* Callback from select layer if we can write to the socket */ -static int gsmtap_wq_w_cb(struct osmo_fd *ofd, struct msgb *msg) -{ - int rc; - - rc = write(ofd->fd, msg->data, msg->len); - if (rc < 0) { - return rc; - } - if (rc != msg->len) { - return -EIO; - } - - return 0; -} - -/* Callback from select layer if we can read from the sink socket */ -static int gsmtap_sink_fd_cb(struct osmo_fd *fd, unsigned int flags) -{ - int rc; - uint8_t buf4096; - - if (!(flags & OSMO_FD_READ)) - return 0; - - rc = read(fd->fd, buf, sizeof(buf)); - if (rc < 0) { - return rc; - } - /* simply discard any data arriving on the socket */ - - return 0; -} - /*! Add a local sink to an existing GSMTAP source and return fd * \paramin gti existing GSMTAP source * \returns file descriptor of locally bound receive socket @@ -445,30 +450,15 @@ */ int gsmtap_source_add_sink(struct gsmtap_inst *gti) { - int fd, rc; - - fd = gsmtap_source_add_sink_fd(gsmtap_inst_fd(gti)); - if (fd < 0) - return fd; - - if (gti->ofd_wq_mode) { - struct osmo_fd *sink_ofd; - - sink_ofd = >i->sink_ofd; - sink_ofd->fd = fd; - sink_ofd->when = OSMO_FD_READ; - sink_ofd->cb = gsmtap_sink_fd_cb; - - rc = osmo_fd_register(sink_ofd); - if (rc < 0) { - close(fd); - return rc; - } - } + return gti->sink_fd = gsmtap_source_add_sink_fd(gsmtap_inst_fd2(gti)); +} - return fd; +/* Registered in Osmo IO as a no-op to set the write callback. */ +static void gsmtap_ops_noop_cb(struct osmo_io_fd *iofd, int res, struct msgb *msg) +{ } +static struct osmo_io_ops gsmtap_ops = { .write_cb = gsmtap_ops_noop_cb }; /*! Open GSMTAP source socket, connect and register osmo_fd * \paramin local_host IP address in string format @@ -487,30 +477,35 @@ const char *rem_host, uint16_t rem_port, int ofd_wq_mode) { struct gsmtap_inst *gti; - int fd, rc; + int fd; fd = gsmtap_source_init_fd2(local_host, local_port, rem_host, rem_port); if (fd < 0) return NULL; gti = talloc_zero(NULL, struct gsmtap_inst); - gti->ofd_wq_mode = ofd_wq_mode; + gti->osmo_io_mode = ofd_wq_mode; + /* Still using the wq member for its 'fd' field only, since we are keeping it for now, anyways */ gti->wq.bfd.fd = fd; - gti->sink_ofd.fd = -1; + gti->sink_fd = -1; if (ofd_wq_mode) { - osmo_wqueue_init(>i->wq, 64); - gti->wq.write_cb = &gsmtap_wq_w_cb; + gti->out = osmo_iofd_setup(gti, gti->wq.bfd.fd, "gsmtap_inst.io_fd", OSMO_IO_FD_MODE_READ_WRITE, &gsmtap_ops, NULL); + if (gti->out == NULL) + goto err_cleanup; + if (osmo_iofd_register(gti->out, gti->wq.bfd.fd) < 0) + goto err_cleanup; - rc = osmo_fd_register(>i->wq.bfd); - if (rc < 0) { - talloc_free(gti); - close(fd); - return NULL; - } + /* osmo write queue previously used was set up with value of 64 */ + osmo_iofd_set_txqueue_max_length(gti->out, 64); } return gti; + +err_cleanup: + talloc_free(gti); + close(fd); + return NULL; } /*! Open GSMTAP source socket, connect and register osmo_fd @@ -534,17 +529,16 @@ if (!gti) return; - if (gti->ofd_wq_mode) { - osmo_fd_unregister(>i->wq.bfd); - osmo_wqueue_clear(>i->wq); - - if (gti->sink_ofd.fd != -1) { - osmo_fd_unregister(>i->sink_ofd); - close(gti->sink_ofd.fd); + if (gti->osmo_io_mode) { + osmo_iofd_free(gti->out); + + if (gti->sink_fd != -1) { + close(gti->sink_fd); + gti->sink_fd = -1; } + } - close(gti->wq.bfd.fd); talloc_free(gti); }
View file
libosmocore_1.9.3.tar.xz/src/core/it_q.c -> libosmocore_1.10.0.tar.xz/src/core/it_q.c
Changed
@@ -245,7 +245,7 @@ /*! Thread-safe de-queue from an inter-thread message queue. * \paramin queue Inter-thread queue from which to dequeue - * \returns dequeued message buffer; NULL if none available + * \returns llist_head of dequeued message; NULL if none available */ struct llist_head *_osmo_it_q_dequeue(struct osmo_it_q *queue) { @@ -254,12 +254,9 @@ pthread_mutex_lock(&queue->mutex); - if (llist_empty(&queue->list)) - l = NULL; - l = queue->list.next; - OSMO_ASSERT(l); - llist_del(l); - queue->current_length--; + l = item_dequeue(&queue->list); + if (l != NULL) + queue->current_length--; pthread_mutex_unlock(&queue->mutex);
View file
libosmocore_1.9.3.tar.xz/src/core/libosmocore.map -> libosmocore_1.10.0.tar.xz/src/core/libosmocore.map
Changed
@@ -39,6 +39,8 @@ get_value_string; get_value_string_or_null; gsmtap_gsm_channel_names; +gsmtap_inst_fd; +gsmtap_inst_fd2; gsmtap_makemsg; gsmtap_makemsg_ex; gsmtap_send; @@ -56,6 +58,8 @@ log_add_target; log_category_name; log_check_level; +log_cache_enable; +log_cache_update; log_del_target; log_enable_multithread; log_fini; @@ -256,15 +260,20 @@ osmo_iofd_close; osmo_iofd_free; osmo_iofd_get_data; +osmo_iofd_get_ioops; osmo_iofd_get_fd; osmo_iofd_get_name; osmo_iofd_set_name; osmo_iofd_get_priv_nr; osmo_iofd_init; +osmo_iofd_mode_names; osmo_iofd_ops; osmo_iofd_register; osmo_iofd_sendto_msgb; +osmo_iofd_sctp_send_msgb; +osmo_iofd_sendmsg_msgb; osmo_iofd_set_alloc_info; +osmo_iofd_set_cmsg_size; osmo_iofd_set_data; osmo_iofd_set_ioops; osmo_iofd_set_priv_nr; @@ -296,6 +305,7 @@ osmo_macaddr_parse; osmo_mnl_destroy; osmo_mnl_init; +osmo_multiaddr_ip_and_port_snprintf; osmo_netdev_add_addr; osmo_netdev_add_route; osmo_netdev_alloc; @@ -372,6 +382,7 @@ osmo_signal_unregister_handler; osmo_sockaddr_cmp; osmo_sockaddr_from_octets; +osmo_sockaddr_from_str_and_uint; osmo_sockaddr_in_to_str_and_uint; osmo_sockaddr_is_any; osmo_sockaddr_is_local; @@ -389,6 +400,7 @@ osmo_sockaddr_str_from_sockaddr; osmo_sockaddr_str_from_sockaddr_in; osmo_sockaddr_str_from_sockaddr_in6; +osmo_sockaddr_str_from_osa; osmo_sockaddr_str_from_str; osmo_sockaddr_str_from_str2; osmo_sockaddr_str_is_nonzero; @@ -401,6 +413,7 @@ osmo_sockaddr_str_to_sockaddr; osmo_sockaddr_str_to_sockaddr_in; osmo_sockaddr_str_to_sockaddr_in6; +osmo_sockaddr_str_to_osa; osmo_sockaddr_to_octets; osmo_sockaddr_to_str; osmo_sockaddr_to_str_and_uint; @@ -431,10 +444,29 @@ osmo_sock_mcast_loop_set; osmo_sock_mcast_subscribe; osmo_sock_mcast_ttl_set; +osmo_sock_multiaddr_add_local_addr; +osmo_sock_multiaddr_del_local_addr; +osmo_sock_multiaddr_get_ip_and_port; +osmo_sock_multiaddr_get_name_buf; +osmo_sock_sctp_get_peer_addr_info; osmo_sock_set_dscp; osmo_sock_set_priority; osmo_sock_unix_init; osmo_sock_unix_init_ofd; +osmo_soft_uart_default_cfg; +osmo_soft_uart_alloc; +osmo_soft_uart_free; +osmo_soft_uart_configure; +osmo_soft_uart_get_name; +osmo_soft_uart_set_name; +osmo_soft_uart_set_rx; +osmo_soft_uart_set_tx; +osmo_soft_uart_rx_ubits; +osmo_soft_uart_tx_ubits; +osmo_soft_uart_get_status; +osmo_soft_uart_set_status; +osmo_soft_uart_set_status_line; +osmo_soft_uart_flush_rx; osmo_stat_item_dec; osmo_stat_item_flush; osmo_stat_item_for_each_group; @@ -491,6 +523,8 @@ osmo_strrb_get_nth; _osmo_strrb_is_bufindex_valid; osmo_strrb_is_empty; +osmo_strbuf_drop_tail; +osmo_strbuf_added_tail; osmo_str_startswith; osmo_str_to_int; osmo_str_to_int64; @@ -565,6 +599,7 @@ osmo_wqueue_clear; osmo_wqueue_enqueue; osmo_wqueue_enqueue_quiet; +osmo_wqueue_set_maxlen; osmo_wqueue_init; rate_ctr_add; rate_ctr_difference;
View file
libosmocore_1.9.3.tar.xz/src/core/logging.c -> libosmocore_1.10.0.tar.xz/src/core/logging.c
Changed
@@ -93,6 +93,80 @@ static __thread long int logging_tid; #if (!EMBEDDED) +/*! One global copy that contains the union of log levels for all targets +* for all categories, used for quick lock free checks of log targets. */ +static volatile uint8_t *log_level_lookup_cache; + +/*! Updates cache for all targets for all categies, caller must hold osmo_log_tgt_mutex. */ +static void log_cache_update_all(void) +{ + struct log_target *tgt; + uint8_t tmp_enosmo_log_info->num_cat; + uint8_t tmp_levelosmo_log_info->num_cat; + + if (!log_level_lookup_cache) + return; + + memset(tmp_en, 0, osmo_log_info->num_cat); + memset(tmp_level, UINT8_MAX, osmo_log_info->num_cat); + + /* values can also decrease.. */ + llist_for_each_entry(tgt, &osmo_log_target_list, entry) { + for (int i = 0; i < osmo_log_info->num_cat; i++) { + struct log_category *cat = &tgt->categoriesi; + tmp_eni = OSMO_MAX(tmp_eni, cat->enabled); + tmp_leveli = OSMO_MIN(tmp_leveli, cat->loglevel); + tmp_leveli = tgt->loglevel ? OSMO_MIN(tmp_leveli, tgt->loglevel) : tmp_leveli; + } + } + + for (int i = 0; i < osmo_log_info->num_cat; i++) + log_level_lookup_cachei = tmp_eni ? tmp_leveli : UINT8_MAX; +} + +/*! Updates single cache entry, caller must hold osmo_log_tgt_mutex. + * + * \paramin mapped_subsys plain category index (after mapping) + * \paramin enabled log category enabled? + * \paramin level log level + */ +void log_cache_update(int mapped_subsys, uint8_t enabled, uint8_t level) +{ + struct log_target *tgt; + struct log_category tmp = { UINT8_MAX, 0 }; + + if (!log_level_lookup_cache) + return; + + /* values can also decrease.. */ + llist_for_each_entry(tgt, &osmo_log_target_list, entry) { + struct log_category *cat = &tgt->categoriesmapped_subsys; + tmp.enabled = OSMO_MAX(tmp.enabled, cat->enabled); + tmp.loglevel = OSMO_MIN(tmp.loglevel, cat->loglevel); + tmp.loglevel = tgt->loglevel ? OSMO_MIN(tmp.loglevel, tgt->loglevel) : tmp.loglevel; + } + tmp.enabled = OSMO_MAX(tmp.enabled, enabled); + tmp.loglevel = OSMO_MIN(tmp.loglevel, level); + + log_level_lookup_cachemapped_subsys = tmp.enabled ? tmp.loglevel : UINT8_MAX; +} + +/*! Queries log level cache. + * + * \paramin mapped_subsys plain category index (after mapping) + * \paramin level log level + * \returns true if logging should happen for at least one log target +*/ +static bool log_cache_check(int mapped_subsys, int level) +{ + if (!log_level_lookup_cache) { + /* log-cache is not enabled, so we simply behave like we did before the cache */ + return true; + } + + return (level < log_level_lookup_cachemapped_subsys) ? false : true; +} + /*! This mutex must be held while using osmo_log_target_list or any of its log_targets in a multithread program. Prevents race conditions between threads like producing unordered timestamps or VTY deleting a target while another @@ -426,6 +500,10 @@ } } while ((category_token = strtok(NULL, ":"))); +#if !defined(EMBEDDED) + log_cache_update_all(); +#endif + free(mask); } @@ -486,18 +564,18 @@ unsigned int level, const char *file, int line, int cont, const char *format, va_list ap) { - int ret, len = 0, offset = 0, rem = buf_len; + int ret; const char *c_subsys = NULL; + struct osmo_strbuf sb = { .buf = buf, .pos = buf, .len = buf_len }; + + /* safety net in case of encountering errors and returning nothing */ + buf0 = '\0'; /* are we using color */ if (target->use_color) { c_subsys = color(subsys); - if (c_subsys) { - ret = snprintf(buf + offset, rem, "%s", c_subsys); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } + if (c_subsys) + OSMO_STRBUF_PRINTF(sb, "%s", c_subsys); } if (!cont) { if (target->print_ext_timestamp) { @@ -506,13 +584,10 @@ struct timeval tv; osmo_gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &tm); - ret = snprintf(buf + offset, rem, "%04d%02d%02d%02d%02d%02d%03d ", - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - (int)(tv.tv_usec / 1000)); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_PRINTF(sb, "%04d%02d%02d%02d%02d%02d%03d ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, + (int)(tv.tv_usec / 1000)); #endif } else if (target->print_timestamp) { time_t tm; @@ -520,97 +595,66 @@ goto err; /* Get human-readable representation of time. man ctime: we need at least 26 bytes in buf */ - if (rem < 26 || !ctime_r(&tm, buf + offset)) + if (OSMO_STRBUF_REMAIN(sb) < 26 || !ctime_r(&tm, sb.pos)) goto err; - ret = strlen(buf + offset); + ret = strnlen(sb.pos, 26); if (ret <= 0) goto err; + OSMO_STRBUF_ADDED_TAIL(sb, ret); /* Get rid of useless final '\n' added by ctime_r. We want a space instead. */ - bufoffset + ret - 1 = ' '; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_DROP_TAIL(sb, 1); + OSMO_STRBUF_PRINTF(sb, " "); } if (target->print_tid) { if (logging_tid == 0) logging_tid = (long int)osmo_gettid(); - ret = snprintf(buf + offset, rem, "%ld ", logging_tid); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - if (target->print_category) { - ret = snprintf(buf + offset, rem, "%s%s%s%s ", - target->use_color ? level_color(level) : "", - log_category_name(subsys), - target->use_color ? OSMO_LOGCOLOR_END : "", - c_subsys ? c_subsys : ""); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - if (target->print_level) { - ret = snprintf(buf + offset, rem, "%s%s%s%s ", - target->use_color ? level_color(level) : "", - log_level_str(level), - target->use_color ? OSMO_LOGCOLOR_END : "", - c_subsys ? c_subsys : ""); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); - } - if (target->print_category_hex) { - ret = snprintf(buf + offset, rem, "<%4.4x> ", subsys); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_PRINTF(sb, "%ld ", logging_tid); } + if (target->print_category) + OSMO_STRBUF_PRINTF(sb, "%s%s%s%s ", + target->use_color ? level_color(level) : "", + log_category_name(subsys), + target->use_color ? OSMO_LOGCOLOR_END : "", + c_subsys ? c_subsys : ""); + if (target->print_level) + OSMO_STRBUF_PRINTF(sb, "%s%s%s%s ", + target->use_color ? level_color(level) : "", + log_level_str(level), + target->use_color ? OSMO_LOGCOLOR_END : "", + c_subsys ? c_subsys : ""); + if (target->print_category_hex) + OSMO_STRBUF_PRINTF(sb, "<%4.4x> ", subsys); if (target->print_filename_pos == LOG_FILENAME_POS_HEADER_END) { switch (target->print_filename2) { case LOG_FILENAME_NONE: break; case LOG_FILENAME_PATH: - ret = snprintf(buf + offset, rem, "%s:%d ", file, line); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_PRINTF(sb, "%s:%d ", file, line); break; case LOG_FILENAME_BASENAME: - ret = snprintf(buf + offset, rem, "%s:%d ", const_basename(file), line); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_PRINTF(sb, "%s:%d ", const_basename(file), line); break; } } } - ret = vsnprintf(buf + offset, rem, format, ap); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_APPEND(sb, vsnprintf, format, ap); /* For LOG_FILENAME_POS_LAST, print the source file info only when the caller ended the log * message in '\n'. If so, nip the last '\n' away, insert the source file info and re-append an * '\n'. All this to allow LOGP("start..."); LOGPC("...end\n") constructs. */ if (target->print_filename_pos == LOG_FILENAME_POS_LINE_END - && offset > 0 && bufoffset - 1 == '\n') { + && sb.pos > sb.buf && *(sb.pos - 1) == '\n') { switch (target->print_filename2) { case LOG_FILENAME_NONE: break; case LOG_FILENAME_PATH: - offset--; - len--; - ret = snprintf(buf + offset, rem, " (%s:%d)\n", file, line); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_DROP_TAIL(sb, 1); + OSMO_STRBUF_PRINTF(sb, " (%s:%d)\n", file, line); break; case LOG_FILENAME_BASENAME: - offset--; - len--; - ret = snprintf(buf + offset, rem, " (%s:%d)\n", const_basename(file), line); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + OSMO_STRBUF_DROP_TAIL(sb, 1); + OSMO_STRBUF_PRINTF(sb, " (%s:%d)\n", const_basename(file), line); break; } } @@ -618,21 +662,15 @@ if (target->use_color && c_subsys) { /* Ensure the last color escape is sent before the newline * (to not clobber journald, which works on single-lines only) */ - if (offset > 0 && bufoffset - 1 == '\n') { - offset--; rem++; - ret = snprintf(buf + offset, rem, OSMO_LOGCOLOR_END "\n"); + if (sb.pos > sb.buf && *(sb.pos - 1) == '\n') { + OSMO_STRBUF_DROP_TAIL(sb, 1); + OSMO_STRBUF_PRINTF(sb, OSMO_LOGCOLOR_END "\n"); } else { - ret = snprintf(buf + offset, rem, OSMO_LOGCOLOR_END); + OSMO_STRBUF_PRINTF(sb, OSMO_LOGCOLOR_END); } - - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); } err: - len = OSMO_MIN(buf_len - 1, len); - buflen = '\0'; - return len; + return OSMO_STRBUF_CHAR_COUNT(sb); } /* Format the log line for given target; use a stack buffer and call target->output */ @@ -720,6 +758,11 @@ subsys = map_subsys(subsys); +#if !defined(EMBEDDED) + if (!log_cache_check(subsys, level)) + return; +#endif + log_tgt_mutex_lock(); llist_for_each_entry(tar, &osmo_log_target_list, entry) { @@ -794,6 +837,9 @@ void log_add_target(struct log_target *target) { llist_add_tail(&target->entry, &osmo_log_target_list); +#if (!EMBEDDED) + log_cache_update_all(); +#endif } /*! Unregister a log target from the logging core @@ -802,6 +848,9 @@ void log_del_target(struct log_target *target) { llist_del(&target->entry); +#if (!EMBEDDED) + log_cache_update_all(); +#endif } /*! Reset (clear) the logging context */ @@ -962,6 +1011,9 @@ void log_set_log_level(struct log_target *target, int log_level) { target->loglevel = log_level; +#if !defined(EMBEDDED) + log_cache_update_all(); +#endif } /*! Set a category filter on a given log target @@ -978,6 +1030,10 @@ category = map_subsys(category); target->categoriescategory.enabled = !!enable; target->categoriescategory.loglevel = level; + +#if !defined(EMBEDDED) + log_cache_update(category, !!enable, level); +#endif } #if (!EMBEDDED) @@ -1086,6 +1142,15 @@ /* global log level */ target->loglevel = 0; + +#if !defined(EMBEDDED) + /* update cache */ + for (i = 0; i < osmo_log_info->num_cat; i++) { + const struct log_info_cat *c = &osmo_log_info->cati; + log_cache_update(i, c->enabled, c->loglevel); + } +#endif + return target; } @@ -1433,6 +1498,31 @@ return rc; } +/*! Enable the log level lookup cache to bypass string formatting and other code for log statements which are + * not actually enabled/needed by any existing log target. + * \retruns 0 in case of success, negative -errno in case of error. */ +int log_cache_enable(void) +{ +#if !defined(EMBEDDED) + if (log_level_lookup_cache) + return -EEXIST; + + log_level_lookup_cache = talloc_zero_array(osmo_log_info, uint8_t, osmo_log_info->num_cat); + if (!log_level_lookup_cache) + return -ENOMEM; + + /* copy everything for level lookup cache */ + log_tgt_mutex_lock(); + log_cache_update_all(); + log_tgt_mutex_unlock(); + + return 0; +#else + return -ENOTSUP; +#endif +} + + /*! Initialize the Osmocom logging core * \paramin inf Information regarding logging categories, could be NULL * \paramin ctx talloc context for logging allocations @@ -1526,6 +1616,11 @@ subsys = map_subsys(subsys); +#if !defined(EMBEDDED) + if (!log_cache_check(subsys, level)) + return 0; +#endif + /* TODO: The following could/should be cached (update on config) */ log_tgt_mutex_lock();
View file
libosmocore_1.9.3.tar.xz/src/core/osmo_io.c -> libosmocore_1.10.0.tar.xz/src/core/osmo_io.c
Changed
@@ -1,8 +1,8 @@ -/*! \file osmo_io.c +/* * New osmocom async I/O API. * - * (C) 2022 by Harald Welte <laforge@osmocom.org> - * (C) 2022-2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * (C) 2022-2024 by Harald Welte <laforge@osmocom.org> + * (C) 2022-2024 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * Author: Daniel Willmann <dwillmann@sysmocom.de> * * All Rights Reserved. @@ -21,7 +21,7 @@ */ #include "../config.h" -#if defined(__linux__) +#ifndef EMBEDDED #include <fcntl.h> #include <stdio.h> @@ -42,6 +42,11 @@ #include "osmo_io_internal.h" +/*! \addtogroup osmo_io + * @{ + * + * \file osmo_io.c */ + /*! This environment variable can be set to manually set the backend used in osmo_io */ #define OSMO_IO_BACKEND_ENV "LIBOSMO_IO_BACKEND" @@ -51,6 +56,13 @@ { 0, NULL } }; +const struct value_string osmo_iofd_mode_names = { + { OSMO_IO_FD_MODE_READ_WRITE, "read/write" }, + { OSMO_IO_FD_MODE_RECVFROM_SENDTO, "recvfrom/sendto" }, + { OSMO_IO_FD_MODE_RECVMSG_SENDMSG, "recvmsg/sendmsg" }, + { 0, NULL } +}; + static enum osmo_io_backend g_io_backend; /* Used by some tests, can't be static */ @@ -98,6 +110,15 @@ exit(1); } + OSMO_ASSERT(osmo_iofd_ops.close); + OSMO_ASSERT(osmo_iofd_ops.register_fd); + OSMO_ASSERT(osmo_iofd_ops.unregister_fd); + OSMO_ASSERT(osmo_iofd_ops.write_enable); + OSMO_ASSERT(osmo_iofd_ops.write_disable); + OSMO_ASSERT(osmo_iofd_ops.read_enable); + OSMO_ASSERT(osmo_iofd_ops.read_disable); + OSMO_ASSERT(osmo_iofd_ops.notify_connected); + osmo_iofd_init(); } @@ -105,8 +126,10 @@ * \paramin iofd the osmo_io file structure * \paramin action the action this msg(hdr) is for (read, write, ..) * \paramin msg the msg buffer to use. Will allocate a new one if NULL + * \paramin cmsg_size size (in bytes) of iofd_msghdr.cmsg buffer. Can be 0 if cmsg is not used. * \returns the newly allocated msghdr or NULL in case of error */ -struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg) +struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg, + size_t cmsg_size) { bool free_msg = false; struct iofd_msghdr *hdr; @@ -120,7 +143,7 @@ talloc_steal(iofd, msg); } - hdr = talloc_zero(iofd, struct iofd_msghdr); + hdr = talloc_zero_size(iofd, sizeof(struct iofd_msghdr) + cmsg_size); if (!hdr) { if (free_msg) talloc_free(msg); @@ -150,9 +173,7 @@ uint16_t headroom = iofd->msgb_alloc.headroom; OSMO_ASSERT(iofd->msgb_alloc.size < 0xffff - headroom); - return msgb_alloc_headroom_c(iofd, - iofd->msgb_alloc.size + headroom, headroom, - iofd->name ? : "iofd_msgb"); + return msgb_alloc_headroom_c(iofd, iofd->msgb_alloc.size + headroom, headroom, "osmo_io_msgb"); } /*! return the pending msgb in iofd or NULL if there is none*/ @@ -246,7 +267,7 @@ */ static enum iofd_seg_act iofd_handle_segmentation(struct osmo_io_fd *iofd, struct msgb *msg, struct msgb **pending_out) { - int extra_len, received_len; + int extra_len, received_len, expected_len; struct msgb *msg_pending; /* Save the start of message before segmentation_cb (which could change it) */ @@ -254,12 +275,15 @@ received_len = msgb_length(msg); - if (!iofd->io_ops.segmentation_cb) { + if (iofd->io_ops.segmentation_cb2) { + expected_len = iofd->io_ops.segmentation_cb2(iofd, msg); + } else if (iofd->io_ops.segmentation_cb) { + expected_len = iofd->io_ops.segmentation_cb(msg); + } else { *pending_out = NULL; return IOFD_SEG_ACT_HANDLE_ONE; } - int expected_len = iofd->io_ops.segmentation_cb(msg); if (expected_len == -EAGAIN) { goto defer; } else if (expected_len < 0) { @@ -306,6 +330,8 @@ int res; struct msgb *pending = NULL; + OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_READ_WRITE); + if (rc <= 0) { iofd->io_ops.read_cb(iofd, rc, msg); return; @@ -323,6 +349,11 @@ iofd->pending = pending; } +/*! completion handler: Internal function called by osmo_io_backend after a given I/O operation has completed + * \paramin iofd I/O file-descriptor on which I/O has completed + * \paramin msg message buffer containing data related to completed I/O + * \paramin rc result code with read size or error (-errno) + * \paramin hdr serialized msghdr containing state of completed I/O */ void iofd_handle_recv(struct osmo_io_fd *iofd, struct msgb *msg, int rc, struct iofd_msghdr *hdr) { talloc_steal(iofd->msgb_alloc.ctx, msg); @@ -333,29 +364,89 @@ case OSMO_IO_FD_MODE_RECVFROM_SENDTO: iofd->io_ops.recvfrom_cb(iofd, rc, msg, &hdr->osa); break; - case OSMO_IO_FD_MODE_SCTP_RECVMSG_SENDMSG: - /* TODO Implement */ + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + iofd->io_ops.recvmsg_cb(iofd, rc, msg, &hdr->hdr); + break; + default: OSMO_ASSERT(false); break; } } +/*! completion handler: Internal function called by osmo_io_backend after a given I/O operation has completed + * \paramin iofd I/O file-descriptor on which I/O has completed + * \paramin rc return value of the I/O operation + * \paramin msghdr serialized msghdr containing state of completed I/O + */ +void iofd_handle_send_completion(struct osmo_io_fd *iofd, int rc, struct iofd_msghdr *msghdr) +{ + struct msgb *msg = msghdr->msg; + + /* Incomplete write */ + if (rc > 0 && rc < msgb_length(msg)) { + /* Re-enqueue remaining data */ + msgb_pull(msg, rc); + msghdr->iov0.iov_len = msgb_length(msg); + iofd_txqueue_enqueue_front(iofd, msghdr); + return; + } + + /* Reenqueue the complete msgb */ + if (rc == -EAGAIN) { + iofd_txqueue_enqueue_front(iofd, msghdr); + return; + } + + /* All other failure and success cases are handled here */ + switch (msghdr->action) { + case IOFD_ACT_WRITE: + if (iofd->io_ops.write_cb) + iofd->io_ops.write_cb(iofd, rc, msg); + break; + case IOFD_ACT_SENDTO: + if (iofd->io_ops.sendto_cb) + iofd->io_ops.sendto_cb(iofd, rc, msg, &msghdr->osa); + break; + case IOFD_ACT_SENDMSG: + if (iofd->io_ops.sendmsg_cb) + iofd->io_ops.sendmsg_cb(iofd, rc, msg); + break; + default: + OSMO_ASSERT(0); + } + + msgb_free(msghdr->msg); + iofd_msghdr_free(msghdr); +} + /* Public functions */ -/*! Send a message through a connected socket. +/*! Write a message to a file descriptor / connected socket. + * The osmo_io_fd must be using OSMO_IO_FD_MODE_READ_WRITE. + * + * Appends the message to the internal transmit queue for eventual non-blocking + * write to the underlying socket/file descriptor. * - * Appends the message to the internal transmit queue. * If the function returns success (0) it will take ownership of the msgb and * internally call msgb_free() after the write request completes. - * In case of an error the msgb needs to be freed by the caller. - * \paramin iofd file descriptor to write to - * \paramin msg message buffer to write + * In case of an error, the msgb needs to be freed by the caller. + * + * \paramin iofd osmo_io_fd file descriptor to write data to + * \paramin msg message buffer containing the data to write * \returns 0 in case of success; a negative value in case of error */ int osmo_iofd_write_msgb(struct osmo_io_fd *iofd, struct msgb *msg) { int rc; - struct iofd_msghdr *msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_WRITE, msg); + + if (OSMO_UNLIKELY(msgb_length(msg) == 0)) { + LOGPIO(iofd, LOGL_ERROR, "Length is 0, rejecting msgb.\n"); + return -EINVAL; + } + + OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_READ_WRITE); + + struct iofd_msghdr *msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_WRITE, msg, 0); if (!msghdr) return -ENOMEM; @@ -376,11 +467,15 @@ } /*! Send a message through an unconnected socket. + * The osmo_io_fd must be using OSMO_IO_FD_MODE_RECVFROM_SENDTO. + * + * Appends the message to the internal transmit queue for eventual non-blocking + * sendto on the underlying socket/file descriptor. * - * Appends the message to the internal transmit queue. * If the function returns success (0), it will take ownership of the msgb and - * internally call msgb_free() after the write request completes. + * internally call msgb_free() after the sendto request completes. * In case of an error the msgb needs to be freed by the caller. + * * \paramin iofd file descriptor to write to * \paramin msg message buffer to send * \paramin sendto_flags Flags to pass to the send call @@ -391,9 +486,14 @@ { int rc; + if (OSMO_UNLIKELY(msgb_length(msg) == 0)) { + LOGPIO(iofd, LOGL_ERROR, "Length is 0, rejecting msgb.\n"); + return -EINVAL; + } + OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_RECVFROM_SENDTO); - struct iofd_msghdr *msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_SENDTO, msg); + struct iofd_msghdr *msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_SENDTO, msg, 0); if (!msghdr) return -ENOMEM; @@ -418,19 +518,163 @@ return 0; } +/*! osmo_io equivalent of the sendmsg(2) socket API call. + * The osmo_io_fd must be using OSMO_IO_FD_MODE_RECVMSG_SENDMSG. + * + * Appends the message to the internal transmit queue for eventual non-blocking + * sendmsg on the underlying socket/file descriptor. + * + * If the function returns success (0), it will take ownership of the msgb and + * internally call msgb_free() after the sendmsg request completes. + * In case of an error the msgb needs to be freed by the caller. + * + * \paramin iofd file descriptor to write to + * \paramin msg message buffer to send; is used to fill msgh->iov + * \paramin sendmsg_flags Flags to pass to the send call + * \paramin msgh 'struct msghdr' for name/control/flags. iov must be empty! + * \returns 0 in case of success; a negative value in case of error + */ +int osmo_iofd_sendmsg_msgb(struct osmo_io_fd *iofd, struct msgb *msg, int sendmsg_flags, const struct msghdr *msgh) +{ + int rc; + struct iofd_msghdr *msghdr; + + if (OSMO_UNLIKELY(msgb_length(msg) == 0)) { + LOGPIO(iofd, LOGL_ERROR, "Length is 0, rejecting msgb.\n"); + return -EINVAL; + } + + OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG); + + if (OSMO_UNLIKELY(msgh->msg_namelen > sizeof(msghdr->osa))) { + LOGPIO(iofd, LOGL_ERROR, "osmo_iofd_sendmsg msg_namelen (%u) > supported %zu bytes\n", + msgh->msg_namelen, sizeof(msghdr->osa)); + return -EINVAL; + } + + if (OSMO_UNLIKELY(msgh->msg_iovlen)) { + LOGPIO(iofd, LOGL_ERROR, "osmo_iofd_sendmsg must have all in 'struct msgb', not in 'msg_iov'\n"); + return -EINVAL; + } + + msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_SENDMSG, msg, msgh->msg_controllen); + if (!msghdr) + return -ENOMEM; + + /* copy over optional address */ + if (msgh->msg_name) { + memcpy(&msghdr->osa, msgh->msg_name, msgh->msg_namelen); + msghdr->hdr.msg_name = &msghdr->osa.u.sa; + msghdr->hdr.msg_namelen = msgh->msg_namelen; + } + + /* build iov from msgb */ + msghdr->iov0.iov_base = msgb_data(msghdr->msg); + msghdr->iov0.iov_len = msgb_length(msghdr->msg); + msghdr->hdr.msg_iov = &msghdr->iov0; + msghdr->hdr.msg_iovlen = 1; + + /* copy over the cmsg from the msghdr */ + if (msgh->msg_control && msgh->msg_controllen) { + msghdr->hdr.msg_control = msghdr->cmsg; + msghdr->hdr.msg_controllen = msgh->msg_controllen; + memcpy(msghdr->cmsg, msgh->msg_control, msgh->msg_controllen); + } + + /* copy over msg_flags */ + msghdr->hdr.msg_flags = sendmsg_flags; + + rc = iofd_txqueue_enqueue(iofd, msghdr); + if (rc < 0) { + iofd_msghdr_free(msghdr); + LOGPIO(iofd, LOGL_ERROR, "enqueueing message failed (%d). Rejecting msgb\n", rc); + return rc; + } + + return 0; +} + +static int check_mode_callback_compat(enum osmo_io_fd_mode mode, const struct osmo_io_ops *ops) +{ + switch (mode) { + case OSMO_IO_FD_MODE_READ_WRITE: + if (ops->recvfrom_cb || ops->sendto_cb) + return false; + if (ops->recvmsg_cb || ops->sendmsg_cb) + return false; + /* Forbid both segementation_cb set, something is wrong: */ + if (ops->segmentation_cb && ops->segmentation_cb2) + return false; + break; + case OSMO_IO_FD_MODE_RECVFROM_SENDTO: + if (ops->read_cb || ops->write_cb) + return false; + if (ops->recvmsg_cb || ops->sendmsg_cb) + return false; + break; + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + if (ops->recvfrom_cb || ops->sendto_cb) + return false; + if (ops->read_cb || ops->write_cb) + return false; + break; + default: + break; + } + + return true; +} + /*! Allocate and setup a new iofd. + * + * Use this to create a new osmo_io_fd, specifying the osmo_io_fd_mode and osmo_io_ops, as well as optionally + * the file-descriptor number and a human-readable name. This is the first function you call for any + * osmo_io_fd. + * + * The created osmo_io_fd is not yet registered, and hence can not be used for any I/O until a subsequent + * call to osmo_iofd_register(). + * + * The created osmo_io_fd is initialized with some default settings: + * * msgb allocations size: OSMO_IO_DEFAULT_MSGB_SIZE (1024) + * * msgb headroom: OSMO_IO_DEFAULT_MSGB_HEADROOM (128) + * * tx_queue depth: 32 + * + * Those values may be adjusted from their defaults by using osmo_iofd_set_alloc_info() and + * osmo_iofd_set_txqueue_max_length() on the osmo_io_fd. + * * \paramin ctx the parent context from which to allocate - * \paramin fd the underlying system file descriptor - * \paramin name the name of the iofd - * \paramin mode the mode of the iofd, whether it should use read()/write(), sendto()/recvfrom() - * \paramin ioops structure with read/write/send/recv callbacks - * \paramin data user data pointer accessible by the ioops callbacks + * \paramin fd the underlying system file descriptor. May be -1 if not known yet; must then be specified + * at subsequent osmo_iofd_register() time. + * \paramin name the optional human-readable name of the iofd; may be NULL + * \paramin mode the osmo_io_fd_mode of the iofd, whether it should use read()/write(), sendto()/recvfrom() + * semantics. + * \paramin ioops structure specifying the read/write/send/recv callbacks. Will be copied to the iofd, so + * the caller does not have to keep it around after issuing the osmo_iofd_setup call. + * \paramin data opaque user data pointer accessible by the ioops callbacks * \returns The newly allocated osmo_io_fd struct or NULL on failure */ struct osmo_io_fd *osmo_iofd_setup(const void *ctx, int fd, const char *name, enum osmo_io_fd_mode mode, const struct osmo_io_ops *ioops, void *data) { - struct osmo_io_fd *iofd = talloc_zero(ctx, struct osmo_io_fd); + struct osmo_io_fd *iofd; + + /* reject unsupported/unknown modes */ + switch (mode) { + case OSMO_IO_FD_MODE_READ_WRITE: + case OSMO_IO_FD_MODE_RECVFROM_SENDTO: + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + break; + default: + return NULL; + } + + if (ioops && !check_mode_callback_compat(mode, ioops)) { + LOGP(DLIO, LOGL_ERROR, "iofd(%s): rejecting call-backs incompatible with mode %s\n", + name ? name : "unknown", osmo_iofd_mode_name(mode)); + return NULL; + } + + iofd = talloc_zero(ctx, struct osmo_io_fd); if (!iofd) return NULL; @@ -458,10 +702,34 @@ return iofd; } -/*! Register the fd with the underlying backend. +/*! Set the size of the control message buffer allocated when submitting recvmsg. + * + * If your osmo_io_fd is in OSMO_IO_FD_MODE_RECVMSG_SENDMSG mode, this API function can be used to tell the + * osmo_io code how much memory should be allocated for the cmsg (control message) buffer when performing + * recvmsg(). */ +int osmo_iofd_set_cmsg_size(struct osmo_io_fd *iofd, size_t cmsg_size) +{ + if (iofd->mode != OSMO_IO_FD_MODE_RECVMSG_SENDMSG) + return -EINVAL; + + iofd->cmsg_size = cmsg_size; + return 0; +} + +/*! Register the osmo_io_fd for active I/O. + * + * Calling this function will register a previously initialized osmo_io_fd for performing I/O. + * + * If the osmo_iofd has a read_cb/recvfrom_cb_recvmsg_cb set in its osmo_io_ops, read/receive will be + * automatically enabled and the respective call-back is called at any time data becomes available. + * + * If there is to-be-transmitted data in the transmit queue, write will be automatically enabled, allowing + * the transmit queue to be drained as soon as the fd/socket becomes writable. * * \paramin iofd the iofd file descriptor - * \paramin fd the system fd number that will be registeres. If negative will use the one already set. + * \paramin fd the system fd number that will be registered. If you did not yet specify the file descriptor + * number during osmo_fd_setup(), or if it has changed since then, you can state the new file descriptor + * number as argument. If you wish to proceed with the previously specified file descriptor number, pass -1. * \returns zero on success, a negative value on error */ int osmo_iofd_register(struct osmo_io_fd *iofd, int fd) @@ -470,14 +738,22 @@ if (fd >= 0) iofd->fd = fd; + else if (iofd->fd < 0) { + /* this might happen if both osmo_iofd_setup() and osmo_iofd_register() are called with -1 */ + LOGPIO(iofd, LOGL_ERROR, "Cannot register io_fd using invalid fd == %d\n", iofd->fd); + return -EBADF; + } - if (osmo_iofd_ops.register_fd) - rc = osmo_iofd_ops.register_fd(iofd); + rc = osmo_iofd_ops.register_fd(iofd); if (rc) return rc; IOFD_FLAG_UNSET(iofd, IOFD_FLAG_CLOSED); - osmo_iofd_ops.read_enable(iofd); + if ((iofd->mode == OSMO_IO_FD_MODE_READ_WRITE && iofd->io_ops.read_cb) || + (iofd->mode == OSMO_IO_FD_MODE_RECVFROM_SENDTO && iofd->io_ops.recvfrom_cb) || + (iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG && iofd->io_ops.recvmsg_cb)) { + osmo_iofd_ops.read_enable(iofd); + } if (iofd->tx_queue.current_length > 0) osmo_iofd_ops.write_enable(iofd); @@ -485,21 +761,20 @@ return rc; } -/*! Unregister the fd from the underlying backend. +/*! Unregister the given osmo_io_fd from osmo_io. + * + * After an osmo_io_fd has been successfully unregistered, it can no longer perform any I/O via osmo_io. + * However, it can be subsequently re-registered using osmo_iofd_register(). * * \paramin iofd the file descriptor * \returns zero on success, a negative value on error */ int osmo_iofd_unregister(struct osmo_io_fd *iofd) { - if (osmo_iofd_ops.unregister_fd) - return osmo_iofd_ops.unregister_fd(iofd); - IOFD_FLAG_SET(iofd, IOFD_FLAG_CLOSED); - - return 0; + return osmo_iofd_ops.unregister_fd(iofd); } -/*! Get the number of messages in the tx queue. +/*! Retrieve the number of messages pending in the transmit queue. * * \paramin iofd the file descriptor */ @@ -508,7 +783,7 @@ return iofd->tx_queue.current_length; } -/*! Clear the transmit queue of the the iofd. +/*! Clear the transmit queue of the given osmo_io_fd. * * This function frees all messages currently pending in the transmit queue * \paramin iofd the file descriptor @@ -522,10 +797,13 @@ } } -/*! Free the iofd. +/*! Free the given osmo_io_fd. + * + * The iofd will be automatically closed before via osmo_iofd_close() which in turn will unregister + * it and clear any pending transmit queue items. You must not reference the iofd + * after calling this function. However, it is safe to call this function from any of osmo_io + * call-backs; in this case, actual free will be internally delayed until that call-back completes. * - * This function is safe to use in the read/write callbacks and will defer freeing it until safe to do so. - * The iofd will be closed before. * \paramin iofd the file descriptor */ void osmo_iofd_free(struct osmo_io_fd *iofd) @@ -544,12 +822,12 @@ } } -/*! Close the iofd. +/*! Close the given osmo_io_fd. * - * This function closes the underlying fd and clears any messages in the tx queue - * The iofd is not freed and can be assigned a new file descriptor with osmo_iofd_register() + * This function closes the underlying fd, unregisters it from osmo_io and clears any messages in the tx + * queue. The iofd itself is not freed and can be assigned a new file descriptor with osmo_iofd_register() * \paramin iofd the file descriptor - * \ returns 0 on success, a negative value otherwise + * \returns 0 on success, a negative value otherwise */ int osmo_iofd_close(struct osmo_io_fd *iofd) { @@ -566,8 +844,7 @@ iofd->pending = NULL; - if (osmo_iofd_ops.close) - rc = osmo_iofd_ops.close(iofd); + rc = osmo_iofd_ops.close(iofd); iofd->fd = -1; return rc; } @@ -592,7 +869,11 @@ iofd->tx_queue.max_length = max_length; } -/*! Get the associated user-data from an iofd. +/*! Retrieve the associated user-data from an osmo_io_fd. + * + * A call to this function will return the opaque user data pointer which was specified previously + * via osmo_iofd_setup() or via osmo_iofd_set_data(). + * * \paramin iofd the file descriptor * \returns the data that was previously set with \ref osmo_iofd_setup() */ @@ -601,7 +882,11 @@ return iofd->data; } -/*! Set the associated user-data from an iofd. +/*! Set the associated user-data from an osmo_io_fd. + * + * Calling this function will set/overwrite the opaque user data pointer, which can later be retrieved using + * osmo_iofd_get_data(). + * * \paramin iofd the file descriptor * \paramin data the data to set */ @@ -610,7 +895,8 @@ iofd->data = data; } -/*! Get the private number from an iofd. +/*! Retrieve the private number from an osmo_io_fd. + * Calling this function will retrieve the private user number previously set via osmo_iofd_set_priv_nr(). * \paramin iofd the file descriptor * \returns the private number that was previously set with \ref osmo_iofd_set_priv_nr() */ @@ -619,7 +905,9 @@ return iofd->priv_nr; } -/*! Set the private number from an iofd. +/*! Set the private number of an osmo_io_fd. + * The priv_nr passed in via this call can later be retrieved via osmo_iofd_get_priv_nr(). It provides + * a way how additional context can be stored in the osmo_io_fd beyond the opaque 'data' pointer. * \paramin iofd the file descriptor * \paramin priv_nr the private number to set */ @@ -628,7 +916,7 @@ iofd->priv_nr = priv_nr; } -/*! Get the underlying file descriptor from an iofd. +/*! Retrieve the underlying file descriptor from an osmo_io_fd. * \paramin iofd the file descriptor * \returns the underlying file descriptor number */ int osmo_iofd_get_fd(const struct osmo_io_fd *iofd) @@ -636,7 +924,7 @@ return iofd->fd; } -/*! Get the name of the file descriptor. +/*! Retrieve the human-readable name of the given osmo_io_fd. * \paramin iofd the file descriptor * \returns the name of the iofd as given in \ref osmo_iofd_setup() */ const char *osmo_iofd_get_name(const struct osmo_io_fd *iofd) @@ -644,7 +932,8 @@ return iofd->name; } -/*! Set the name of the file descriptor. +/*! Set the human-readable name of the file descriptor. + * The given name will be used as context by all related logging and future calls to osmo_iofd_get_name(). * \paramin iofd the file descriptor * \paramin name the name to set on the file descriptor */ void osmo_iofd_set_name(struct osmo_io_fd *iofd, const char *name) @@ -652,22 +941,73 @@ osmo_talloc_replace_string(iofd, &iofd->name, name); } -/*! Set the osmo_io_ops for an iofd. +/*! Set the osmo_io_ops calbacks for an osmo_io_fd. + * This function can be used to update/overwrite the call-back functions for the given osmo_io_fd; it + * replaces the currently-set call-back function pointers from a previous call to osmo_iofd_set_ioops() + * or the original osmo_iofd_setup(). * \paramin iofd Target iofd file descriptor - * \paramin ioops osmo_io_ops structure to be set */ -void osmo_iofd_set_ioops(struct osmo_io_fd *iofd, const struct osmo_io_ops *ioops) -{ + * \paramin ioops osmo_io_ops structure to be copied to the osmo_io_fd. + * \returns 0 on success, negative on error */ +int osmo_iofd_set_ioops(struct osmo_io_fd *iofd, const struct osmo_io_ops *ioops) +{ + if (!check_mode_callback_compat(iofd->mode, ioops)) { + LOGPIO(iofd, LOGL_ERROR, "rejecting call-backs incompatible with mode %s\n", + osmo_iofd_mode_name(iofd->mode)); + return -EINVAL; + } + iofd->io_ops = *ioops; + + switch (iofd->mode) { + case OSMO_IO_FD_MODE_READ_WRITE: + if (iofd->io_ops.read_cb) + osmo_iofd_ops.read_enable(iofd); + else + osmo_iofd_ops.read_disable(iofd); + break; + case OSMO_IO_FD_MODE_RECVFROM_SENDTO: + if (iofd->io_ops.recvfrom_cb) + osmo_iofd_ops.read_enable(iofd); + else + osmo_iofd_ops.read_disable(iofd); + break; + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + if (iofd->io_ops.recvmsg_cb) + osmo_iofd_ops.read_enable(iofd); + else + osmo_iofd_ops.read_disable(iofd); + break; + default: + OSMO_ASSERT(0); + } + + return 0; } -/*! Notify the user if/when the socket is connected. - * When the socket is connected the write_cb will be called. +/*! Retrieve the osmo_io_ops for an iofd. + * \paramin iofd Target iofd file descriptor + * \paramin ioops caller-allocated osmo_io_ops structure to be filled */ +void osmo_iofd_get_ioops(struct osmo_io_fd *iofd, struct osmo_io_ops *ioops) +{ + *ioops = iofd->io_ops; +} + +/*! Request notification of the user if/when a client socket is connected. + * Calling this function will request osmo_io to notify the user (via + * write call-back) once a non-blocking outbound connect() of the + * socket completes. + * + * This only works for connection oriented sockets in either + * OSMO_IO_FD_MODE_READ_WRITE or OSMO_IO_FD_MODE_RECVMSG_SENDMSG mode. + * * \paramin iofd the file descriptor */ void osmo_iofd_notify_connected(struct osmo_io_fd *iofd) { - OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_READ_WRITE); - osmo_iofd_ops.write_enable(iofd); + OSMO_ASSERT(iofd->mode == OSMO_IO_FD_MODE_READ_WRITE || + iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG); + osmo_iofd_ops.notify_connected(iofd); } +/*! @} */ -#endif /* defined(__linux__) */ +#endif /* ifndef(EMBEDDED) */
View file
libosmocore_1.9.3.tar.xz/src/core/osmo_io_internal.h -> libosmocore_1.10.0.tar.xz/src/core/osmo_io_internal.h
Changed
@@ -4,6 +4,7 @@ #include <unistd.h> #include <stdbool.h> +#include <netinet/sctp.h> #include <osmocom/core/osmo_io.h> #include <osmocom/core/linuxlist.h> @@ -31,12 +32,14 @@ void (*write_disable)(struct osmo_io_fd *iofd); void (*read_enable)(struct osmo_io_fd *iofd); void (*read_disable)(struct osmo_io_fd *iofd); + void (*notify_connected)(struct osmo_io_fd *iofd); }; #define IOFD_FLAG_CLOSED (1<<0) #define IOFD_FLAG_IN_CALLBACK (1<<1) #define IOFD_FLAG_TO_FREE (1<<2) #define IOFD_FLAG_NOTIFY_CONNECTED (1<<3) +#define IOFD_FLAG_FD_REGISTERED (1<<4) #define IOFD_FLAG_SET(iofd, flag) \ (iofd)->flags |= (flag) @@ -70,6 +73,9 @@ /*! private number, extending \a data */ unsigned int priv_nr; + /*! size of iofd_msghdr.cmsg when allocated in recvmsg path */ + size_t cmsg_size; + struct { /*! talloc context from which to allocate msgb when reading */ const void *ctx; @@ -98,6 +104,8 @@ void *read_msghdr; void *write_msghdr; /* TODO: index into array of registered fd's? */ + /* osmo_fd for non-blocking connect handling */ + struct osmo_fd connect_ofd; } uring; } u; }; @@ -107,21 +115,33 @@ IOFD_ACT_WRITE, IOFD_ACT_RECVFROM, IOFD_ACT_SENDTO, - // TODO: SCTP_* + IOFD_ACT_RECVMSG, + IOFD_ACT_SENDMSG, }; -/* serialized version of 'struct msghdr' employed by sendmsg/recvmsg */ +/*! serialized version of 'struct msghdr' employed by sendmsg/recvmsg */ struct iofd_msghdr { + /*! entry into osmo_io_fd.tx_queue.msg_queue */ struct llist_head list; enum iofd_msg_action action; + /*! the 'struct msghdr' we are wrapping/ecapsulating here */ struct msghdr hdr; + /*! socket address of the remote peer */ struct osmo_sockaddr osa; + /*! io-vector we need to pass as argument to sendmsg/recvmsg; is set up + * to point into msg below */ struct iovec iov1; + /*! flags we pass as argument to sendmsg / recvmsg */ int flags; + /*! message-buffer containing data for this I/O operation */ struct msgb *msg; + /*! I/O file descriptor on which we perform this I/O operation */ struct osmo_io_fd *iofd; + + /*! control message buffer for passing sctp_sndrcvinfo along */ + char cmsg0; /* size is determined by iofd->cmsg_size on recvmsg, and by mcghdr->msg_controllen on sendmsg */ }; enum iofd_seg_act { @@ -130,7 +150,7 @@ IOFD_SEG_ACT_DEFER, }; -struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg); +struct iofd_msghdr *iofd_msghdr_alloc(struct osmo_io_fd *iofd, enum iofd_msg_action action, struct msgb *msg, size_t cmsg_size); void iofd_msghdr_free(struct iofd_msghdr *msghdr); struct msgb *iofd_msgb_alloc(struct osmo_io_fd *iofd); @@ -138,6 +158,7 @@ struct msgb *iofd_msgb_pending_or_alloc(struct osmo_io_fd *iofd); void iofd_handle_recv(struct osmo_io_fd *iofd, struct msgb *msg, int rc, struct iofd_msghdr *msghdr); +void iofd_handle_send_completion(struct osmo_io_fd *iofd, int rc, struct iofd_msghdr *msghdr); void iofd_handle_segmented_read(struct osmo_io_fd *iofd, struct msgb *msg, int rc); int iofd_txqueue_enqueue(struct osmo_io_fd *iofd, struct iofd_msghdr *msghdr);
View file
libosmocore_1.9.3.tar.xz/src/core/osmo_io_poll.c -> libosmocore_1.10.0.tar.xz/src/core/osmo_io_poll.c
Changed
@@ -21,7 +21,7 @@ */ #include "../config.h" -#if defined(__linux__) +#ifndef EMBEDDED #include <errno.h> #include <stdio.h> @@ -49,6 +49,7 @@ if (what & OSMO_FD_READ) { struct iofd_msghdr hdr; + msg = iofd_msgb_pending_or_alloc(iofd); if (!msg) { LOGPIO(iofd, LOGL_ERROR, "Could not allocate msgb for reading\n"); @@ -58,16 +59,22 @@ hdr.msg = msg; hdr.iov0.iov_base = msg->tail; hdr.iov0.iov_len = msgb_tailroom(msg); - hdr.hdr.msg_iov = &hdr.iov0; - hdr.hdr.msg_iovlen = 1; - hdr.hdr.msg_name = &hdr.osa.u.sa; - hdr.hdr.msg_namelen = sizeof(struct osmo_sockaddr); + hdr.hdr = (struct msghdr) { + .msg_iov = &hdr.iov0, + .msg_iovlen = 1, + .msg_name = &hdr.osa.u.sa, + .msg_namelen = sizeof(struct osmo_sockaddr), + }; + if (iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG) { + hdr.hdr.msg_control = alloca(iofd->cmsg_size); + hdr.hdr.msg_controllen = iofd->cmsg_size; + } rc = recvmsg(ofd->fd, &hdr.hdr, flags); if (rc > 0) msgb_put(msg, rc); - iofd_handle_recv(iofd, msg, rc, &hdr); + iofd_handle_recv(iofd, msg, (rc < 0 && errno > 0) ? -errno : rc, &hdr); } if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED)) @@ -76,38 +83,27 @@ if (what & OSMO_FD_WRITE) { struct iofd_msghdr *msghdr = iofd_txqueue_dequeue(iofd); if (msghdr) { - msg = msghdr->msg; - rc = sendmsg(ofd->fd, &msghdr->hdr, msghdr->flags); - if (rc > 0 && rc < msgb_length(msg)) { - msgb_pull(msg, rc); - iofd_txqueue_enqueue_front(iofd, msghdr); - return; - } - + iofd_handle_send_completion(iofd, (rc < 0 && errno > 0) ? -errno : rc, msghdr); + } else { + /* Socket is writable, but we have no data to send. A non-blocking/async + connect() is signalled this way. */ switch (iofd->mode) { case OSMO_IO_FD_MODE_READ_WRITE: - iofd->io_ops.write_cb(iofd, rc, msg); + iofd->io_ops.write_cb(iofd, 0, NULL); break; case OSMO_IO_FD_MODE_RECVFROM_SENDTO: - iofd->io_ops.sendto_cb(iofd, rc, msg, &msghdr->osa); + iofd->io_ops.sendto_cb(iofd, 0, NULL, NULL); + break; + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + iofd->io_ops.sendmsg_cb(iofd, 0, NULL); break; - case OSMO_IO_FD_MODE_SCTP_RECVMSG_SENDMSG: - OSMO_ASSERT(false); + default: break; } - - talloc_free(msghdr); - msgb_free(msg); - } else { - if (iofd->mode == OSMO_IO_FD_MODE_READ_WRITE) - /* Socket is writable, but we have no data to send. A non-blocking/async - connect() is signalled this way. */ - iofd->io_ops.write_cb(iofd, 0, NULL); if (osmo_iofd_txqueue_len(iofd) == 0) iofd_poll_ops.write_disable(iofd); } - } } @@ -127,48 +123,70 @@ return 0; } -int iofd_poll_register(struct osmo_io_fd *iofd) +static int iofd_poll_register(struct osmo_io_fd *iofd) { struct osmo_fd *ofd = &iofd->u.poll.ofd; + int rc; + + if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_FD_REGISTERED)) + return 0; osmo_fd_setup(ofd, iofd->fd, 0, &iofd_poll_ofd_cb_dispatch, iofd, 0); - return osmo_fd_register(ofd); + rc = osmo_fd_register(ofd); + if (!rc) + IOFD_FLAG_SET(iofd, IOFD_FLAG_FD_REGISTERED); + return rc; } -int iofd_poll_unregister(struct osmo_io_fd *iofd) +static int iofd_poll_unregister(struct osmo_io_fd *iofd) { struct osmo_fd *ofd = &iofd->u.poll.ofd; + + if (!IOFD_FLAG_ISSET(iofd, IOFD_FLAG_FD_REGISTERED)) + return 0; osmo_fd_unregister(ofd); + IOFD_FLAG_UNSET(iofd, IOFD_FLAG_FD_REGISTERED); return 0; } -int iofd_poll_close(struct osmo_io_fd *iofd) +static int iofd_poll_close(struct osmo_io_fd *iofd) { + iofd_poll_unregister(iofd); osmo_fd_close(&iofd->u.poll.ofd); return 0; } -void iofd_poll_read_enable(struct osmo_io_fd *iofd) +static void iofd_poll_read_enable(struct osmo_io_fd *iofd) { osmo_fd_read_enable(&iofd->u.poll.ofd); } -void iofd_poll_read_disable(struct osmo_io_fd *iofd) +static void iofd_poll_read_disable(struct osmo_io_fd *iofd) { osmo_fd_read_disable(&iofd->u.poll.ofd); } -void iofd_poll_write_enable(struct osmo_io_fd *iofd) +static void iofd_poll_write_enable(struct osmo_io_fd *iofd) { osmo_fd_write_enable(&iofd->u.poll.ofd); } -void iofd_poll_write_disable(struct osmo_io_fd *iofd) +static void iofd_poll_write_disable(struct osmo_io_fd *iofd) { osmo_fd_write_disable(&iofd->u.poll.ofd); } +static void iofd_poll_notify_connected(struct osmo_io_fd *iofd) +{ + int rc; + + rc = iofd_poll_register(iofd); + if (rc < 0) + return; + osmo_fd_write_enable(&iofd->u.poll.ofd); +} + const struct iofd_backend_ops iofd_poll_ops = { .register_fd = iofd_poll_register, .unregister_fd = iofd_poll_unregister, @@ -177,6 +195,7 @@ .write_disable = iofd_poll_write_disable, .read_enable = iofd_poll_read_enable, .read_disable = iofd_poll_read_disable, + .notify_connected = iofd_poll_notify_connected, }; -#endif /* defined(__linux__) */ +#endif /* ifndef EMBEDDED */
View file
libosmocore_1.9.3.tar.xz/src/core/osmo_io_uring.c -> libosmocore_1.10.0.tar.xz/src/core/osmo_io_uring.c
Changed
@@ -3,6 +3,7 @@ * * (C) 2022-2023 by sysmocom s.f.m.c. * Author: Daniel Willmann <daniel@sysmocom.de> + * (C) 2023-2024 by Harald Welte <laforge@osmocom.org> * * All Rights Reserved. * @@ -35,6 +36,8 @@ #include <stdbool.h> #include <errno.h> +#include <netinet/in.h> +#include <netinet/sctp.h> #include <sys/eventfd.h> #include <liburing.h> @@ -59,6 +62,8 @@ static __thread struct osmo_io_uring g_ring; static void iofd_uring_cqe(struct io_uring *ring); + +/*! read call-back for eventfd notifying us if entries are in the completion queue */ static int iofd_uring_poll_cb(struct osmo_fd *ofd, unsigned int what) { struct io_uring *ring = ofd->data; @@ -83,20 +88,33 @@ /*! initialize the uring and tie it into our event loop */ void osmo_iofd_uring_init(void) { - int rc; + int rc, evfd; + rc = io_uring_queue_init(IOFD_URING_ENTRIES, &g_ring.ring, 0); if (rc < 0) - OSMO_ASSERT(0); + osmo_panic("failure during io_uring_queue_init(): %s\n", strerror(-rc)); rc = eventfd(0, 0); if (rc < 0) { io_uring_queue_exit(&g_ring.ring); - OSMO_ASSERT(0); + osmo_panic("failure creating eventfd(0, 0) for io_uring: %s\n", strerror(-rc)); } + evfd = rc; - osmo_fd_setup(&g_ring.event_ofd, rc, OSMO_FD_READ, iofd_uring_poll_cb, &g_ring.ring, 0); - osmo_fd_register(&g_ring.event_ofd); - io_uring_register_eventfd(&g_ring.ring, rc); + osmo_fd_setup(&g_ring.event_ofd, evfd, OSMO_FD_READ, iofd_uring_poll_cb, &g_ring.ring, 0); + rc = osmo_fd_register(&g_ring.event_ofd); + if (rc < 0) { + close(evfd); + io_uring_queue_exit(&g_ring.ring); + osmo_panic("failure registering io_uring-eventfd as osmo_fd: %d\n", rc); + } + rc = io_uring_register_eventfd(&g_ring.ring, evfd); + if (rc < 0) { + osmo_fd_unregister(&g_ring.event_ofd); + close(evfd); + io_uring_queue_exit(&g_ring.ring); + osmo_panic("failure registering eventfd with io_uring: %s\n", strerror(-rc)); + } } @@ -112,7 +130,7 @@ OSMO_ASSERT(0); } - msghdr = iofd_msghdr_alloc(iofd, action, msg); + msghdr = iofd_msghdr_alloc(iofd, action, msg, iofd->cmsg_size); if (!msghdr) { LOGPIO(iofd, LOGL_ERROR, "Could not allocate msghdr for reading\n"); OSMO_ASSERT(0); @@ -124,6 +142,10 @@ switch (action) { case IOFD_ACT_READ: break; + case IOFD_ACT_RECVMSG: + msghdr->hdr.msg_control = msghdr->cmsg; + msghdr->hdr.msg_controllen = iofd->cmsg_size; + /* fall-through */ case IOFD_ACT_RECVFROM: msghdr->hdr.msg_iov = &msghdr->iov0; msghdr->hdr.msg_iovlen = 1; @@ -144,6 +166,7 @@ case IOFD_ACT_READ: io_uring_prep_readv(sqe, iofd->fd, msghdr->iov, 1, 0); break; + case IOFD_ACT_RECVMSG: case IOFD_ACT_RECVFROM: io_uring_prep_recvmsg(sqe, iofd->fd, &msghdr->hdr, msghdr->flags); break; @@ -157,6 +180,7 @@ iofd->u.uring.read_msghdr = msghdr; } +/*! completion call-back for READ/RECVFROM */ static void iofd_uring_handle_recv(struct iofd_msghdr *msghdr, int rc) { struct osmo_io_fd *iofd = msghdr->iofd; @@ -179,51 +203,33 @@ static int iofd_uring_submit_tx(struct osmo_io_fd *iofd); +/*! completion call-back for WRITE/SENDTO */ static void iofd_uring_handle_tx(struct iofd_msghdr *msghdr, int rc) { struct osmo_io_fd *iofd = msghdr->iofd; - struct msgb *msg = msghdr->msg; - - if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED)) - goto out_free; - - /* Error during write */ - if (rc < 0) { - if (msghdr->action == IOFD_ACT_WRITE) - iofd->io_ops.write_cb(iofd, rc, msg); - else if (msghdr->action == IOFD_ACT_SENDTO) - iofd->io_ops.sendto_cb(iofd, rc, msg, &msghdr->osa); - else - OSMO_ASSERT(0); - goto out_free; - } - /* Incomplete write */ - if (rc < msgb_length(msg)) { - /* Re-enqueue remaining data */ - msgb_pull(msg, rc); - msghdr->iov0.iov_len = msgb_length(msg); - iofd_txqueue_enqueue_front(iofd, msghdr); - goto out; + /* Detach msghdr from iofd. It might get freed here or it is freed during iofd_handle_send_completion(). + * If there is pending data to send, iofd_uring_submit_tx() will attach it again. + * iofd_handle_send_completion() will invoke a callback function to signal the possibility of write/send. + * This callback function might close iofd, leading to the potential freeing of iofd->u.uring.write_msghdr if + * still attached. Since iofd_handle_send_completion() frees msghdr at the end of the function, detaching + * msghdr here prevents a double-free bug. */ + if (iofd->u.uring.write_msghdr == msghdr) + iofd->u.uring.write_msghdr = NULL; + + if (OSMO_UNLIKELY(IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED))) { + msgb_free(msghdr->msg); + iofd_msghdr_free(msghdr); + } else { + iofd_handle_send_completion(iofd, rc, msghdr); } - if (msghdr->action == IOFD_ACT_WRITE) - iofd->io_ops.write_cb(iofd, rc, msg); - else if (msghdr->action == IOFD_ACT_SENDTO) - iofd->io_ops.sendto_cb(iofd, rc, msg, &msghdr->osa); - else - OSMO_ASSERT(0); - -out_free: - msgb_free(msghdr->msg); - iofd_msghdr_free(msghdr); - -out: - iofd->u.uring.write_msghdr = NULL; + /* submit the next to-be-transmitted message for this file descriptor */ if (iofd->u.uring.write_enabled && !IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED)) iofd_uring_submit_tx(iofd); } +/*! handle completion of a single I/O message */ static void iofd_uring_handle_completion(struct iofd_msghdr *msghdr, int res) { struct osmo_io_fd *iofd = msghdr->iofd; @@ -233,23 +239,25 @@ switch (msghdr->action) { case IOFD_ACT_READ: case IOFD_ACT_RECVFROM: + case IOFD_ACT_RECVMSG: iofd_uring_handle_recv(msghdr, res); break; case IOFD_ACT_WRITE: case IOFD_ACT_SENDTO: + case IOFD_ACT_SENDMSG: iofd_uring_handle_tx(msghdr, res); break; default: OSMO_ASSERT(0) } - if (!iofd->u.uring.read_msghdr && !iofd->u.uring.write_msghdr) - IOFD_FLAG_UNSET(iofd, IOFD_FLAG_IN_CALLBACK); + IOFD_FLAG_UNSET(iofd, IOFD_FLAG_IN_CALLBACK); if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_TO_FREE) && !iofd->u.uring.read_msghdr && !iofd->u.uring.write_msghdr) talloc_free(iofd); } +/*! process all pending completion queue entries in given io_uring */ static void iofd_uring_cqe(struct io_uring *ring) { int rc; @@ -264,6 +272,11 @@ io_uring_cqe_seen(ring, cqe); continue; } + if (!msghdr->iofd) { + io_uring_cqe_seen(ring, cqe); + iofd_msghdr_free(msghdr); + continue; + } rc = cqe->res; /* Hand the entry back to the kernel before */ @@ -274,6 +287,7 @@ } } +/*! will submit the next to-be-transmitted message for given iofd */ static int iofd_uring_submit_tx(struct osmo_io_fd *iofd) { struct io_uring_sqe *sqe; @@ -294,6 +308,7 @@ switch (msghdr->action) { case IOFD_ACT_WRITE: case IOFD_ACT_SENDTO: + case IOFD_ACT_SENDMSG: io_uring_prep_sendmsg(sqe, msghdr->iofd->fd, &msghdr->hdr, msghdr->flags); break; default: @@ -317,23 +332,39 @@ static int iofd_uring_unregister(struct osmo_io_fd *iofd) { struct io_uring_sqe *sqe; + struct iofd_msghdr *msghdr; + if (iofd->u.uring.read_msghdr) { + msghdr = iofd->u.uring.read_msghdr; sqe = io_uring_get_sqe(&g_ring.ring); OSMO_ASSERT(sqe != NULL); io_uring_sqe_set_data(sqe, NULL); LOGPIO(iofd, LOGL_DEBUG, "Cancelling read\n"); - io_uring_prep_cancel(sqe, iofd->u.uring.read_msghdr, 0); + iofd->u.uring.read_msghdr = NULL; + talloc_steal(OTC_GLOBAL, msghdr); + msghdr->iofd = NULL; + io_uring_prep_cancel(sqe, msghdr, 0); } if (iofd->u.uring.write_msghdr) { + msghdr = iofd->u.uring.write_msghdr; sqe = io_uring_get_sqe(&g_ring.ring); OSMO_ASSERT(sqe != NULL); io_uring_sqe_set_data(sqe, NULL); LOGPIO(iofd, LOGL_DEBUG, "Cancelling write\n"); - io_uring_prep_cancel(sqe, iofd->u.uring.write_msghdr, 0); + iofd->u.uring.write_msghdr = NULL; + talloc_steal(OTC_GLOBAL, msghdr); + msgb_free(msghdr->msg); + msghdr->iofd = NULL; + io_uring_prep_cancel(sqe, msghdr, 0); } io_uring_submit(&g_ring.ring); + if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED)) { + osmo_fd_unregister(&iofd->u.uring.connect_ofd); + IOFD_FLAG_UNSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED); + } + return 0; } @@ -344,6 +375,10 @@ if (iofd->u.uring.write_msghdr) return; + /* This function is called again, once the socket is connected. */ + if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED)) + return; + if (osmo_iofd_txqueue_len(iofd) > 0) iofd_uring_submit_tx(iofd); else if (iofd->mode == OSMO_IO_FD_MODE_READ_WRITE) { @@ -355,21 +390,20 @@ LOGPIO(iofd, LOGL_ERROR, "Could not allocate msgb for writing\n"); OSMO_ASSERT(0); } - msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_WRITE, msg); + msghdr = iofd_msghdr_alloc(iofd, IOFD_ACT_WRITE, msg, 0); if (!msghdr) { LOGPIO(iofd, LOGL_ERROR, "Could not allocate msghdr for writing\n"); OSMO_ASSERT(0); } msghdr->iov0.iov_base = msgb_data(msg); - msghdr->iov0.iov_len = msgb_tailroom(msg); + msghdr->iov0.iov_len = msgb_length(msg); sqe = io_uring_get_sqe(&g_ring.ring); if (!sqe) { LOGPIO(iofd, LOGL_ERROR, "Could not get io_uring_sqe\n"); OSMO_ASSERT(0); } - // Prep msgb/iov io_uring_prep_writev(sqe, iofd->fd, msghdr->iov, 1, 0); io_uring_sqe_set_data(sqe, msghdr); @@ -390,6 +424,10 @@ if (iofd->u.uring.read_msghdr) return; + /* This function is called again, once the socket is connected. */ + if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED)) + return; + switch (iofd->mode) { case OSMO_IO_FD_MODE_READ_WRITE: iofd_uring_submit_recv(iofd, IOFD_ACT_READ); @@ -397,6 +435,9 @@ case OSMO_IO_FD_MODE_RECVFROM_SENDTO: iofd_uring_submit_recv(iofd, IOFD_ACT_RECVFROM); break; + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + iofd_uring_submit_recv(iofd, IOFD_ACT_RECVMSG); + break; default: OSMO_ASSERT(0); } @@ -415,6 +456,68 @@ return close(iofd->fd); } +/* called via osmocom poll/select main handling once outbound non-blocking connect() completes */ +static int iofd_uring_connected_cb(struct osmo_fd *ofd, unsigned int what) +{ + struct osmo_io_fd *iofd = ofd->data; + + LOGPIO(iofd, LOGL_DEBUG, "Socket connected or failed.\n"); + + if (!(what & OSMO_FD_WRITE)) + return 0; + + /* Unregister from poll/select handling. */ + osmo_fd_unregister(ofd); + IOFD_FLAG_UNSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED); + + /* Notify the application about this via a zero-length write completion call-back. */ + IOFD_FLAG_SET(iofd, IOFD_FLAG_IN_CALLBACK); + switch (iofd->mode) { + case OSMO_IO_FD_MODE_READ_WRITE: + iofd->io_ops.write_cb(iofd, 0, NULL); + break; + case OSMO_IO_FD_MODE_RECVFROM_SENDTO: + iofd->io_ops.sendto_cb(iofd, 0, NULL, NULL); + break; + case OSMO_IO_FD_MODE_RECVMSG_SENDMSG: + iofd->io_ops.sendmsg_cb(iofd, 0, NULL); + break; + } + IOFD_FLAG_UNSET(iofd, IOFD_FLAG_IN_CALLBACK); + + /* If write/read notifications are pending, enable it now. */ + if (iofd->u.uring.write_enabled && !IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED)) + iofd_uring_write_enable(iofd); + if (iofd->u.uring.read_enabled && !IOFD_FLAG_ISSET(iofd, IOFD_FLAG_CLOSED)) + iofd_uring_read_enable(iofd); + + if (IOFD_FLAG_ISSET(iofd, IOFD_FLAG_TO_FREE) && !iofd->u.uring.read_msghdr && !iofd->u.uring.write_msghdr) + talloc_free(iofd); + return 0; +} + +static void iofd_uring_notify_connected(struct osmo_io_fd *iofd) +{ + if (iofd->mode == OSMO_IO_FD_MODE_RECVMSG_SENDMSG) { + /* Don't call this function after enabling read or write. */ + OSMO_ASSERT(!iofd->u.uring.write_enabled && !iofd->u.uring.read_enabled); + + /* Use a temporary osmo_fd which we can use to notify us once the connection is established + * or failed (indicated by FD becoming writable). + * This is needed as (at least for SCTP sockets) one cannot submit a zero-length writev/sendmsg + * in order to get notification when the socekt is writable.*/ + if (!IOFD_FLAG_ISSET(iofd, IOFD_FLAG_NOTIFY_CONNECTED)) { + osmo_fd_setup(&iofd->u.uring.connect_ofd, iofd->fd, OSMO_FD_WRITE, + iofd_uring_connected_cb, iofd, 0); + if (osmo_fd_register(&iofd->u.uring.connect_ofd) < 0) + LOGPIO(iofd, LOGL_ERROR, "Failed to register FD for connect event.\n"); + else + IOFD_FLAG_SET(iofd, IOFD_FLAG_NOTIFY_CONNECTED); + } + } else + iofd_uring_write_enable(iofd); +} + const struct iofd_backend_ops iofd_uring_ops = { .register_fd = iofd_uring_register, .unregister_fd = iofd_uring_unregister, @@ -423,6 +526,7 @@ .write_disable = iofd_uring_write_disable, .read_enable = iofd_uring_read_enable, .read_disable = iofd_uring_read_disable, + .notify_connected = iofd_uring_notify_connected, }; #endif /* defined(__linux__) */
View file
libosmocore_1.9.3.tar.xz/src/core/sockaddr_str.c -> libosmocore_1.10.0.tar.xz/src/core/sockaddr_str.c
Changed
@@ -33,6 +33,7 @@ #include <osmocom/core/sockaddr_str.h> #include <osmocom/core/utils.h> #include <osmocom/core/byteswap.h> +#include <osmocom/core/socket.h> /*! \addtogroup sockaddr_str * @@ -359,6 +360,17 @@ return -EINVAL; } +/*! Convert IPv4 or IPv6 address and port to osmo_sockaddr_str. + * \paramout sockaddr_str The instance to copy to. + * \paramin src IPv4 or IPv6 address and port data. + * \return 0 on success, negative if src does not indicate AF_INET nor AF_INET6 (or if the conversion fails, which + * should not be possible in practice). + */ +int osmo_sockaddr_str_from_osa(struct osmo_sockaddr_str *sockaddr_str, const struct osmo_sockaddr *src) +{ + return osmo_sockaddr_str_from_sockaddr(sockaddr_str, &src->u.sas); +} + /*! Convert osmo_sockaddr_str address string to IPv4 address data. * \paramin sockaddr_str The instance to convert the IP of. * \paramout dst IPv4 address data to write to. @@ -509,5 +521,15 @@ } } +/*! Convert osmo_sockaddr_str address string and port to IPv4 or IPv6 address and port data. + * \paramin sockaddr_str The instance to convert the IP and port of. + * \paramout dst IPv4/IPv6 address and port data to write to. + * \return 0 on success, negative on error (e.g. invalid IP address string for the family indicated by sockaddr_str->af). + */ +int osmo_sockaddr_str_to_osa(const struct osmo_sockaddr_str *sockaddr_str, struct osmo_sockaddr *dst) +{ + return osmo_sockaddr_str_to_sockaddr(sockaddr_str, &dst->u.sas); +} + /*! @} */ #endif // HAVE_NETINET_IN_H
View file
libosmocore_1.9.3.tar.xz/src/core/socket.c -> libosmocore_1.10.0.tar.xz/src/core/socket.c
Changed
@@ -26,6 +26,7 @@ * \file socket.c */ #ifdef HAVE_SYS_SOCKET_H +#define _GNU_SOURCE /* for struct ucred on glibc >= 2.8 */ #include <osmocom/core/logging.h> #include <osmocom/core/select.h> @@ -616,18 +617,45 @@ #ifdef HAVE_LIBSCTP -/* Check whether there's an IPv6 Addr as first option of any addrinfo item in the addrinfo set */ +/* Check whether there's an addrinfo item in the addrinfo set with an IPv4 or IPv6 option */ static void addrinfo_has_v4v6addr(const struct addrinfo **result, size_t result_count, bool *has_v4, bool *has_v6) { size_t host_idx; + const struct addrinfo *rp; *has_v4 = false; *has_v6 = false; for (host_idx = 0; host_idx < result_count; host_idx++) { - if (resulthost_idx->ai_family == AF_INET) - *has_v4 = true; - else if (resulthost_idx->ai_family == AF_INET6) - *has_v6 = true; + for (rp = resulthost_idx; rp != NULL; rp = rp->ai_next) { + if (resulthost_idx->ai_family == AF_INET) + *has_v4 = true; + else if (resulthost_idx->ai_family == AF_INET6) + *has_v6 = true; + } + } +} + +/* Check whether there's an addrinfo item in the addrinfo set with only an IPv4 or IPv6 option */ +static void addrinfo_has_v4v6only_addr(const struct addrinfo **result, size_t result_count, bool *has_v4only, bool *has_v6only) +{ + size_t host_idx; + const struct addrinfo *rp; + *has_v4only = false; + *has_v6only = false; + + for (host_idx = 0; host_idx < result_count; host_idx++) { + bool has_v4 = false; + bool has_v6 = false; + for (rp = resulthost_idx; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family == AF_INET6) + has_v6 = true; + else + has_v4 = true; + } + if (has_v4 && !has_v6) + *has_v4only = true; + else if (has_v6 && !has_v4) + *has_v6only = true; } } @@ -636,13 +664,16 @@ { size_t host_idx; struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; + const struct addrinfo *rp; for (host_idx = 0; host_idx < result_count; host_idx++) { - if (resulthost_idx->ai_family != AF_INET6) - continue; - if (memcmp(&((struct sockaddr_in6 *)resulthost_idx->ai_addr)->sin6_addr, - &in6addr_any, sizeof(in6addr_any)) == 0) - return true; + for (rp = resulthost_idx; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family != AF_INET6) + continue; + if (memcmp(&((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr, + &in6addr_any, sizeof(in6addr_any)) == 0) + return true; + } } return false; } @@ -676,22 +707,28 @@ for (host_idx = 0; host_idx < host_cont; host_idx++) { /* Addresses are ordered based on RFC 3484, see man getaddrinfo */ for (rp = resulthost_idx; rp != NULL; rp = rp->ai_next) { - if (family != AF_UNSPEC && rp->ai_family != family) - continue; - if (offset + rp->ai_addrlen > addrs_buf_len) { - LOGP(DLGLOBAL, LOGL_ERROR, "Output buffer to small: %zu\n", - addrs_buf_len); - return -ENOSPC; + if (family == AF_UNSPEC || rp->ai_family == family) + break; + } + if (!rp && family == AF_INET6) { + /* See if we can find an AF_INET addr for the AF_INET6 socket instead: */ + for (rp = resulthost_idx; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family == AF_INET) + break; } - memcpy(addrs_buf + offset, rp->ai_addr, rp->ai_addrlen); - offset += rp->ai_addrlen; - break; } if (!rp) { /* No addr could be bound for this host! */ LOGP(DLGLOBAL, LOGL_ERROR, "No suitable remote address found for host: %s\n", hostshost_idx); return -ENODEV; } + if (offset + rp->ai_addrlen > addrs_buf_len) { + LOGP(DLGLOBAL, LOGL_ERROR, "Output buffer to small: %zu\n", + addrs_buf_len); + return -ENOSPC; + } + memcpy(addrs_buf + offset, rp->ai_addr, rp->ai_addrlen); + offset += rp->ai_addrlen; } return 0; } @@ -827,15 +864,13 @@ struct addrinfo *res_locOSMO_SOCK_MAX_ADDRS, *res_remOSMO_SOCK_MAX_ADDRS; int sfd = -1, rc, on = 1; unsigned int i; - bool loc_has_v4addr, rem_has_v4addr; - bool loc_has_v6addr, rem_has_v6addr; + bool loc_has_v4addr = false, loc_has_v6addr = false; + bool rem_has_v4addr = false, rem_has_v6addr = false; + bool loc_has_v4only_addr, rem_has_v4only_addr; + bool loc_has_v6only_addr, rem_has_v6only_addr; struct sockaddr_in6 addrs_bufOSMO_SOCK_MAX_ADDRS; char strbuf512; - /* updated later in case of AF_UNSPEC */ - loc_has_v4addr = rem_has_v4addr = (family == AF_INET); - loc_has_v6addr = rem_has_v6addr = (family == AF_INET6); - /* TODO: So far this function is only aimed for SCTP, but could be reused in the future for other protocols with multi-addr support */ if (proto != IPPROTO_SCTP) @@ -862,10 +897,17 @@ local_hosts_cnt, local_port, true); if (rc < 0) return -EINVAL; - /* Figure out if there's any IPV4 or IPv6 addr in the set */ - if (family == AF_UNSPEC) - addrinfo_has_v4v6addr((const struct addrinfo **)res_loc, local_hosts_cnt, - &loc_has_v4addr, &loc_has_v6addr); + /* Figure out if there's any IPv4 or IPv6 entry in the result set */ + addrinfo_has_v4v6addr((const struct addrinfo **)res_loc, local_hosts_cnt, + &loc_has_v4addr, &loc_has_v6addr); + /* Figure out if there's any IPv4-only or IPv6-only addr in the result set */ + addrinfo_has_v4v6only_addr((const struct addrinfo **)res_loc, local_hosts_cnt, + &loc_has_v4only_addr, &loc_has_v6only_addr); + if (family == AF_INET && loc_has_v6only_addr) { + LOGP(DLGLOBAL, LOGL_ERROR, "Cannot bind an IPv6 address to an AF_INET socket\n"); + rc = -EINVAL; + goto ret_freeaddrinfo_loc; + } } /* figure out remote side of socket */ if (flags & OSMO_SOCK_F_CONNECT) { @@ -875,48 +917,51 @@ rc = -EINVAL; goto ret_freeaddrinfo_loc; } - /* Figure out if there's any IPv4 or IPv6 addr in the set */ - if (family == AF_UNSPEC) - addrinfo_has_v4v6addr((const struct addrinfo **)res_rem, remote_hosts_cnt, - &rem_has_v4addr, &rem_has_v6addr); + /* Figure out if there's any IPv4 or IPv6 entry in the result set */ + addrinfo_has_v4v6addr((const struct addrinfo **)res_rem, remote_hosts_cnt, + &rem_has_v4addr, &rem_has_v6addr); + /* Figure out if there's any IPv4-only or IPv6-only addr in the result set */ + addrinfo_has_v4v6only_addr((const struct addrinfo **)res_rem, remote_hosts_cnt, + &rem_has_v4only_addr, &rem_has_v6only_addr); + if (family == AF_INET && rem_has_v6only_addr) { + LOGP(DLGLOBAL, LOGL_ERROR, "Cannot connect to an IPv6 address in an AF_INET socket\n"); + rc = -EINVAL; + goto ret_freeaddrinfo; + } + } + + /* Find out the socket family now if not established by caller: + * Both are checked here through "or" here to account for "bind flag set, + * connect flag not set" and viceversa. */ + if (family == AF_UNSPEC) { + if (!loc_has_v6addr && !rem_has_v6addr) + family = AF_INET; + else + family = AF_INET6; } - if (((flags & OSMO_SOCK_F_BIND) && (flags & OSMO_SOCK_F_CONNECT)) && - !addrinfo_has_in6addr_any((const struct addrinfo **)res_loc, local_hosts_cnt) && + /* if both sets are used, make sure there's at least 1 address of the + * same type on each set so that SCTP INIT/INIT-ACK can work. */ + if (family == AF_INET6 && ((flags & OSMO_SOCK_F_BIND) && (flags & OSMO_SOCK_F_CONNECT)) && (loc_has_v4addr != rem_has_v4addr || loc_has_v6addr != rem_has_v6addr)) { - LOGP(DLGLOBAL, LOGL_ERROR, "Invalid v4 vs v6 in local vs remote addresses: " - "local:%s%s remote:%s%s\n", - loc_has_v4addr ? " v4" : "", loc_has_v6addr ? " v6" : "", - rem_has_v4addr ? " v4" : "", rem_has_v6addr ? " v6" : "" - ); - rc = -EINVAL; - goto ret_freeaddrinfo; + if (!addrinfo_has_in6addr_any((const struct addrinfo **)res_loc, local_hosts_cnt)) { + LOGP(DLGLOBAL, LOGL_ERROR, "Invalid v4 vs v6 in local vs remote addresses: " + "local:%s%s remote:%s%s\n", + loc_has_v4addr ? " v4" : "", loc_has_v6addr ? " v6" : "", + rem_has_v4addr ? " v4" : "", rem_has_v6addr ? " v6" : ""); + rc = -EINVAL; + goto ret_freeaddrinfo; + } } - sfd = socket_helper_multiaddr(loc_has_v6addr ? AF_INET6 : AF_INET, - type, proto, flags); + sfd = socket_helper_multiaddr(family, type, proto, flags); if (sfd < 0) { rc = sfd; goto ret_freeaddrinfo; } - if (flags & OSMO_SOCK_F_BIND) { - /* Since so far we only allow IPPROTO_SCTP in this function, - no need to check below for "proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR" */ - rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)); - if (rc < 0) { - int err = errno; - multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt); - LOGP(DLGLOBAL, LOGL_ERROR, - "cannot setsockopt socket:" - " %s:%u: %s\n", - strbuf, local_port, - strerror(err)); - goto ret_close; - } - - if (pars && pars->sctp.sockopt_auth_supported.set) { + if (pars) { + if (pars->sctp.sockopt_auth_supported.set) { /* RFC 5061 4.2.7: ASCONF also requires AUTH feature. */ rc = setsockopt_sctp_auth_supported(sfd, pars->sctp.sockopt_auth_supported.value); if (rc < 0) { @@ -932,7 +977,7 @@ } } - if (pars && pars->sctp.sockopt_asconf_supported.set) { + if (pars->sctp.sockopt_asconf_supported.set) { rc = setsockopt_sctp_asconf_supported(sfd, pars->sctp.sockopt_asconf_supported.value); if (rc < 0) { int err = errno; @@ -947,7 +992,7 @@ } } - if (pars && pars->sctp.sockopt_initmsg.set) { + if (pars->sctp.sockopt_initmsg.set) { rc = setsockopt_sctp_initmsg(sfd, pars); if (rc < 0) { int err = errno; @@ -960,6 +1005,23 @@ /* do not fail, some parameters will be left as the global default */ } } + } + + if (flags & OSMO_SOCK_F_BIND) { + /* Since so far we only allow IPPROTO_SCTP in this function, + no need to check below for "proto != IPPROTO_UDP || flags & OSMO_SOCK_F_UDP_REUSEADDR" */ + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); + if (rc < 0) { + int err = errno; + multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt); + LOGP(DLGLOBAL, LOGL_ERROR, + "cannot setsockopt socket:" + " %s:%u: %s\n", + strbuf, local_port, + strerror(err)); + goto ret_close; + } /* Build array of addresses taking first entry for each host. TODO: Ideally we should use backtracking storing last used @@ -1257,6 +1319,160 @@ return osmo_sock_init(ss->sa_family, type, proto, host, port, flags); } +#ifdef HAVE_LIBSCTP +/*! Add addresses to the multi-address (SCTP) socket active binding set + * \paramin sfd The multi-address (SCTP) socket + * \paramin addrs array of char pointers (strings), each containing local host name or IP address in string form + * \paramin addrs_cnt length of addrs_hosts (in items) + * \returns 0 on success; negative on error + * + * This function only supports SCTP sockets so far, and hence it should be + * called only on socket file descriptions referencing that kind of sockets. + */ +int osmo_sock_multiaddr_add_local_addr(int sfd, const char **addrs, size_t addrs_cnt) +{ + struct osmo_sockaddr osa; + socklen_t slen = sizeof(osa); + uint16_t sfd_family; + uint16_t type = SOCK_STREAM ;/* Fixme: we assume fd is SOCK_STREAM */ + uint8_t proto = IPPROTO_SCTP; /* Fixme: we assume fd is IPPROTO_SCTP */ + struct addrinfo *resOSMO_SOCK_MAX_ADDRS; + uint16_t port; + struct sockaddr_in6 addrs_bufOSMO_SOCK_MAX_ADDRS; + unsigned int i; + int rc; + bool res_has_v4addr = false, res_has_v6addr = false; + + rc = getsockname(sfd, &osa.u.sa, &slen); + if (rc < 0) + return rc; /* TODO: log error? */ + sfd_family = osa.u.sa.sa_family; + port = osmo_sockaddr_port(&osa.u.sa); + + if (sfd_family != AF_INET && sfd_family != AF_INET6) + return -EINVAL; + + rc = addrinfo_helper_multi(res, AF_UNSPEC, type, proto, addrs, + addrs_cnt, port, true); + if (rc < 0) + return -EINVAL; + + addrinfo_has_v4v6addr((const struct addrinfo **)res, addrs_cnt, + &res_has_v4addr, &res_has_v6addr); + if (sfd_family == AF_INET && !res_has_v4addr) { + rc = -EINVAL; + goto ret_free; + } + + uint16_t new_addr_family; + if (sfd_family == AF_INET) + new_addr_family = AF_INET; + else if (sfd_family == AF_INET6 && !res_has_v4addr) + new_addr_family = AF_INET6; + else + new_addr_family = AF_UNSPEC; + rc = addrinfo_to_sockaddr(new_addr_family, (const struct addrinfo **)res, + addrs, addrs_cnt, + (uint8_t *)addrs_buf, sizeof(addrs_buf)); + if (rc < 0) { + rc = -ENODEV; + goto ret_free; + } + + rc = sctp_bindx(sfd, (struct sockaddr *)addrs_buf, addrs_cnt, SCTP_BINDX_ADD_ADDR); + if (rc == -1) { + int err = errno; + char strbuf512; + multiaddr_snprintf(strbuf, sizeof(strbuf), addrs, addrs_cnt); + LOGP(DLGLOBAL, LOGL_NOTICE, "Unable to bind socket to new addresses: %s:%u: %s\n", + strbuf, port, strerror(err)); + rc = -ENODEV; + goto ret_free; + } + +ret_free: + for (i = 0; i < addrs_cnt; i++) + freeaddrinfo(resi); + return rc; +} + +/*! Remove addresses from the multi-address (SCTP) socket active binding set + * \paramin sfd The multi-address (SCTP) socket + * \paramin addrs array of char pointers (strings), each containing local host name or IP address in string form + * \paramin addrs_cnt length of addrs_hosts (in items) + * \returns 0 on success; negative on error + * + * This function only supports SCTP sockets so far, and hence it should be + * called only on socket file descriptions referencing that kind of sockets. + */ +int osmo_sock_multiaddr_del_local_addr(int sfd, const char **addrs, size_t addrs_cnt) +{ + struct osmo_sockaddr osa; + socklen_t slen = sizeof(osa); + uint16_t sfd_family; + uint16_t type = SOCK_STREAM ;/* Fixme: we assume fd is SOCK_STREAM */ + uint8_t proto = IPPROTO_SCTP; /* Fixme: we assume fd is IPPROTO_SCTP */ + struct addrinfo *resOSMO_SOCK_MAX_ADDRS; + uint16_t port; + struct sockaddr_in6 addrs_bufOSMO_SOCK_MAX_ADDRS; + unsigned int i; + int rc; + bool res_has_v4addr = false, res_has_v6addr = false; + + rc = getsockname(sfd, &osa.u.sa, &slen); + if (rc < 0) + return rc; /* TODO: log error? */ + sfd_family = osa.u.sa.sa_family; + port = osmo_sockaddr_port(&osa.u.sa); + + if (sfd_family != AF_INET && sfd_family != AF_INET6) + return -EINVAL; + + rc = addrinfo_helper_multi(res, AF_UNSPEC, type, proto, addrs, + addrs_cnt, port, true); + if (rc < 0) + return -EINVAL; + + addrinfo_has_v4v6addr((const struct addrinfo **)res, addrs_cnt, + &res_has_v4addr, &res_has_v6addr); + if (sfd_family == AF_INET && !res_has_v4addr) { + rc = -EINVAL; + goto ret_free; + } + + uint16_t del_addr_family; + if (sfd_family == AF_INET) + del_addr_family = AF_INET; + else if (sfd_family == AF_INET6 && !res_has_v4addr) + del_addr_family = AF_INET6; + else + del_addr_family = AF_UNSPEC; + rc = addrinfo_to_sockaddr(del_addr_family, (const struct addrinfo **)res, + addrs, addrs_cnt, + (uint8_t *)addrs_buf, sizeof(addrs_buf)); + if (rc < 0) { + rc = -ENODEV; + goto ret_free; + } + + rc = sctp_bindx(sfd, (struct sockaddr *)addrs_buf, addrs_cnt, SCTP_BINDX_REM_ADDR); + if (rc == -1) { + int err = errno; + char strbuf512; + multiaddr_snprintf(strbuf, sizeof(strbuf), addrs, addrs_cnt); + LOGP(DLGLOBAL, LOGL_NOTICE, "Unable to unbind socket from addresses: %s:%u: %s\n", + strbuf, port, strerror(err)); + rc = -ENODEV; + goto ret_free; + } + +ret_free: + for (i = 0; i < addrs_cnt; i++) + freeaddrinfo(resi); + return rc; +} +#endif /* HAVE_LIBSCTP */ + static int sockaddr_equal(const struct sockaddr *a, const struct sockaddr *b, unsigned int len) { @@ -1508,6 +1724,27 @@ } } +/*! Convert an IP address string (and port number) into a 'struct osmo_sockaddr'. + * \paramout osa_out caller-allocated osmo_sockaddr storage + * \paramin ipstr IPv4,v6 address in string format + * \paramin port port number (host byte order) + * \returns 0 on success; negative on error. */ +int osmo_sockaddr_from_str_and_uint(struct osmo_sockaddr *osa_out, const char *ipstr, uint16_t port) +{ + struct addrinfo *ai = addrinfo_helper(AF_UNSPEC, 0, 0, ipstr, port, true); + + if (!ai) + return -EIO; + + if (ai->ai_addrlen > sizeof(*osa_out)) + return -ENOSPC; + + memcpy(&osa_out->u.sa, ai->ai_addr, ai->ai_addrlen); + freeaddrinfo(ai); + + return 0; +} + /*! Initialize a unix domain socket (including bind/connect) * \paramin type Socket type like SOCK_DGRAM, SOCK_STREAM * \paramin proto Protocol like IPPROTO_TCP, IPPROTO_UDP @@ -1632,6 +1869,97 @@ return 0; } +#ifdef HAVE_LIBSCTP +/*! Get multiple IP addresses and/or port number on socket in separate string buffers + * \paramin fd file descriptor of socket. + * \paramout ip_proto IPPROTO of the socket, eg: IPPROTO_SCTP. + * \paramout ip Pointer to memory holding consecutive buffers of size ip_len. + * \paramout ip_cnt length ip array pointer. on return it contains the number of addresses found. + * \paramin ip_len length of each of the string buffer in the the ip array. + * \paramout port number (will be filled in when not NULL). + * \paramin port_len length of the port buffer. + * \paramin local (true) or remote (false) name will get looked at. + * \returns 0 on success; negative otherwise. + * + * Upon return, ip_cnt can be set to a higher value than the one set by the + * caller. This can be used by the caller to find out the required array length + * and then obtaining by calling the function twice. Only up to ip_cnt addresses + * are filed in, as per the value provided by the caller. + * + * Usage example retrieving all (up to OSMO_SOCK_MAX_ADDRS, 32) bound IP addresses and bound port: + * char hostbufOSMO_SOCK_MAX_ADDRSINET6_ADDRSTRLEN; + * size_t num_hostbuf = ARRAY_SIZE(hostbuf); + * char portbuf6; + * rc = osmo_sock_multiaddr_get_ip_and_port(fd, IPPROTO_SCTP, &hostbuf00, &num_hostbuf, + * sizeof(hostbuf0), portbuf, sizeof(portbuf), true); + * if (rc < 0) + * goto error; + * if (num_hostbuf > ARRAY_SIZE(hostbuf)) + * goto not_enough_buffers; + */ +int osmo_sock_multiaddr_get_ip_and_port(int fd, int ip_proto, char *ip, size_t *ip_cnt, size_t ip_len, + char *port, size_t port_len, bool local) +{ + struct sockaddr *addrs = NULL; + unsigned int n_addrs, i; + void *addr_buf; + int rc; + + switch (ip_proto) { + case IPPROTO_SCTP: + break; /* continue below */ + default: + if (*ip_cnt == 0) { + *ip_cnt = 1; + return 0; + } + *ip_cnt = 1; + return osmo_sock_get_ip_and_port(fd, ip, ip_len, port, port_len, local); + } + + rc = local ? sctp_getladdrs(fd, 0, &addrs) : sctp_getpaddrs(fd, 0, &addrs); + if (rc < 0) + return rc; + if (rc == 0) + return -ENOTCONN; + + n_addrs = rc; + addr_buf = (void *)addrs; + for (i = 0; i < n_addrs; i++) { + struct sockaddr *sa_addr = (struct sockaddr *)addr_buf; + size_t addrlen; + + if (i >= *ip_cnt) + break; + + switch (sa_addr->sa_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; + default: + rc = -EINVAL; + goto free_addrs_ret; + } + + rc = getnameinfo(sa_addr, addrlen, &ipi * ip_len, ip_len, + port, port_len, + NI_NUMERICHOST | NI_NUMERICSERV); + if (rc < 0) + goto free_addrs_ret; + addr_buf += addrlen; + } + + *ip_cnt = n_addrs; + rc = 0; +free_addrs_ret: + local ? sctp_freeladdrs(addrs) : sctp_freepaddrs(addrs); + return rc; +} +#endif + /*! Get local IP address on socket * \paramin fd file descriptor of socket * \paramout ip IP address (will be filled in) @@ -1693,6 +2021,114 @@ return talloc_asprintf(ctx, "(%s)", str); } +#ifdef HAVE_LIBSCTP +/*! Format multiple IP addresses and/or port number into a combined string buffer + * \paramout str Destination string buffer. + * \paramin str_len sizeof(str), usually OSMO_SOCK_MULTIADDR_PEER_STR_MAXLEN. + * \paramout ip Pointer to memory holding ip_cnt consecutive buffers of size ip_len. + * \paramout ip_cnt length ip array pointer. on return it contains the number of addresses found. + * \paramin ip_len length of each of the string buffer in the the ip array. + * \paramout port number (will be printed in when not NULL). + * \return String length as returned by snprintf(), or negative on error. + * + * This API expects an ip array as the one filled in by + * osmo_sock_multiaddr_get_ip_and_port(), and hence it's a good companion for + * that API. + */ +int osmo_multiaddr_ip_and_port_snprintf(char *str, size_t str_len, + const char *ip, size_t ip_cnt, size_t ip_len, + const char *portbuf) +{ + struct osmo_strbuf sb = { .buf = str, .len = str_len }; + bool is_v6 = false; + unsigned int i; + + if (ip_cnt == 0) { + OSMO_STRBUF_PRINTF(sb, "NULL:%s", portbuf); + return sb.chars_needed; + } + if (ip_cnt > 1) + OSMO_STRBUF_PRINTF(sb, "("); + else if ((is_v6 = !!strchr(&ip0, ':'))) /* IPv6, add to separate from port. */ + OSMO_STRBUF_PRINTF(sb, ""); + + for (i = 0; i < ip_cnt - 1; i++) + OSMO_STRBUF_PRINTF(sb, "%s|", &ipi * ip_len); + OSMO_STRBUF_PRINTF(sb, "%s", &ipi * ip_len); + + if (ip_cnt > 1) + OSMO_STRBUF_PRINTF(sb, ")"); + else if (is_v6) + OSMO_STRBUF_PRINTF(sb, ""); + if (portbuf) + OSMO_STRBUF_PRINTF(sb, ":%s", portbuf); + + return sb.chars_needed; +} + +/*! Get address/port information on socket in provided string buffer, like "r=1.2.3.4:5<->l=6.7.8.9:10". + * This does not include braces like osmo_sock_get_name(). + * \paramout str Destination string buffer. + * \paramin str_len sizeof(str), usually OSMO_SOCK_MULTIADDR_NAME_MAXLEN. + * \paramin fd File descriptor of socket. + * \paramin fd IPPROTO of the socket, eg: IPPROTO_SCTP. + * \return String length as returned by snprintf(), or negative on error. + */ +int osmo_sock_multiaddr_get_name_buf(char *str, size_t str_len, int fd, int sk_proto) +{ + char hostbufOSMO_SOCK_MAX_ADDRSINET6_ADDRSTRLEN; + size_t num_hostbuf = ARRAY_SIZE(hostbuf); + char portbuf6; + struct osmo_strbuf sb = { .buf = str, .len = str_len }; + + if (fd < 0) { + osmo_strlcpy(str, "<error-bad-fd>", str_len); + return sb.chars_needed; + } + + switch (sk_proto) { + case IPPROTO_SCTP: + break; /* continue below */ + default: + return osmo_sock_get_name_buf(str, str_len, fd); + } + + /* get remote */ + OSMO_STRBUF_PRINTF(sb, "r="); + if (osmo_sock_multiaddr_get_ip_and_port(fd, sk_proto, &hostbuf00, &num_hostbuf, + sizeof(hostbuf0), portbuf, sizeof(portbuf), false) != 0) { + OSMO_STRBUF_PRINTF(sb, "NULL"); + } else { + const bool need_more_bufs = num_hostbuf > ARRAY_SIZE(hostbuf); + if (need_more_bufs) + num_hostbuf = ARRAY_SIZE(hostbuf); + OSMO_STRBUF_APPEND(sb, osmo_multiaddr_ip_and_port_snprintf, + &hostbuf00, num_hostbuf, sizeof(hostbuf0), portbuf); + if (need_more_bufs) + OSMO_STRBUF_PRINTF(sb, "<need-more-bufs!>"); + } + + OSMO_STRBUF_PRINTF(sb, "<->l="); + + /* get local */ + num_hostbuf = ARRAY_SIZE(hostbuf); + if (osmo_sock_multiaddr_get_ip_and_port(fd, sk_proto, &hostbuf00, &num_hostbuf, + sizeof(hostbuf0), portbuf, sizeof(portbuf), true) != 0) { + OSMO_STRBUF_PRINTF(sb, "NULL"); + } else { + const bool need_more_bufs = num_hostbuf > ARRAY_SIZE(hostbuf); + if (need_more_bufs) + num_hostbuf = ARRAY_SIZE(hostbuf); + OSMO_STRBUF_APPEND(sb, osmo_multiaddr_ip_and_port_snprintf, + &hostbuf00, num_hostbuf, sizeof(hostbuf0), portbuf); + if (need_more_bufs) + OSMO_STRBUF_PRINTF(sb, "<need-more-bufs!>"); + } + + return sb.chars_needed; +} +#endif + /*! Get address/port information on socket in provided string buffer, like "r=1.2.3.4:5<->l=6.7.8.9:10". * This does not include braces like osmo_sock_get_name(). * \paramout str Destination string buffer. @@ -1702,8 +2138,10 @@ */ int osmo_sock_get_name_buf(char *str, size_t str_len, int fd) { - char hostbuf_lINET6_ADDRSTRLEN, hostbuf_rINET6_ADDRSTRLEN; - char portbuf_l6, portbuf_r6; + struct osmo_strbuf sb = { .buf = str, .len = str_len }; + struct osmo_sockaddr osa; + struct sockaddr_un *sun; + socklen_t len; int rc; if (fd < 0) { @@ -1711,17 +2149,78 @@ return -EBADF; } - /* get local */ - if ((rc = osmo_sock_get_ip_and_port(fd, hostbuf_l, sizeof(hostbuf_l), portbuf_l, sizeof(portbuf_l), true))) { + + len = sizeof(osa.u.sas); + rc = getsockname(fd, &osa.u.sa, &len); + if (rc < 0) { osmo_strlcpy(str, "<error-in-getsockname>", str_len); return rc; } - /* get remote */ - if (osmo_sock_get_ip_and_port(fd, hostbuf_r, sizeof(hostbuf_r), portbuf_r, sizeof(portbuf_r), false) != 0) - return snprintf(str, str_len, "r=NULL<->l=%s:%s", hostbuf_l, portbuf_l); - - return snprintf(str, str_len, "r=%s:%s<->l=%s:%s", hostbuf_r, portbuf_r, hostbuf_l, portbuf_l); + switch (osa.u.sa.sa_family) { + case AF_INET: + case AF_INET6: + { + char hostbuf_lINET6_ADDRSTRLEN, hostbuf_rINET6_ADDRSTRLEN; + char portbuf_l6, portbuf_r6; + + len = sizeof(osa.u.sas); + rc = getnameinfo(&osa.u.sa, len, hostbuf_l, sizeof(hostbuf_l), + portbuf_l, sizeof(portbuf_l), + NI_NUMERICHOST | NI_NUMERICSERV); + if (rc < 0) { + osmo_strlcpy(str, "<error-in-getnameinfo>", str_len); + return rc; + } + /* Now attempt to get remote: */ + len = sizeof(osa.u.sas); + rc = getpeername(fd, &osa.u.sa, &len); + if (rc < 0) { + OSMO_STRBUF_PRINTF(sb, "r=NULL<->l=%s:%s", hostbuf_l, portbuf_l); + return sb.chars_needed; + } + len = sizeof(osa.u.sas); + rc = getnameinfo(&osa.u.sa, len, hostbuf_r, sizeof(hostbuf_r), + portbuf_r, sizeof(portbuf_r), + NI_NUMERICHOST | NI_NUMERICSERV); + if (rc < 0) { + OSMO_STRBUF_PRINTF(sb, "r=NULL<->l=%s:%s", hostbuf_l, portbuf_l); + return sb.chars_needed; + } + OSMO_STRBUF_PRINTF(sb, "r=%s:%s<->l=%s:%s", hostbuf_r, portbuf_r, hostbuf_l, portbuf_l); + return sb.chars_needed; + } + case AF_UNIX: + { + unsigned long long remote_pid; + bool have_remote_pid; +#if defined(SO_PEERCRED) + struct ucred ucred; + len = sizeof(struct ucred); + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) { + have_remote_pid = false; + } else { + have_remote_pid = true; + remote_pid = (unsigned long long)ucred.pid; + } +#else + #pragma message "SO_PEERCRED not available" + have_remote_pid = false; +#endif + /* Make sure sun_path is NULL terminated: */ + sun = (struct sockaddr_un *)&osa.u.sa; + sun->sun_pathsizeof(sun->sun_path) - 1 = '\0'; + if (have_remote_pid) + OSMO_STRBUF_PRINTF(sb, "r=%llu<->", remote_pid); + else + OSMO_STRBUF_PRINTF(sb, "r=NULL<->"); + OSMO_STRBUF_PRINTF(sb, "l=%s:%d", sun->sun_path, fd); + return sb.chars_needed; + } + default: + osmo_strlcpy(str, "<socket-family-no-supported>", str_len); + return -ENOTSUP; + } } /*! Get address/port information on socket in static string, like "r=1.2.3.4:5<->l=6.7.8.9:10". @@ -2222,6 +2721,83 @@ return setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)); } +#ifdef HAVE_LIBSCTP +/*! Fill in array of struct sctp_paddrinfo with each of the remote addresses of an SCTP socket + * \paramin fd file descriptor of SCTP socket + * \paramout pinfo Pointer to memory holding an array of struct sctp_paddrinfo (pinfo_cnt length). + * \paramin,out pinfo_cnt length of pinfo array (in elements). On return it contains the number of addresses found. + * \returns 0 on success; negative otherwise + * + * Upon return, pinfo_cnt can be set to a higher value than the one set by the + * caller. This can be used by the caller to find out the required array length + * and then obtaining by calling the function twice. Only up to pinfo_cnt addresses + * are filled in, as per the value provided by the caller. + * + * Usage example retrieving struct sctp_paddrinfo for all (up to OSMO_SOCK_MAX_ADDRS, 32) remote IP addresses: + * struct sctp_paddrinfo pinfoOSMO_SOCK_MAX_ADDRS; + * size_t pinfo_cnt = ARRAY_SIZE(pinfo); + * rc = osmo_sock_sctp_get_peer_addr_info(fd, &pinfo0, &num_hostbuf, pinfo_cnt); + * if (rc < 0) + * goto error; + * if (pinfo_cnt > ARRAY_SIZE(hostbuf)) + * goto not_enough_buffers; + */ +int osmo_sock_sctp_get_peer_addr_info(int fd, struct sctp_paddrinfo *pinfo, size_t *pinfo_cnt) +{ + struct sockaddr *addrs = NULL; + unsigned int n_addrs, i; + void *addr_buf; + int rc; + socklen_t optlen; + + rc = sctp_getpaddrs(fd, 0, &addrs); + + if (rc < 0) + return rc; + if (rc == 0) + return -ENOTCONN; + + n_addrs = rc; + addr_buf = (void *)addrs; + for (i = 0; i < n_addrs; i++) { + struct sockaddr *sa_addr = (struct sockaddr *)addr_buf; + size_t addrlen; + + switch (sa_addr->sa_family) { + case AF_INET: + addrlen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + addrlen = sizeof(struct sockaddr_in6); + break; + default: + rc = -EINVAL; + goto free_addrs_ret; + } + + if (i >= *pinfo_cnt) { + addr_buf += addrlen; + continue; + } + + memset(&pinfoi, 0, sizeof(pinfo0)); + memcpy(&pinfoi.spinfo_address, sa_addr, addrlen); + optlen = sizeof(pinfo0); + rc = getsockopt(fd, SOL_SCTP, SCTP_GET_PEER_ADDR_INFO, &pinfoi, &optlen); + if (rc < 0) + goto free_addrs_ret; + + addr_buf += addrlen; + } + + *pinfo_cnt = n_addrs; + rc = 0; +free_addrs_ret: + sctp_freepaddrs(addrs); + return rc; +} +#endif + #endif /* HAVE_SYS_SOCKET_H */ /*! @} */
View file
libosmocore_1.10.0.tar.xz/src/core/soft_uart.c
Added
@@ -0,0 +1,518 @@ +/*! \file soft_uart.c + * Software UART implementation. */ +/* + * (C) 2022 by Harald Welte <laforge@gnumonks.org> + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 2 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. + * + */ + +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/soft_uart.h> + +/*! Rx/Tx flow state of a soft-UART */ +enum suart_flow_state { + SUART_FLOW_ST_IDLE, /*!< waiting for a start bit or Tx data */ + SUART_FLOW_ST_DATA, /*!< receiving/transmitting data bits */ + SUART_FLOW_ST_PARITY, /*!< receiving/transmitting parity bits */ + SUART_FLOW_ST_STOP, /*!< receiving/transmitting stop bits */ +}; + +/*! Internal state of a soft-UART */ +struct osmo_soft_uart { + struct osmo_soft_uart_cfg cfg; + const char *name; + /* modem status (bitmask of OSMO_SUART_STATUS_F_*) */ + unsigned int status; + struct { + bool running; + uint8_t bit_count; + uint8_t shift_reg; + struct msgb *msg; + ubit_t parity_bit; /* 0 (even) / 1 (odd) */ + unsigned int flags; + struct osmo_timer_list timer; + enum suart_flow_state flow_state; + } rx; + struct { + bool running; + uint8_t bit_count; + uint8_t shift_reg; + ubit_t parity_bit; /* 0 (even) / 1 (odd) */ + enum suart_flow_state flow_state; + } tx; +}; + +/*! Default soft-UART configuration (8-N-1) */ +const struct osmo_soft_uart_cfg osmo_soft_uart_default_cfg = { + .num_data_bits = 8, + .num_stop_bits = 1, + .parity_mode = OSMO_SUART_PARITY_NONE, + .rx_buf_size = 1024, + .rx_timeout_ms = 100, + .flow_ctrl_mode = OSMO_SUART_FLOW_CTRL_NONE, +}; + +/************************************************************************* + * Receiver + *************************************************************************/ + +/*! Flush the receive buffer, passing ownership of the msgb to the .rx_cb(). + * \paramin suart soft-UART instance holding the receive buffer. */ +void osmo_soft_uart_flush_rx(struct osmo_soft_uart *suart) +{ + if (suart->rx.msg && msgb_length(suart->rx.msg)) { + osmo_timer_del(&suart->rx.timer); + if (suart->cfg.rx_cb) { + suart->cfg.rx_cb(suart->cfg.priv, suart->rx.msg, suart->rx.flags); + /* call-back has taken ownership of msgb, no need to free() here */ + suart->rx.msg = msgb_alloc_c(suart, suart->cfg.rx_buf_size, "soft_uart_rx"); + } else { + msgb_reset(suart->rx.msg); + } + } +} + +/* one character was received; add to receive buffer and notify user, if needed */ +static void suart_rx_ch(struct osmo_soft_uart *suart, uint8_t ch) +{ + unsigned int msg_len; + + OSMO_ASSERT(suart->rx.msg); + msgb_put_u8(suart->rx.msg, ch); + msg_len = msgb_length(suart->rx.msg); + + if (msg_len >= suart->cfg.rx_buf_size || suart->rx.flags) { + /* either the buffer is full, or we hit a parity and/or a framing error */ + osmo_soft_uart_flush_rx(suart); + } else if (msg_len == 1) { + /* first character in new message: start timer */ + osmo_timer_schedule(&suart->rx.timer, suart->cfg.rx_timeout_ms / 1000, + (suart->cfg.rx_timeout_ms % 1000) * 1000); + } +} + +/* receive a single bit */ +static inline void suart_rx_bit(struct osmo_soft_uart *suart, const ubit_t bit) +{ + switch (suart->rx.flow_state) { + case SUART_FLOW_ST_IDLE: + if (bit == 0) { /* start bit condition */ + suart->rx.flow_state = SUART_FLOW_ST_DATA; + suart->rx.flags = 0x00; + suart->rx.shift_reg = 0; + suart->rx.bit_count = 0; + suart->rx.parity_bit = 0; + } + break; + case SUART_FLOW_ST_DATA: + suart->rx.bit_count++; + suart->rx.shift_reg >>= 1; + if (bit != 0) { + suart->rx.parity_bit = !suart->rx.parity_bit; /* flip */ + suart->rx.shift_reg |= 0x80; + } + if (suart->rx.bit_count >= suart->cfg.num_data_bits) { + /* we have accumulated enough data bits */ + if (suart->cfg.parity_mode != OSMO_SUART_PARITY_NONE) + suart->rx.flow_state = SUART_FLOW_ST_PARITY; + else + suart->rx.flow_state = SUART_FLOW_ST_STOP; + /* align the register if needed */ + if (suart->cfg.num_data_bits < 8) + suart->rx.shift_reg >>= (8 - suart->cfg.num_data_bits); + } + break; + case SUART_FLOW_ST_PARITY: + switch (suart->cfg.parity_mode) { + case OSMO_SUART_PARITY_EVEN: + /* number of 1-bits (in both data and parity) shall be even */ + if (suart->rx.parity_bit != bit) + suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR; + break; + case OSMO_SUART_PARITY_ODD: + /* number of 1-bits (in both data and parity) shall be odd */ + if (suart->rx.parity_bit == bit) + suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR; + break; + case OSMO_SUART_PARITY_MARK: + /* parity bit must always be 1 */ + if (bit != 1) + suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR; + break; + case OSMO_SUART_PARITY_SPACE: + /* parity bit must always be 0 */ + if (bit != 0) + suart->rx.flags |= OSMO_SUART_F_PARITY_ERROR; + break; + case OSMO_SUART_PARITY_NONE: /* shall not happen */ + default: + OSMO_ASSERT(0); + } + + suart->rx.flow_state = SUART_FLOW_ST_STOP; + break; + case SUART_FLOW_ST_STOP: + suart->rx.bit_count++; + if (bit != 1) + suart->rx.flags |= OSMO_SUART_F_FRAMING_ERROR; + + if (suart->rx.bit_count >= (suart->cfg.num_data_bits + suart->cfg.num_stop_bits)) { + /* we have accumulated enough stop bits */ + suart_rx_ch(suart, suart->rx.shift_reg); + suart->rx.flow_state = SUART_FLOW_ST_IDLE; + } + break; + } +} + +/* receive timer expiration: flush rx-buffer to user call-back */ +static void suart_rx_timer_cb(void *data) +{ + struct osmo_soft_uart *suart = data; + osmo_soft_uart_flush_rx(suart); +} + +/*! Feed a number of unpacked bits into the soft-UART receiver. + * \paramin suart soft-UART instance to feed bits into. + * \paramin ubits pointer to the unpacked bits. + * \paramin n_ubits number of unpacked bits to be fed. + * \returns 0 on success; negative on error. + * -EAGAIN indicates that the receiver is disabled. */ +int osmo_soft_uart_rx_ubits(struct osmo_soft_uart *suart, const ubit_t *ubits, size_t n_ubits) +{ + if (!suart->rx.running) + return -EAGAIN; + for (size_t i = 0; i < n_ubits; i++) + suart_rx_bit(suart, ubitsi); + return 0; +} + +/************************************************************************* + * Transmitter + *************************************************************************/ + +/* pull a single bit out of the UART transmitter */ +static inline ubit_t suart_tx_bit(struct osmo_soft_uart *suart, struct msgb *msg) +{ + ubit_t tx_bit = 1; + + switch (suart->tx.flow_state) { + case SUART_FLOW_ST_IDLE: + if (msg && msgb_length(msg) > 0) { /* if we have pending data */ + suart->tx.shift_reg = msgb_pull_u8(msg); + suart->tx.flow_state = SUART_FLOW_ST_DATA; + suart->tx.bit_count = 0; + suart->tx.parity_bit = 0; + tx_bit = 0; + } + break; + case SUART_FLOW_ST_DATA: + tx_bit = suart->tx.shift_reg & 1; + suart->tx.parity_bit ^= tx_bit; + suart->tx.shift_reg >>= 1; + suart->tx.bit_count++; + if (suart->tx.bit_count >= suart->cfg.num_data_bits) { + /* we have transmitted all data bits */ + if (suart->cfg.parity_mode != OSMO_SUART_PARITY_NONE) + suart->tx.flow_state = SUART_FLOW_ST_PARITY; + else + suart->tx.flow_state = SUART_FLOW_ST_STOP; + } + break; + case SUART_FLOW_ST_PARITY: + switch (suart->cfg.parity_mode) { + case OSMO_SUART_PARITY_EVEN: + /* number of 1-bits (in both data and parity) shall be even */ + tx_bit = suart->tx.parity_bit; + break; + case OSMO_SUART_PARITY_ODD: + /* number of 1-bits (in both data and parity) shall be odd */ + tx_bit = !suart->tx.parity_bit; + break; + case OSMO_SUART_PARITY_MARK: + /* parity bit must always be 1 */ + tx_bit = 1; + break; + case OSMO_SUART_PARITY_SPACE: + /* parity bit must always be 0 */ + tx_bit = 0; + break; + case OSMO_SUART_PARITY_NONE: + default: /* shall not happen */ + OSMO_ASSERT(0); + } + + suart->tx.flow_state = SUART_FLOW_ST_STOP; + break; + case SUART_FLOW_ST_STOP: + suart->tx.bit_count++; + if (suart->tx.bit_count >= (suart->cfg.num_data_bits + suart->cfg.num_stop_bits)) { + /* we have transmitted all stop bits, we're done */ + suart->tx.flow_state = SUART_FLOW_ST_IDLE; + } + break; + } + + return tx_bit; +} + +/* pull pending bits out of the UART */ +static size_t suart_tx_pending(struct osmo_soft_uart *suart, ubit_t *ubits, size_t n_ubits) +{ + size_t i; + + for (i = 0; i < n_ubits; i++) { + if (suart->tx.flow_state == SUART_FLOW_ST_IDLE) + break; + ubitsi = suart_tx_bit(suart, NULL); + } + + return i; +} + +/*! Pull a number of unpacked bits out of the soft-UART transmitter. + * \paramin suart soft-UART instance to pull the bits from. + * \paramout ubits pointer to a buffer where to store pulled bits. + * \paramin n_ubits number of unpacked bits to be pulled. + * \returns number of bits pulled (may be less than n_ubits); negative on error. + * -EAGAIN indicates that the transmitter is disabled. */ +int osmo_soft_uart_tx_ubits(struct osmo_soft_uart *suart, ubit_t *ubits, size_t n_ubits) +{ + const struct osmo_soft_uart_cfg *cfg = &suart->cfg; + size_t n_frame_bits, n_chars; + struct msgb *msg = NULL; + + if (OSMO_UNLIKELY(n_ubits == 0)) + return -EINVAL; + + if (!suart->tx.running) + return -EAGAIN; + + switch (suart->cfg.flow_ctrl_mode) { + case OSMO_SUART_FLOW_CTRL_DTR_DSR: + /* if DSR is de-asserted, Tx pending bits and suspend */ + if (~suart->status & OSMO_SUART_STATUS_F_DSR) + return suart_tx_pending(suart, ubits, n_ubits); + /* else: keep transmitting as usual */ + break; + case OSMO_SUART_FLOW_CTRL_RTS_CTS: + /* if CTS is de-asserted, Tx pending bits and suspend */ + if (~suart->status & OSMO_SUART_STATUS_F_CTS) + return suart_tx_pending(suart, ubits, n_ubits); + /* else: keep transmitting as usual */ + break; + case OSMO_SUART_FLOW_CTRL_NONE: + default: + break; + } + + /* calculate UART frame size for the effective config */ + n_frame_bits = 1 + cfg->num_data_bits + cfg->num_stop_bits; + if (cfg->parity_mode != OSMO_SUART_PARITY_NONE) + n_frame_bits += 1; + + /* calculate the number of characters we can fit into n_ubits */ + n_chars = n_ubits / n_frame_bits; + if (n_chars == 0) { + /* we can transmit at least one character */ + if (suart->tx.flow_state == SUART_FLOW_ST_IDLE) + n_chars = 1; + } + + if (n_chars > 0) { + /* allocate a Tx buffer msgb */ + msg = msgb_alloc_c(suart, n_chars, "soft_uart_tx"); + OSMO_ASSERT(msg != NULL); + + /* call the .tx_cb() to populate the Tx buffer */ + OSMO_ASSERT(cfg->tx_cb != NULL); + suart->cfg.tx_cb(cfg->priv, msg); + } + + for (size_t i = 0; i < n_ubits; i++) + ubitsi = suart_tx_bit(suart, msg); + msgb_free(msg); + + return n_ubits; +} + +/*! Get the modem status bitmask of the given soft-UART. + * \paramin suart soft-UART instance to get the modem status. + * \returns bitmask of OSMO_SUART_STATUS_F_*. */ +unsigned int osmo_soft_uart_get_status(const struct osmo_soft_uart *suart) +{ + return suart->status; +} + +/*! Set the modem status bitmask of the given soft-UART. + * \paramin suart soft-UART instance to set the modem status. + * \paramin status bitmask of OSMO_SUART_STATUS_F_*. + * \returns 0 on success; negative on error. */ +int osmo_soft_uart_set_status(struct osmo_soft_uart *suart, unsigned int status) +{ + const struct osmo_soft_uart_cfg *cfg = &suart->cfg; + + if (cfg->status_change_cb != NULL) { + if (suart->status != status) + cfg->status_change_cb(cfg->priv, status); + } + + suart->status = status; + return 0; +} + +/*! Activate/deactivate a modem status line of the given soft-UART. + * \paramin suart soft-UART instance to update the modem status. + * \paramin line a modem status line, one of OSMO_SUART_STATUS_F_*. + * \paramin active activate (true) or deactivate (false) the line. */ +void osmo_soft_uart_set_status_line(struct osmo_soft_uart *suart, + enum osmo_soft_uart_status line, + bool active) +{ + unsigned int status = suart->status; + + if (active) /* assert the given line */ + status |= line; + else /* de-assert the given line */ + status &= ~line; + + osmo_soft_uart_set_status(suart, status); +} + + +/************************************************************************* + * Management / Initialization + *************************************************************************/ + +/*! Allocate a soft-UART instance. + * \paramin ctx parent talloc context. + * \paramin name name of the soft-UART instance. + * \paramin cfg initial configuration of the soft-UART instance. + * \returns pointer to allocated soft-UART instance; NULL on error. */ +struct osmo_soft_uart *osmo_soft_uart_alloc(void *ctx, const char *name, + const struct osmo_soft_uart_cfg *cfg) +{ + struct osmo_soft_uart *suart = talloc_zero(ctx, struct osmo_soft_uart); + if (!suart) + return NULL; + suart->name = talloc_strdup(suart, name); + + OSMO_ASSERT(cfg != NULL); + suart->cfg = *cfg; + + return suart; +} + +/*! Release memory taken by the given soft-UART. + * \paramin suart soft-UART instance to be free()d. */ +void osmo_soft_uart_free(struct osmo_soft_uart *suart) +{ + if (suart == NULL) + return; + + osmo_timer_del(&suart->rx.timer); + msgb_free(suart->rx.msg); + + talloc_free((void *)suart->name); + talloc_free(suart); +} + +/*! Change soft-UART configuration to the user-provided config. + * \paramin suart soft-UART instance to be re-configured. + * \paramin cfg the user-provided config to be applied. + * \returns 0 on success; negative on error. */ +int osmo_soft_uart_configure(struct osmo_soft_uart *suart, const struct osmo_soft_uart_cfg *cfg) +{ + /* consistency checks on the configuration */ + if (cfg->num_data_bits > 8 || cfg->num_data_bits == 0) + return -EINVAL; + if (cfg->num_stop_bits == 0) + return -EINVAL; + if (cfg->parity_mode < 0 || cfg->parity_mode >= _OSMO_SUART_PARITY_NUM) + return -EINVAL; + if (cfg->rx_buf_size == 0) + return -EINVAL; + + if (suart->cfg.rx_buf_size > cfg->rx_buf_size || + suart->cfg.rx_timeout_ms > cfg->rx_timeout_ms) { + osmo_soft_uart_flush_rx(suart); + } + + suart->cfg = *cfg; + + osmo_timer_setup(&suart->rx.timer, suart_rx_timer_cb, suart); + + return 0; +} + +/*! Get a name for the given soft-UART instance. + * \paramin suart soft-UART instance to get the name from. + * \returns name of the given soft-UART instance. */ +const char *osmo_soft_uart_get_name(const struct osmo_soft_uart *suart) +{ + return suart->name; +} + +/*! Set a new name for the given soft-UART instance. + * \paramin suart soft-UART instance to set the name for. + * \paramin name the new name. */ +void osmo_soft_uart_set_name(struct osmo_soft_uart *suart, const char *name) +{ + osmo_talloc_replace_string(suart, (char **)&suart->name, name); +} + +/*! Enable/disable receiver of the given soft-UART. + * \paramin suart soft-UART instance to be re-configured. + * \paramin enable enable/disable state of the receiver. + * \returns 0 on success; negative on error. */ +int osmo_soft_uart_set_rx(struct osmo_soft_uart *suart, bool enable) +{ + if (!enable && suart->rx.running) { + osmo_soft_uart_flush_rx(suart); + suart->rx.running = false; + suart->rx.flow_state = SUART_FLOW_ST_IDLE; + } else if (enable && !suart->rx.running) { + if (!suart->rx.msg) + suart->rx.msg = msgb_alloc_c(suart, suart->cfg.rx_buf_size, "soft_uart_rx"); + suart->rx.running = true; + suart->rx.flow_state = SUART_FLOW_ST_IDLE; + } + + return 0; +} + +/*! Enable/disable transmitter of the given soft-UART. + * \paramin suart soft-UART instance to be re-configured. + * \paramin enable enable/disable state of the transmitter. + * \returns 0 on success; negative on error. */ +int osmo_soft_uart_set_tx(struct osmo_soft_uart *suart, bool enable) +{ + if (!enable && suart->tx.running) { + suart->tx.running = false; + suart->tx.flow_state = SUART_FLOW_ST_IDLE; + } else if (enable && !suart->tx.running) { + suart->tx.running = true; + suart->tx.flow_state = SUART_FLOW_ST_IDLE; + } + + return 0; +}
View file
libosmocore_1.9.3.tar.xz/src/core/tdef.c -> libosmocore_1.10.0.tar.xz/src/core/tdef.c
Changed
@@ -337,26 +337,37 @@ const char *file, int line) { const struct osmo_tdef_state_timeout *t = osmo_tdef_get_state_timeout(state, timeouts_array); - unsigned long val = 0; + unsigned long val_ms = 0; /* No timeout defined for this state? */ if (!t) return _osmo_fsm_inst_state_chg(fi, state, 0, 0, file, line); - if (t->T) - val = osmo_tdef_get(tdefs, t->T, OSMO_TDEF_S, default_timeout); + if (t->T) { + const struct osmo_tdef *tdef = osmo_tdef_get_entry((struct osmo_tdef *)tdefs, t->T); + if (tdef == NULL) { + /* emulate the old behavior: treat default_timeout as OSMO_TDEF_S */ + OSMO_ASSERT(default_timeout >= 0); + val_ms = default_timeout * 1000; + } else { + val_ms = osmo_tdef_round(tdef->val, tdef->unit, OSMO_TDEF_MS); + /* emulate the old behavior: treat OSMO_TDEF_CUSTOM as OSMO_TDEF_S */ + if (tdef->unit == OSMO_TDEF_CUSTOM) + val_ms *= 1000; + } + } if (t->keep_timer) { if (t->T) - return _osmo_fsm_inst_state_chg_keep_or_start_timer(fi, state, val, t->T, file, line); + return _osmo_fsm_inst_state_chg_keep_or_start_timer_ms(fi, state, val_ms, t->T, file, line); else return _osmo_fsm_inst_state_chg_keep_timer(fi, state, file, line); } - /* val is always initialized here, because if t->keep_timer is false, t->T must be != 0. + /* val_ms is always initialized here, because if t->keep_timer is false, t->T must be != 0. * Otherwise osmo_tdef_get_state_timeout() would have returned NULL. */ OSMO_ASSERT(t->T); - return _osmo_fsm_inst_state_chg(fi, state, val, t->T, file, line); + return _osmo_fsm_inst_state_chg_ms(fi, state, val_ms, t->T, file, line); } const struct value_string osmo_tdef_unit_names = {
View file
libosmocore_1.9.3.tar.xz/src/core/timer.c -> libosmocore_1.10.0.tar.xz/src/core/timer.c
Changed
@@ -191,7 +191,16 @@ return -1; nearest_ms = nearest_p->tv_sec * 1000; +#ifndef EMBEDDED + /* By adding 999 milliseconds, we ensure rounding up to the nearest + * whole millisecond. This approach prevents the return of 0 when the + * timer is still active, and it guarantees that the calling process + * does not wait for a duration shorter than the time remaining on the + * timer. */ + nearest_ms += (nearest_p->tv_usec + 999) / 1000; +#else nearest_ms += nearest_p->tv_usec / 1000; +#endif return nearest_ms; }
View file
libosmocore_1.9.3.tar.xz/src/core/utils.c -> libosmocore_1.10.0.tar.xz/src/core/utils.c
Changed
@@ -147,13 +147,15 @@ */ int osmo_bcd2str(char *dst, size_t dst_size, const uint8_t *bcd, int start_nibble, int end_nibble, bool allow_hex) { - char *dst_end = dst + dst_size - 1; + char *dst_end; int nibble_i; int rc = 0; if (!dst || dst_size < 1 || start_nibble < 0) return -ENOMEM; + dst_end = dst + dst_size - 1; + for (nibble_i = start_nibble; nibble_i < end_nibble && dst < dst_end; nibble_i++, dst++) { uint8_t nibble = bcdnibble_i >> 1; if ((nibble_i & 1)) @@ -1211,6 +1213,51 @@ return (sum * 9) % 10 + '0'; } +/*! Remove up to N chars from the end of an osmo_strbuf. + * |--char-count---| - - chars_needed - - | + * |<---------drop----------| + */ +void osmo_strbuf_drop_tail(struct osmo_strbuf *sb, size_t n_chars) +{ + size_t drop_n; + if (sb->pos <= sb->buf) + return; + drop_n = OSMO_MIN(sb->chars_needed, n_chars); + sb->chars_needed -= drop_n; + /* chars_needed was reduced by n_chars, which may have been entirely behind the end of a full buffer, within the + * hypothetical chars_needed. Modify the buffer tail pos only if the buffer is not or longer full now. */ + if (sb->chars_needed >= OSMO_STRBUF_CHAR_COUNT(*sb)) + return; + sb->pos = sb->buf + sb->chars_needed; + *sb->pos = '\0'; +} + +/*! Let osmo_strbuf know that n_chars characters (excluding nul) were written to the end of the buffer. + * If sb is nonempty, the n_chars are assumed to have been written to sb->pos. If sb is still empty and pos == NULL, the + * n_chars are assumed to have been written to the start of the buffer. + * Advance sb->pos and sb->chars_needed by at most n_chars, or up to sb->len - 1. + * Ensure nul termination. */ +void osmo_strbuf_added_tail(struct osmo_strbuf *sb, size_t n_chars) +{ + /* On init of an osmo_strbuf, sb->pos == NULL, which is defined as semantically identical to pointing at the + * start of the buffer. A caller may just write to the buffer and call osmo_strbuf_added_tail(), in which case + * still pos == NULL. pos != NULL happens as soon as the first OSMO_STRBUF_*() API has acted on the strbuf. */ + if (!sb->pos) + sb->pos = sb->buf; + sb->chars_needed += n_chars; + /* first get remaining space, not counting trailing nul; but safeguard against empty buffer */ + size_t n_added = OSMO_STRBUF_REMAIN(*sb); + if (n_added) + n_added--; + /* do not add more than fit in sb->len, still ensuring nul termination */ + n_added = OSMO_MIN(n_added, n_chars); + if (n_added) + sb->pos += n_added; + /* when a strbuf is full, sb->pos may point after the final nul, so nul terminate only when pos is valid. */ + if (sb->pos < sb->buf + sb->len) + *sb->pos = '\0'; +} + /*! Compare start of a string. * This is an optimisation of 'strstr(str, startswith_str) == str' because it doesn't search through the entire string. * \param str (Longer) string to compare.
View file
libosmocore_1.9.3.tar.xz/src/core/write_queue.c -> libosmocore_1.10.0.tar.xz/src/core/write_queue.c
Changed
@@ -147,4 +147,24 @@ queue->bfd.when &= ~OSMO_FD_WRITE; } +/*! Update write queue length & drop excess messages. + * \paramin queue linked list header of message queue + * \paramin len new max. wqueue length + * \returns Number of messages dropped. + * + * Messages beyond the new maximum message queue size will be dropped. + */ +size_t osmo_wqueue_set_maxlen(struct osmo_wqueue *queue, unsigned int len) +{ + size_t dropped_msgs = 0; + struct msgb *msg; + queue->max_length = len; + while (queue->current_length > queue->max_length) { + msg = msgb_dequeue_count(&queue->msg_queue, &queue->current_length); + msgb_free(msg); + dropped_msgs++; + } + return dropped_msgs; +} + /*! @} */
View file
libosmocore_1.9.3.tar.xz/src/ctrl/Makefile.am -> libosmocore_1.10.0.tar.xz/src/ctrl/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=8:1:8 +LIBVERSION=9:0:9 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
View file
libosmocore_1.9.3.tar.xz/src/ctrl/control_cmd.c -> libosmocore_1.10.0.tar.xz/src/ctrl/control_cmd.c
Changed
@@ -31,6 +31,7 @@ #include <unistd.h> #include <osmocom/ctrl/control_cmd.h> +#include <osmocom/ctrl/control_if.h> #include <osmocom/core/msgb.h> #include <osmocom/core/talloc.h> @@ -647,7 +648,7 @@ cmd->type = CTRL_TYPE_ERROR; } - rc = ctrl_cmd_send(&cmd->ccon->write_queue, cmd); + rc = ctrl_cmd_send2(cmd->ccon, cmd); talloc_free(cmd); llist_del(&cd->list);
View file
libosmocore_1.9.3.tar.xz/src/ctrl/control_if.c -> libosmocore_1.10.0.tar.xz/src/ctrl/control_if.c
Changed
@@ -106,18 +106,28 @@ llist_for_each_entry(ccon, &ctrl->ccon_list, list_entry) { if (ccon == cmd->ccon) continue; - if (ctrl_cmd_send(&ccon->write_queue, cmd)) + if (ctrl_cmd_send2(ccon, cmd)) ret++; } return ret; } -/*! Encode a CTRL command and append it to the given write queue +/*! Encode a CTRL command and append it to the given ctrl_connection * \paraminout queue write queue to which encoded \a cmd shall be appended * \paramin cmd decoded command representation * \returns 0 in case of success; negative on error */ int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd) { + struct ctrl_connection *ccon = container_of(queue, struct ctrl_connection, write_queue); + return ctrl_cmd_send2(ccon, cmd); +} + +/*! Encode a CTRL command and append it to the given ctrl_connection + * \paraminout queue write queue to which encoded \a cmd shall be appended + * \paramin cmd decoded command representation + * \returns 0 in case of success; negative on error */ +int ctrl_cmd_send2(struct ctrl_connection *ccon, struct ctrl_cmd *cmd) +{ int ret; struct msgb *msg; @@ -130,7 +140,7 @@ ipa_prepend_header_ext(msg, IPAC_PROTO_EXT_CTRL); ipa_prepend_header(msg, IPAC_PROTO_OSMO); - ret = osmo_wqueue_enqueue(queue, msg); + ret = osmo_wqueue_enqueue(&ccon->write_queue, msg); if (ret != 0) { LOGP(DLCTRL, LOGL_ERROR, "Failed to enqueue the command.\n"); msgb_free(msg); @@ -464,7 +474,7 @@ send_reply: /* There is a reply or error that should be reported back to the sender. */ - ctrl_cmd_send(&ccon->write_queue, cmd); + ctrl_cmd_send2(ccon, cmd); just_free: talloc_free(cmd); return 0;
View file
libosmocore_1.9.3.tar.xz/src/ctrl/libosmoctrl.map -> libosmocore_1.10.0.tar.xz/src/ctrl/libosmoctrl.map
Changed
@@ -15,6 +15,7 @@ ctrl_cmd_parse2; ctrl_cmd_parse3; ctrl_cmd_send; +ctrl_cmd_send2; ctrl_cmd_send_to_all; ctrl_cmd_send_trap; ctrl_cmd_trap;
View file
libosmocore_1.9.3.tar.xz/src/gb/Makefile.am -> libosmocore_1.10.0.tar.xz/src/gb/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=16:0:2 +LIBVERSION=16:1:2 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) AM_CFLAGS = -Wall -fno-strict-aliasing \
View file
libosmocore_1.9.3.tar.xz/src/gb/gprs_ns2_internal.h -> libosmocore_1.10.0.tar.xz/src/gb/gprs_ns2_internal.h
Changed
@@ -62,7 +62,22 @@ struct gprs_ns2_vc_bind; #define NS_TIMERS_COUNT 11 -#define NS_TIMERS "(tns-block|tns-block-retries|tns-reset|tns-reset-retries|tns-test|tns-alive|tns-alive-retries|tsns-prov|tsns-size-retries|tsns-config-retries|tsns-procedures-retries)" + +#define TNS_BLOCK_STR "tns-block" +#define TNS_BLOCK_RETRIES_STR "tns-block-retries" +#define TNS_RESET_STR "tns-reset" +#define TNS_RESET_RETRIES_STR "tns-reset-retries" +#define TNS_TEST_STR "tns-test" +#define TNS_ALIVE_STR "tns-alive" +#define TNS_ALIVE_RETRIES_STR "tns-alive-retries" +#define TSNS_PROV_STR "tsns-prov" +#define TSNS_SIZE_RETRIES_STR "tsns-size-retries" +#define TSNS_CONFIG_RETRIES_STR "tsns-config-retries" +#define TSNS_PROCEDURES_RETRIES_STR "tsns-procedures-retries" +#define NS_TIMERS "(" TNS_BLOCK_STR "|" TNS_BLOCK_RETRIES_STR "|" TNS_RESET_STR "|" TNS_RESET_RETRIES_STR "|" TNS_TEST_STR "|"\ + TNS_ALIVE_STR "|" TNS_ALIVE_RETRIES_STR "|" TSNS_PROV_STR "|" TSNS_SIZE_RETRIES_STR "|" TSNS_CONFIG_RETRIES_STR "|"\ + TSNS_PROCEDURES_RETRIES_STR ")" + #define NS_TIMERS_HELP \ "(un)blocking Timer (Tns-block) timeout\n" \ "(un)blocking Timer (Tns-block) number of retries\n" \
View file
libosmocore_1.9.3.tar.xz/src/gb/gprs_ns2_vty.c -> libosmocore_1.10.0.tar.xz/src/gb/gprs_ns2_vty.c
Changed
@@ -91,18 +91,18 @@ }; /* TODO: this should into osmo timer */ -static const struct value_string gprs_ns_timer_strs = { - { 0, "tns-block" }, - { 1, "tns-block-retries" }, - { 2, "tns-reset" }, - { 3, "tns-reset-retries" }, - { 4, "tns-test" }, - { 5, "tns-alive" }, - { 6, "tns-alive-retries" }, - { 7, "tsns-prov" }, - { 8, "tsns-size-retries" }, - { 9, "tsns-config-retries" }, - {10, "tsns-procedures-retries" }, +const struct value_string gprs_ns_timer_strs = { + { NS_TOUT_TNS_BLOCK, TNS_BLOCK_STR }, + { NS_TOUT_TNS_BLOCK_RETRIES, TNS_BLOCK_RETRIES_STR }, + { NS_TOUT_TNS_RESET, TNS_RESET_STR }, + { NS_TOUT_TNS_RESET_RETRIES, TNS_RESET_RETRIES_STR }, + { NS_TOUT_TNS_TEST, TNS_TEST_STR }, + { NS_TOUT_TNS_ALIVE, TNS_ALIVE_STR }, + { NS_TOUT_TNS_ALIVE_RETRIES, TNS_ALIVE_RETRIES_STR }, + { NS_TOUT_TSNS_PROV, TSNS_PROV_STR }, + { NS_TOUT_TSNS_SIZE_RETRIES, TSNS_SIZE_RETRIES_STR }, + { NS_TOUT_TSNS_CONFIG_RETRIES, TSNS_CONFIG_RETRIES_STR }, + { NS_TOUT_TSNS_PROCEDURES_RETRIES, TSNS_PROCEDURES_RETRIES_STR }, { 0, NULL } };
View file
libosmocore_1.9.3.tar.xz/src/gsm/Makefile.am -> libosmocore_1.10.0.tar.xz/src/gsm/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=20:0:0 +LIBVERSION=21:0:1 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall $(TALLOC_CFLAGS) @@ -33,10 +33,13 @@ milenage/aes-internal.c milenage/aes-internal-enc.c \ milenage/milenage.c gan.c ipa.c gsm0341.c apn.c \ tuak/KeccakP-1600-3gpp.c tuak/tuak.c auth_tuak.c \ - gsup.c gsup_sms.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ + gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \ gsm23003.c gsm23236.c mncc.c bts_features.c oap_client.c \ gsm29118.c gsm48_rest_octets.c cbsp.c gsm48049.c \ - gad.c bsslap.c bssmap_le.c kdf.c iuup.c gsm44021.c gsm44068.c + gad.c bsslap.c bssmap_le.c kdf.c iuup.c gsm44021.c gsm44068.c rlp.c +if !EMBEDDED +libgsmint_la_SOURCES += gsup.c gsup_sms.c +endif # !EMBEDDED libgsmint_la_LDFLAGS = -no-undefined libgsmint_la_LIBADD = $(top_builddir)/src/core/libosmocore.la $(top_builddir)/src/isdn/libosmoisdn.la
View file
libosmocore_1.9.3.tar.xz/src/gsm/bts_features.c -> libosmocore_1.10.0.tar.xz/src/gsm/bts_features.c
Changed
@@ -47,6 +47,8 @@ { BTS_FEAT_OSMUX, "Osmux (Osmocom RTP multiplexing)" }, { BTS_FEAT_VBS, "Voice Broadcast Service" }, { BTS_FEAT_VGCS, "Voice Group Call Service" }, + { BTS_FEAT_TWTS001, "TW-TS-001 RTP format" }, + { BTS_FEAT_TWTS002, "TW-TS-002 RTP format" }, { 0, NULL } }; @@ -88,6 +90,8 @@ { BTS_FEAT_OSMUX, "OSMUX" }, { BTS_FEAT_VBS, "VBS" }, { BTS_FEAT_VGCS, "VGCS" }, + { BTS_FEAT_TWTS001, "TWTS001" }, + { BTS_FEAT_TWTS002, "TWTS002" }, {} };
View file
libosmocore_1.9.3.tar.xz/src/gsm/cbsp.c -> libosmocore_1.10.0.tar.xz/src/gsm/cbsp.c
Changed
@@ -1567,6 +1567,26 @@ return rc; } +/*! call-back function to segment the data at message boundaries. + * Returns the size of the next message. If it returns -EAGAIN or a value larger than msgb_length() (message + * is incomplete), the caller (e.g. osmo_io) has to wait for more data to be read. */ +int osmo_cbsp_segmentation_cb(struct msgb *msg) +{ + const struct cbsp_header *h; + int len; + + if (msgb_length(msg) < sizeof(*h)) + return -EAGAIN; + + h = (const struct cbsp_header *) msg->data; + msg->l1h = msg->data; + msg->l2h = msg->data + sizeof(*h); + /* then read the length as specified in the header */ + len = h->len0 << 16 | h->len1 << 8 | h->len2; + + return sizeof(*h) + len; +} + /*! value_string for enum osmo_cbsp_cause. */ const struct value_string osmo_cbsp_cause_names = { { OSMO_CBSP_CAUSE_PARAM_NOT_RECOGNISED, "Parameter-not-recognised" },
View file
libosmocore_1.9.3.tar.xz/src/gsm/gsm0808.c -> libosmocore_1.10.0.tar.xz/src/gsm/gsm0808.c
Changed
@@ -2310,9 +2310,10 @@ GSM0808_IE_PS_REGISTERED_OPERATOR = { TLV_TYPE_FIXED, 3 }, GSM0808_IE_CS_REGISTERED_OPERATOR = { TLV_TYPE_FIXED, 3 }, - /* Osmocom extensions */ + /* Osmocom and Themyscira extensions */ GSM0808_IE_OSMO_OSMUX_SUPPORT = { TLV_TYPE_T }, GSM0808_IE_OSMO_OSMUX_CID = { TLV_TYPE_TV }, + GSM0808_IE_THEMWI_RTP_EXTENSIONS = { TLV_TYPE_TLV }, }, };
View file
libosmocore_1.9.3.tar.xz/src/gsm/gsm0808_utils.c -> libosmocore_1.10.0.tar.xz/src/gsm/gsm0808_utils.c
Changed
@@ -2075,25 +2075,12 @@ { 0, NULL } }; -#define APPEND_THING(func, args...) do { \ - int remain = buflen - (pos - buf); \ - int l = func(pos, remain, ##args); \ - if (l < 0 || l > remain) \ - pos = buf + buflen; \ - else \ - pos += l; \ - if (l > 0) \ - total_len += l; \ - } while(0) -#define APPEND_STR(fmt, args...) APPEND_THING(snprintf, fmt, ##args) -#define APPEND_CELL_ID_U(DISCR, U) APPEND_THING(gsm0808_cell_id_u_name, DISCR, U) - char *gsm0808_cell_id_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id *cid) { - char *pos = buf; - int total_len = 0; - APPEND_STR("%s:", gsm0808_cell_id_discr_name(cid->id_discr)); - APPEND_CELL_ID_U(cid->id_discr, &cid->id); + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + + OSMO_STRBUF_PRINTF(sb, "%s:", gsm0808_cell_id_discr_name(cid->id_discr)); + OSMO_STRBUF_APPEND(sb, gsm0808_cell_id_u_name, cid->id_discr, &cid->id); return buf; } @@ -2140,30 +2127,31 @@ */ int gsm0808_cell_id_list_name_buf(char *buf, size_t buflen, const struct gsm0808_cell_id_list2 *cil) { - char *pos = buf; - int total_len = 0; - int i; + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - APPEND_STR("%s%u", gsm0808_cell_id_discr_name(cil->id_discr), cil->id_list_len); + OSMO_STRBUF_PRINTF(sb, "%s%u", + gsm0808_cell_id_discr_name(cil->id_discr), + cil->id_list_len); switch (cil->id_discr) { case CELL_IDENT_BSS: case CELL_IDENT_NO_CELL: - return total_len; + return sb.chars_needed; default: break; } - APPEND_STR(":{"); + OSMO_STRBUF_PRINTF(sb, ":{"); - for (i = 0; i < cil->id_list_len; i++) { + for (unsigned int i = 0; i < cil->id_list_len; i++) { if (i) - APPEND_STR(", "); - APPEND_CELL_ID_U(cil->id_discr, &cil->id_listi); + OSMO_STRBUF_PRINTF(sb, ", "); + OSMO_STRBUF_APPEND(sb, gsm0808_cell_id_u_name, + cil->id_discr, &cil->id_listi); } - APPEND_STR("}"); - return total_len; + OSMO_STRBUF_PRINTF(sb, "}"); + return sb.chars_needed; } /*! Return a human-readable representation of \a cil in a static buffer. @@ -2185,9 +2173,6 @@ return buf; } -#undef APPEND_STR -#undef APPEND_CELL_ID_U - char *gsm0808_channel_type_name_buf(char *buf, size_t buf_len, const struct gsm0808_channel_type *ct) { snprintf(buf, buf_len, "ch_indctr=0x%x ch_rate_type=0x%x perm_spch=%s",
View file
libosmocore_1.9.3.tar.xz/src/gsm/gsm48.c -> libosmocore_1.10.0.tar.xz/src/gsm/gsm48.c
Changed
@@ -641,8 +641,10 @@ char *str = NULL; /* initialize to avoid uninitialized false warnings on some gcc versions (11.1.0) */ size_t str_size = 0; /* initialize to avoid uninitialized false warnings on some gcc versions (11.1.0) */ - if (!mi_data || mi_len < 1) - return -EBADMSG; + if (!mi_data || mi_len < 1) { + rc = -EBADMSG; + goto return_error; + } nibbles_len = (mi_len - 1) * 2 + ((mi_data0 & GSM_MI_ODD) ? 1 : 0);
View file
libosmocore_1.9.3.tar.xz/src/gsm/gsm48_ie.c -> libosmocore_1.10.0.tar.xz/src/gsm/gsm48_ie.c
Changed
@@ -44,10 +44,11 @@ }; /*! Like gsm48_decode_bcd_number2() but with less airtight bounds checking. - * \paramout Caller-provided output buffer + * \paramout output Caller-provided output buffer + * \paramin output_len sizeof(output) * \paramin bcd_lv Length-Value portion of to-be-decoded IE * \paramin h_len Length of an optional heder between L and V portion - * \returns - in case of success; negative on error */ + * \returns 0 in case of success; negative on error */ int gsm48_decode_bcd_number(char *output, int output_len, const uint8_t *bcd_lv, int h_len) { @@ -139,7 +140,7 @@ * \paramin max_len Maximum Length of \a bcd_lv * \paramin h_len Length of an optional heder between L and V portion * \paramin input phone number as 0-terminated ASCII - * \returns number of bytes used in \a bcd_lv + * \returns number of bytes used in \a bcd_lv; negative on error * * Depending on a context (e.g. called or calling party BCD number), the * optional header between L and V parts can contain TON (Type Of Number), @@ -179,8 +180,8 @@ } /*! Decode TS 04.08 Bearer Capability IE (10.5.4.5) - * \paramout Caller-provided memory for decoded output - * \aramin LV portion of TS 04.08 Bearer Capability + * \paramout bcap Caller-provided memory for decoded output + * \paramin lv LV portion of TS 04.08 Bearer Capability * \returns 0 on success; negative on error */ int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap, const uint8_t *lv) @@ -233,6 +234,7 @@ } break; case GSM_MNCC_BCAP_UNR_DIG: + case GSM_MNCC_BCAP_AUDIO: case GSM_MNCC_BCAP_FAX_G3: i = 1; while (!(lvi & 0x80)) { @@ -334,10 +336,11 @@ lvi |= 0x80; /* last IE of octet 3 etc */ break; case GSM48_BCAP_ITCAP_UNR_DIG_INF: + case GSM48_BCAP_ITCAP_3k1_AUDIO: case GSM48_BCAP_ITCAP_FAX_G3: lvi++ |= 0x80; /* last IE of octet 3 etc */ /* octet 4 */ - lvi++ = 0xb8; + lvi++ = 0x88; /* octet 5 */ lvi++ = 0x80 | ((bcap->data.rate_adaption & 3) << 3) | (bcap->data.sig_access & 7); @@ -369,7 +372,7 @@ } /*! Decode TS 04.08 Call Control Capabilities IE (10.5.4.5a) - * \paramout Caller-provided memory for decoded CC capabilities + * \paramout ccap Caller-provided memory for decoded CC capabilities * \paramin lv Length-Value of IE * \returns 0 on success; negative on error */ int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv) @@ -455,7 +458,7 @@ } /*! Decode TS 04.08 Caller ID - * \paramout called Caller-provided memory for decoded number + * \paramout callerid Caller-provided memory for decoded number * \paramin lv Length-Value portion of IE * \returns 0 on success; negative on error */ int gsm48_decode_callerid(struct gsm_mncc_number *callerid,
View file
libosmocore_1.9.3.tar.xz/src/gsm/gsup.c -> libosmocore_1.10.0.tar.xz/src/gsm/gsup.c
Changed
@@ -103,6 +103,10 @@ OSMO_VALUE_STRING(OSMO_GSUP_MSGT_ROUTING_ERROR), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_EPDG_TUNNEL_REQUEST), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_EPDG_TUNNEL_RESULT), + OSMO_VALUE_STRING(OSMO_GSUP_MSGT_EPDG_TUNNEL_ERROR), + { 0, NULL } }; @@ -122,6 +126,62 @@ return OSMO_GSUP_TO_MSGT_ERROR(type_in); } +static int decode_pdp_address(const uint8_t *data, size_t data_len, struct osmo_gsup_pdp_info *pdp_info) +{ + const struct gsm48_pdp_address *pdp_addr = (const struct gsm48_pdp_address *)data; + /* Explicitly pre-nitialize them to AF_UNSPEC to signal they are empty: */ + pdp_info->pdp_address0.u.sa.sa_family = AF_UNSPEC; + pdp_info->pdp_address1.u.sa.sa_family = AF_UNSPEC; + + if (data_len < 2) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + pdp_info->pdp_type_org = pdp_addr->organization; + pdp_info->pdp_type_nr = pdp_addr->type; + + if (pdp_info->pdp_type_org != PDP_TYPE_ORG_IETF) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + + /* Skip type-org + type-nr for easy calculations below: */ + data_len -= 2; + + switch (pdp_info->pdp_type_nr) { + case PDP_TYPE_N_IETF_IPv4: + if (data_len == 0) + return 0; /* empty, marked as AF_UNSET. */ + if (data_len != sizeof(pdp_addr->ietf.v4)) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + pdp_info->pdp_address0.u.sa.sa_family = AF_INET; + pdp_info->pdp_address0.u.sin.sin_addr.s_addr = pdp_addr->ietf.v4; + return 0; + case PDP_TYPE_N_IETF_IPv6: + if (data_len == 0) + return 0; /* empty, marked as AF_UNSET. */ + if (data_len != sizeof(pdp_addr->ietf.v6)) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + pdp_info->pdp_address0.u.sa.sa_family = AF_INET6; + memcpy(&pdp_info->pdp_address0.u.sin6.sin6_addr, + pdp_addr->ietf.v6, + sizeof(pdp_addr->ietf.v6)); + return 0; + case PDP_TYPE_N_IETF_IPv4v6: + if (data_len == 0) + return 0; /* empty, marked as AF_UNSET. */ + if (data_len != sizeof(pdp_addr->ietf.v4v6)) + return -GMM_CAUSE_PROTO_ERR_UNSPEC; + pdp_info->pdp_address0.u.sa.sa_family = AF_INET; + pdp_info->pdp_address0.u.sin.sin_addr.s_addr = pdp_addr->ietf.v4v6.v4; + pdp_info->pdp_address1.u.sa.sa_family = AF_INET6; + memcpy(&pdp_info->pdp_address1.u.sin6.sin6_addr, + pdp_addr->ietf.v4v6.v6, + sizeof(pdp_addr->ietf.v4v6.v6)); + return 0; + default: + /* reserved, both pdp_info->pdp_address are preinitialied to AF_UNSET. */ + return 0; + } +} + static int decode_pdp_info(uint8_t *data, size_t data_len, struct osmo_gsup_pdp_info *pdp_info) { @@ -145,9 +205,9 @@ pdp_info->context_id = osmo_decode_big_endian(value, value_len); break; - case OSMO_GSUP_PDP_TYPE_IE: - pdp_info->pdp_type = - osmo_decode_big_endian(value, value_len) & 0x0fff; + case OSMO_GSUP_PDP_ADDRESS_IE: + if ((rc = decode_pdp_address(value, value_len, pdp_info)) < 0) + return rc; break; case OSMO_GSUP_ACCESS_POINT_NAME_IE: @@ -262,7 +322,7 @@ parse_error: LOGP(DLGSUP, LOGL_ERROR, - "GSUP IE type %d, length %zu invalid in PDP info\n", iei, value_len); + "GSUP IE type %d, length %zu invalid in auth info\n", iei, value_len); return -1; } @@ -353,7 +413,7 @@ switch (iei) { case OSMO_GSUP_IMSI_IE: - case OSMO_GSUP_PDP_TYPE_IE: + case OSMO_GSUP_PDP_ADDRESS_IE: case OSMO_GSUP_ACCESS_POINT_NAME_IE: case OSMO_GSUP_SRES_IE: case OSMO_GSUP_KC_IE: @@ -446,6 +506,11 @@ gsup_msg->rand = value; break; + case OSMO_GSUP_PCO_IE: + gsup_msg->pco = value; + gsup_msg->pco_len = value_len; + break; + case OSMO_GSUP_MSISDN_IE: gsup_msg->msisdn_enc = value; gsup_msg->msisdn_enc_len = value_len; @@ -597,11 +662,45 @@ u8 = pdp_info->context_id; msgb_tlv_put(msg, OSMO_GSUP_PDP_CONTEXT_ID_IE, sizeof(u8), &u8); - if (pdp_info->pdp_type) { - msgb_tlv_put(msg, OSMO_GSUP_PDP_TYPE_IE, - OSMO_GSUP_PDP_TYPE_SIZE, - osmo_encode_big_endian(pdp_info->pdp_type | 0xf000, - OSMO_GSUP_PDP_TYPE_SIZE)); + if (pdp_info->pdp_type_org == PDP_TYPE_ORG_IETF) { + struct gsm48_pdp_address pdp_addr; + uint8_t pdp_addr_len = 2; + pdp_addr.spare = 0x0f; + pdp_addr.organization = pdp_info->pdp_type_org; + pdp_addr.type = pdp_info->pdp_type_nr; + + switch (pdp_info->pdp_type_nr) { + case PDP_TYPE_N_IETF_IPv4: + if (pdp_info->pdp_address0.u.sa.sa_family == AF_INET) { + pdp_addr.ietf.v4 = pdp_info->pdp_address0.u.sin.sin_addr.s_addr; + pdp_addr_len += sizeof(pdp_addr.ietf.v4); + } + break; + case PDP_TYPE_N_IETF_IPv6: + if (pdp_info->pdp_address0.u.sa.sa_family == AF_INET6) { + memcpy(pdp_addr.ietf.v6, + &pdp_info->pdp_address0.u.sin6.sin6_addr, + sizeof(pdp_addr.ietf.v6)); + pdp_addr_len += sizeof(pdp_addr.ietf.v6); + } + break; + case PDP_TYPE_N_IETF_IPv4v6: + if (pdp_info->pdp_address0.u.sa.sa_family == AF_INET) { + pdp_addr.ietf.v4v6.v4 = pdp_info->pdp_address0.u.sin.sin_addr.s_addr; + pdp_addr_len += sizeof(pdp_addr.ietf.v4v6.v4); + } + if (pdp_info->pdp_address0.u.sa.sa_family == AF_INET6) { + memcpy(pdp_addr.ietf.v4v6.v6, + &pdp_info->pdp_address1.u.sin6.sin6_addr, + sizeof(pdp_addr.ietf.v4v6.v6)); + pdp_addr_len += sizeof(pdp_addr.ietf.v4v6.v6); + } + break; + } + + msgb_tlv_put(msg, OSMO_GSUP_PDP_ADDRESS_IE, + pdp_addr_len, + (const uint8_t *)&pdp_addr); } if (pdp_info->apn_enc) { @@ -778,6 +877,11 @@ if (gsup_msg->rand) msgb_tlv_put(msg, OSMO_GSUP_RAND_IE, 16, gsup_msg->rand); + if (gsup_msg->pco && gsup_msg->pco_len > 0) { + if (gsup_msg->pco_len > OSMO_GSUP_MAX_PCO_LEN) + return -EINVAL; + msgb_tlv_put(msg, OSMO_GSUP_PCO_IE, gsup_msg->pco_len, gsup_msg->pco); + } if (gsup_msg->cn_domain) { uint8_t dn = gsup_msg->cn_domain; msgb_tlv_put(msg, OSMO_GSUP_CN_DOMAIN_IE, 1, &dn); @@ -911,6 +1015,7 @@ { OSMO_GSUP_MESSAGE_CLASS_SMS, "SMS" }, { OSMO_GSUP_MESSAGE_CLASS_USSD, "USSD" }, { OSMO_GSUP_MESSAGE_CLASS_INTER_MSC, "Inter-MSC" }, + { OSMO_GSUP_MESSAGE_CLASS_IPSEC_EPDG, "IPsec-ePDG" }, {} };
View file
libosmocore_1.9.3.tar.xz/src/gsm/ipa.c -> libosmocore_1.10.0.tar.xz/src/gsm/ipa.c
Changed
@@ -267,34 +267,43 @@ return 0; } +/*! Fill ud struct from tp structure. + * \paramin,out ud ipaccess_unit to fill + * \paramin tp the decoded TLV structure from eg. ID_RESP message + * \returns zero on success, negative on error + * + * This function expects parameter ud's fields to be initialized to zero if not yet set. + * Existing incoming string pointer fields are expected to be allocated using + * talloc and will be deallocated as such if replaced with the content of tp. + **/ int ipa_ccm_tlv_to_unitdata(struct ipaccess_unit *ud, const struct tlv_parsed *tp) { int rc = 0; if (TLVP_PRES_LEN(tp, IPAC_IDTAG_SERNR, 1)) - ud->serno = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_SERNR)); + osmo_talloc_replace_string(ud, &ud->serno, + (char *)TLVP_VAL(tp, IPAC_IDTAG_SERNR)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_UNITNAME, 1)) - ud->unit_name = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_UNITNAME)); + osmo_talloc_replace_string(ud, &ud->unit_name, + (char *)TLVP_VAL(tp, IPAC_IDTAG_UNITNAME)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_LOCATION1, 1)) - ud->location1 = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_LOCATION1)); + osmo_talloc_replace_string(ud, &ud->location1, + (char *)TLVP_VAL(tp, IPAC_IDTAG_LOCATION1)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_LOCATION2, 1)) - ud->location2 = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_LOCATION2)); + osmo_talloc_replace_string(ud, &ud->location2, + (char *)TLVP_VAL(tp, IPAC_IDTAG_LOCATION2)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_EQUIPVERS, 1)) - ud->equipvers = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_EQUIPVERS)); + osmo_talloc_replace_string(ud, &ud->equipvers, + (char *)TLVP_VAL(tp, IPAC_IDTAG_EQUIPVERS)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_SWVERSION, 1)) - ud->swversion = talloc_strdup(ud, (char *) - TLVP_VAL(tp, IPAC_IDTAG_SWVERSION)); + osmo_talloc_replace_string(ud, &ud->swversion, + (char *)TLVP_VAL(tp, IPAC_IDTAG_SWVERSION)); if (TLVP_PRES_LEN(tp, IPAC_IDTAG_MACADDR, 17)) { rc = osmo_macaddr_parse(ud->mac_addr, (char *)
View file
libosmocore_1.9.3.tar.xz/src/gsm/lapdm.c -> libosmocore_1.10.0.tar.xz/src/gsm/lapdm.c
Changed
@@ -27,6 +27,7 @@ #include <stdio.h> #include <stdint.h> +#include <inttypes.h> #include <string.h> #include <errno.h> @@ -196,9 +197,10 @@ char name256; if (name_pfx) { snprintf(name, sizeof(name), "%s%s", name_pfx, i == 0 ? "0" : "3"); - lapdm_dl_init(&le->datalinki, le, t200_msi, n200, name); + lapdm_dl_init(&le->datalinki, le, (t200_ms) ? t200_msi : 0, n200, name); } else - lapdm_dl_init(&le->datalinki, le, t200_msi, n200, NULL); + lapdm_dl_init(&le->datalinki, le, (t200_ms) ? t200_msi : 0, n200, NULL); + INIT_LLIST_HEAD(&le->datalinki.tx_ui_queue); } lapdm_entity_set_mode(le, mode); @@ -295,6 +297,7 @@ for (i = 0; i < ARRAY_SIZE(le->datalink); i++) { dl = &le->datalinki; lapd_dl_exit(&dl->dl); + msgb_queue_free(&dl->tx_ui_queue); } } @@ -358,6 +361,18 @@ /* if there is a pending message, queue it */ if (le->tx_pending || le->flags & LAPDM_ENT_F_POLLING_ONLY) { + struct msgb *old_msg; + + /* In 'RTS' mode there can be only one message. */ + if (le->flags & LAPDM_ENT_F_RTS) { + /* Overwrite existing message by removing it first. */ + if ((old_msg = msgb_dequeue(&dl->dl.tx_queue))) { + msgb_free(old_msg); + /* Reset V(S) to V(A), because there is no outstanding message now. */ + dl->dl.v_send = dl->dl.v_ack; + } + } + *msgb_push(msg, 1) = pad; *msgb_push(msg, 1) = link_id; *msgb_push(msg, 1) = chan_nr; @@ -377,21 +392,87 @@ return le->l1_prim_cb(&pp.oph, le->l1_ctx); } +static int tx_ph_data_enqueue_ui(struct lapdm_datalink *dl, struct msgb *msg, + uint8_t chan_nr, uint8_t link_id, uint8_t pad) +{ + struct lapdm_entity *le = dl->entity; + struct osmo_phsap_prim pp; + + /* if there is a pending message, queue it */ + if (le->tx_pending || le->flags & LAPDM_ENT_F_POLLING_ONLY) { + *msgb_push(msg, 1) = pad; + *msgb_push(msg, 1) = link_id; + *msgb_push(msg, 1) = chan_nr; + msgb_enqueue(&dl->tx_ui_queue, msg); + return 0; + } + + osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA, + PRIM_OP_REQUEST, msg); + pp.u.data.chan_nr = chan_nr; + pp.u.data.link_id = link_id; + + /* send the frame now */ + le->tx_pending = 0; /* disabled flow control */ + lapdm_pad_msgb(msg, pad); + + return le->l1_prim_cb(&pp.oph, le->l1_ctx); +} + +/* Get transmit frame from queue, if any. In polling mode, indicate RTS to LAPD and start T200, if pending. */ +static struct msgb *tx_dequeue_msgb(struct lapdm_datalink *dl, uint32_t fn) +{ + struct msgb *msg; + + /* Call RTS function of LAPD, to queue next frame. */ + if (dl->entity->flags & LAPDM_ENT_F_RTS) { + struct lapd_msg_ctx lctx; + int rc; + + /* Poll next frame. */ + lctx.dl = &dl->dl; + rc = lapd_ph_rts_ind(&lctx); + + /* If T200 has been started, calculate timeout FN. */ + if (rc == 1) { + /* Set T200 in advance. */ + dl->t200_timeout = fn; + ADD_MODULO(dl->t200_timeout, dl->t200_fn, GSM_MAX_FN); + + LOGDL(&dl->dl, LOGL_INFO, + "T200 running from FN %"PRIu32" to FN %"PRIu32" (%"PRIu32" frames).\n", + fn, dl->t200_timeout, dl->t200_fn); + } + } + + /* If there is no frame from LAPD, send UI frame, if any. */ + msg = msgb_dequeue(&dl->dl.tx_queue); + if (msg) + LOGDL(&dl->dl, LOGL_INFO, "Sending frame from TX queue. (FN %"PRIu32")\n", fn); + else { + msg = msgb_dequeue(&dl->tx_ui_queue); + if (msg) + LOGDL(&dl->dl, LOGL_INFO, "Sending UI frame from TX queue. (FN %"PRIu32")\n", fn); + } + return msg; +} + /* Dequeue a Downlink message for DCCH (dedicated channel) */ -static struct msgb *tx_dequeue_dcch_msgb(struct lapdm_entity *le) +static struct msgb *tx_dequeue_dcch_msgb(struct lapdm_entity *le, uint32_t fn) { struct msgb *msg; /* SAPI=0 always has higher priority than SAPI=3 */ - msg = msgb_dequeue(&le->datalinkDL_SAPI0.dl.tx_queue); - if (msg == NULL) /* no SAPI=0 messages, dequeue SAPI=3 (if any) */ - msg = msgb_dequeue(&le->datalinkDL_SAPI3.dl.tx_queue); + msg = tx_dequeue_msgb(&le->datalinkDL_SAPI0, fn); + if (msg == NULL) { /* no SAPI=0 messages, dequeue SAPI=3 (if any) */ + msg = tx_dequeue_msgb(&le->datalinkDL_SAPI3, fn); + } return msg; } /* Dequeue a Downlink message for ACCH (associated channel) */ -static struct msgb *tx_dequeue_acch_msgb(struct lapdm_entity *le) +static struct msgb *tx_dequeue_acch_msgb(struct lapdm_entity *le, uint32_t fn) { struct lapdm_datalink *dl; int last = le->last_tx_dequeue; @@ -403,7 +484,7 @@ /* next */ i = (i + 1) % n; dl = &le->datalinki; - if ((msg = msgb_dequeue(&dl->dl.tx_queue))) + if ((msg = tx_dequeue_msgb(dl, fn))) break; } while (i != last); @@ -417,7 +498,7 @@ /*! dequeue a msg that's pending transmission via L1 and wrap it into * a osmo_phsap_prim */ -int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp) +int lapdm_phsap_dequeue_prim_fn(struct lapdm_entity *le, struct osmo_phsap_prim *pp, uint32_t fn) { struct msgb *msg; uint8_t pad; @@ -425,9 +506,9 @@ /* Dequeue depending on channel type: DCCH or ACCH. * See 3GPP TS 44.005, section 4.2.2 "Priority". */ if (le == &le->lapdm_ch->lapdm_dcch) - msg = tx_dequeue_dcch_msgb(le); + msg = tx_dequeue_dcch_msgb(le, fn); else - msg = tx_dequeue_acch_msgb(le); + msg = tx_dequeue_acch_msgb(le, fn); if (!msg) return -ENODEV; @@ -449,6 +530,57 @@ return 0; } +static void lapdm_t200_fn_dl(struct lapdm_datalink *dl, uint32_t fn) +{ + uint32_t diff; + + OSMO_ASSERT((dl->dl.lapd_flags & LAPD_F_RTS)); + + /* If T200 is running, check if it has fired. */ + if (dl->dl.t200_rts != LAPD_T200_RTS_RUNNING) + return; + + /* Calculate how many frames fn is behind t200_timeout. + * If it is negative (>= GSM_MAX_FN / 2), we have not reached t200_timeout yet. + * If it is 0 or positive, we reached it or we are a bit too late, which is not a problem. + */ + diff = fn; + ADD_MODULO(diff, GSM_MAX_FN - dl->t200_timeout, GSM_MAX_FN); + if (diff >= GSM_MAX_FN / 2) + return; + + LOGDL(&dl->dl, LOGL_INFO, "T200 timeout at FN %"PRIu32", detected at FN %"PRIu32".\n", dl->t200_timeout, fn); + + lapd_t200_timeout(&dl->dl); +} + +/*! Get receive frame number from L1. It is used to check the T200 timeout. + * This function is used if LAPD is in RTS mode only. (Applies if the LAPDM_ENT_F_POLLING_ONLY flag is set.) + * This function must be called for every valid or invalid data frame received. + * The frame number fn must be the frame number of the first burst of a data frame. + * This function must be called after the frame is delivered to layer 2. + * In case of TCH, this this function must be called for every speech frame received, meaning that there was no valid + * data frame. */ +void lapdm_t200_fn(struct lapdm_entity *le, uint32_t fn) +{ + unsigned int i; + + if (!(le->flags & LAPDM_ENT_F_POLLING_ONLY)) { + LOGP(DLLAPD, LOGL_ERROR, "Function call not allowed on timer based T200.\n"); + return; + } + + for (i = 0; i < ARRAY_SIZE(le->datalink); i++) + lapdm_t200_fn_dl(&le->datalinki, fn); +} + +/*! dequeue a msg that's pending transmission via L1 and wrap it into + * a osmo_phsap_prim */ +int lapdm_phsap_dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp) +{ + return lapdm_phsap_dequeue_prim_fn(le, pp, 0); +} + /* get next frame from the tx queue. because the ms has multiple datalinks, * each datalink's queue is read round-robin. */ @@ -658,7 +790,8 @@ LAPDm_CTRL_PF_BIT(msg->l2h1)); rc = 0; } else if (LAPDm_CTRL_is_S(msg->l2h1)) { - LOGDL(dl, LOGL_ERROR, "Supervisory frame in queue, this shouldn't happen\n"); + msg->l2h1 = LAPDm_CTRL_S(dl->v_recv, LAPDm_CTRL_S_BITS(msg->l2h1), + LAPDm_CTRL_PF_BIT(msg->l2h1)); } } @@ -852,6 +985,7 @@ return -EINVAL; } /* send to LAPD */ + LOGDL(lctx.dl, LOGL_DEBUG, "Frame received at FN %"PRIu32".\n", fn); rc = lapd_ph_data_ind(msg, &lctx); break; case LAPDm_FMT_Bter: @@ -1083,7 +1217,7 @@ } /* Tramsmit */ - return tx_ph_data_enqueue(dl, msg, chan_nr, link_id, 23); + return tx_ph_data_enqueue_ui(dl, msg, chan_nr, link_id, 23); } /* L3 requests transfer of acknowledged information */ @@ -1480,6 +1614,7 @@ for (i = 0; i < ARRAY_SIZE(le->datalink); i++) { dl = &le->datalinki; lapd_dl_reset(&dl->dl); + msgb_queue_free(&dl->tx_ui_queue); } } @@ -1493,7 +1628,22 @@ /*! Set the flags of a LAPDm entity */ void lapdm_entity_set_flags(struct lapdm_entity *le, unsigned int flags) { + unsigned int dl_flags = 0; + struct lapdm_datalink *dl; + int i; + le->flags = flags; + + /* Set flags at LAPD. */ + if (le->flags & LAPDM_ENT_F_RTS) + dl_flags |= LAPD_F_RTS; + if (le->flags & LAPDM_ENT_F_DROP_2ND_REJ) + dl_flags |= LAPD_F_DROP_2ND_REJ; + + for (i = 0; i < ARRAY_SIZE(le->datalink); i++) { + dl = &le->datalinki; + lapd_dl_set_flags(&dl->dl, dl_flags); + } } /*! Set the flags of all LAPDm entities in a LAPDm channel */ @@ -1503,4 +1653,25 @@ lapdm_entity_set_flags(&lc->lapdm_acch, flags); } +/*! Set the T200 FN timer of a LAPDm entity + * \paramin \ref lapdm_entity + * \paramin t200_fn Array of T200 timeout in frame numbers for all SAPIs (0, 3) */ +void lapdm_entity_set_t200_fn(struct lapdm_entity *le, const uint32_t *t200_fn) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(le->datalink); i++) + le->datalinki.t200_fn = t200_fni; +} + +/*! Set the T200 FN timer of all LAPDm entities in a LAPDm channel + * \paramin \ref lapdm_channel + * \paramin t200_fn_dcch Array of T200 timeout in frame numbers for all SAPIs (0, 3) on SDCCH/FACCH + * \paramin t200_fn_acch Array of T200 timeout in frame numbers for all SAPIs (0, 3) on SACCH */ +void lapdm_channel_set_t200_fn(struct lapdm_channel *lc, const uint32_t *t200_fn_dcch, const uint32_t *t200_fn_acch) +{ + lapdm_entity_set_t200_fn(&lc->lapdm_dcch, t200_fn_dcch); + lapdm_entity_set_t200_fn(&lc->lapdm_acch, t200_fn_acch); +} + /*! @} */
View file
libosmocore_1.9.3.tar.xz/src/gsm/libosmogsm.map -> libosmocore_1.10.0.tar.xz/src/gsm/libosmogsm.map
Changed
@@ -587,7 +587,11 @@ lapdm_entity_reset; lapdm_entity_set_flags; lapdm_entity_set_mode; +lapdm_entity_set_t200_fn; +lapdm_channel_set_t200_fn; lapdm_phsap_dequeue_prim; +lapdm_phsap_dequeue_prim_fn; +lapdm_t200_fn; lapdm_phsap_up; lapdm_rslms_recvmsg; @@ -789,6 +793,7 @@ osmo_cbsp_decode; osmo_cbsp_recv_buffered; osmo_cbsp_errstr; +osmo_cbsp_segmentation_cb; osmo_i460_demux_in; osmo_i460_mux_enqueue; @@ -860,5 +865,12 @@ osmo_csd_3k6_encode_frame; osmo_csd_ubit_dump; +osmo_rlp_decode; +osmo_rlp_encode; +osmo_rlp_fcs_compute; +osmo_rlp_ftype_s_vals; +osmo_rlp_ftype_u_vals; +osmo_rlp_ftype_vals; + local: *; };
View file
libosmocore_1.10.0.tar.xz/src/gsm/rlp.c
Added
@@ -0,0 +1,243 @@ +/* + * Copyright (C) 2022-2023 Harald Welte <laforge@osmocom.org> + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 2 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. + */ + +/*! \addtogroup rlp + * @{ + * RLP (Radio Link Protocol) as per 3GPP TS 24.022 + * + */ + +#include <stdint.h> +#include <stddef.h> +#include <string.h> +#include <errno.h> + +#include <osmocom/gsm/rlp.h> + +const struct value_string osmo_rlp_ftype_vals = { + { OSMO_RLP_FT_U, "U" }, + { OSMO_RLP_FT_S, "S" }, + { OSMO_RLP_FT_IS, "IS" }, + { 0, NULL } +}; + +const struct value_string osmo_rlp_ftype_u_vals = { + { OSMO_RLP_U_FT_SABM, "SABM" }, + { OSMO_RLP_U_FT_UA, "UA" }, + { OSMO_RLP_U_FT_DISC, "DISC" }, + { OSMO_RLP_U_FT_DM, "DM" }, + { OSMO_RLP_U_FT_NULL, "NULL" }, + { OSMO_RLP_U_FT_UI, "UI" }, + { OSMO_RLP_U_FT_XID, "XID" }, + { OSMO_RLP_U_FT_TEST, "TEST" }, + { OSMO_RLP_U_FT_REMAP, "REMAP" }, + { 0, NULL } +}; + +const struct value_string osmo_rlp_ftype_s_vals = { + { OSMO_RLP_S_FT_RR, "RR" }, + { OSMO_RLP_S_FT_REJ, "REJ" }, + { OSMO_RLP_S_FT_RNR, "RNR" }, + { OSMO_RLP_S_FT_SREJ, "SREJ" }, + { 0, NULL } +}; + +/* number of bytes used up by FCS */ +#define FCS_SIZE_BYTES 3 + +/*! decode a RLP frame into its abstract representation. Doesn't check FCS correctness. + * \paramout out caller-allocated memory for output of decoded frame + * \paramin version RLP version number to use when decoding + * \paramin data raw RLP frame input data + * \paramin data_len length of data (in octets); must be 30 (240bit) or 72 (576bit) + * \returns 0 in case of success; negative on error */ +int osmo_rlp_decode(struct osmo_rlp_frame_decoded *out, uint8_t version, const uint8_t *data, size_t data_len) +{ + const uint8_t hdr_len = 2; /* will become a variable when we introduce v2 support */ + uint8_t n_s, n_r; + + if (data_len != 240/8 && data_len != 576/8) + return -EINVAL; + + /* we only support version 0+1 so far */ + if (version >= 2) + return -ENOTSUP; + + memset(out, 0, sizeof(*out)); + out->version = version; + + out->c_r = data0 & 1; + n_s = (data0 >> 3) | (data1 & 1) << 5; + n_r = (data1 >> 2); + out->fcs = (datadata_len-1 << 16) | (datadata_len-2) << 8 | (datadata_len-3 << 0); + out->p_f = (data1 >> 1) & 1; + + switch (n_s) { + case 0x3f: + out->ftype = OSMO_RLP_FT_U; + out->u_ftype = n_r & 0x1f; + if (out->u_ftype == OSMO_RLP_U_FT_XID) { + memcpy(out->info, data + hdr_len, data_len - (hdr_len + FCS_SIZE_BYTES)); + out->info_len = data_len - (hdr_len + FCS_SIZE_BYTES); + } + break; + case 0x3e: + out->ftype = OSMO_RLP_FT_S; + out->s_ftype = (data0 >> 1) & 3; + out->n_r = n_r; + break; + default: + out->ftype = OSMO_RLP_FT_IS; + out->s_ftype = (data0 >> 1) & 3; + out->n_s = n_s; + out->n_r = n_r; + memcpy(out->info, data + hdr_len, data_len - (hdr_len + FCS_SIZE_BYTES)); + out->info_len = data_len - (2 + 3); + break; + } + + return 0; +} + +/*! encode a RLP frame from its abstract representation. Generates FCS. + * \paramout out caller-allocated output buffer + * \paramin out_size size of output buffer (in octets); must be 30 (240bit) or 72 (576bit) + * \paramin in decoded RLP frame which is to be encoded + * \returns number of output bytes used; negative on error */ +int osmo_rlp_encode(uint8_t *out, size_t out_size, const struct osmo_rlp_frame_decoded *in) +{ + const uint8_t hdr_len = 2; /* will become a variable when we introduce v2 support */ + uint8_t n_s, n_r, s_bits; + uint32_t fcs; + + /* we only support version 0+1 so far */ + if (in->version >= 2) + return -ENOTSUP; + + if (out_size != 240/8 && out_size != 576/8) + return -EINVAL; + + memset(out, 0, out_size); + + if (in->c_r) + out0 |= 0x01; + if (in->p_f) + out1 |= 0x02; + + switch (in->ftype) { + case OSMO_RLP_FT_U: + n_s = 0x3f; + n_r = in->u_ftype; + s_bits = 0; + if (in->u_ftype == OSMO_RLP_U_FT_XID) { + if (in->info_len > out_size - (hdr_len + FCS_SIZE_BYTES)) + return -EINVAL; + memcpy(out+hdr_len, in->info, in->info_len); + } + break; + case OSMO_RLP_FT_S: + n_s = 0x3e; + n_r = in->n_r; + s_bits = in->s_ftype; + break; + case OSMO_RLP_FT_IS: + /* we only support 240 bit so far */ + if (in->info_len > out_size - (hdr_len + FCS_SIZE_BYTES)) + return -EINVAL; + n_s = in->n_s; + n_r = in->n_r; + s_bits = in->s_ftype; + memcpy(out+hdr_len, in->info, in->info_len); + break; + default: + return -EINVAL; + } + + /* patch N(S) into output data */ + out0 |= (n_s & 0x1F) << 3; + out1 |= (n_s & 0x20) >> 5; + + /* patch N(R) / M-bits into output data */ + out1 |= (n_r & 0x3f) << 2; + + /* patch S-bits into output data */ + out0 |= (s_bits & 3) << 1; + + /* compute FCS + add it to end of frame */ + fcs = osmo_rlp_fcs_compute(out, out_size - FCS_SIZE_BYTES); + outout_size - 3 = (fcs >> 0) & 0xff; + outout_size - 2 = (fcs >> 8) & 0xff; + outout_size - 1 = (fcs >> 16) & 0xff; + + return out_size; +} + + +static const uint32_t rlp_fcs_table256 = { + 0x00B29D2D, 0x00643A5B, 0x0044D87A, 0x00927F0C, 0x00051C38, 0x00D3BB4E, 0x00F3596F, 0x0025FE19, + 0x008694BC, 0x005033CA, 0x0070D1EB, 0x00A6769D, 0x003115A9, 0x00E7B2DF, 0x00C750FE, 0x0011F788, + 0x00DA8E0F, 0x000C2979, 0x002CCB58, 0x00FA6C2E, 0x006D0F1A, 0x00BBA86C, 0x009B4A4D, 0x004DED3B, + 0x00EE879E, 0x003820E8, 0x0018C2C9, 0x00CE65BF, 0x0059068B, 0x008FA1FD, 0x00AF43DC, 0x0079E4AA, + 0x0062BB69, 0x00B41C1F, 0x0094FE3E, 0x00425948, 0x00D53A7C, 0x00039D0A, 0x00237F2B, 0x00F5D85D, + 0x0056B2F8, 0x0080158E, 0x00A0F7AF, 0x007650D9, 0x00E133ED, 0x0037949B, 0x001776BA, 0x00C1D1CC, + 0x000AA84B, 0x00DC0F3D, 0x00FCED1C, 0x002A4A6A, 0x00BD295E, 0x006B8E28, 0x004B6C09, 0x009DCB7F, + 0x003EA1DA, 0x00E806AC, 0x00C8E48D, 0x001E43FB, 0x008920CF, 0x005F87B9, 0x007F6598, 0x00A9C2EE, + 0x0049DA1E, 0x009F7D68, 0x00BF9F49, 0x0069383F, 0x00FE5B0B, 0x0028FC7D, 0x00081E5C, 0x00DEB92A, + 0x007DD38F, 0x00AB74F9, 0x008B96D8, 0x005D31AE, 0x00CA529A, 0x001CF5EC, 0x003C17CD, 0x00EAB0BB, + 0x0021C93C, 0x00F76E4A, 0x00D78C6B, 0x00012B1D, 0x00964829, 0x0040EF5F, 0x00600D7E, 0x00B6AA08, + 0x0015C0AD, 0x00C367DB, 0x00E385FA, 0x0035228C, 0x00A241B8, 0x0074E6CE, 0x005404EF, 0x0082A399, + 0x0099FC5A, 0x004F5B2C, 0x006FB90D, 0x00B91E7B, 0x002E7D4F, 0x00F8DA39, 0x00D83818, 0x000E9F6E, + 0x00ADF5CB, 0x007B52BD, 0x005BB09C, 0x008D17EA, 0x001A74DE, 0x00CCD3A8, 0x00EC3189, 0x003A96FF, + 0x00F1EF78, 0x0027480E, 0x0007AA2F, 0x00D10D59, 0x00466E6D, 0x0090C91B, 0x00B02B3A, 0x00668C4C, + 0x00C5E6E9, 0x0013419F, 0x0033A3BE, 0x00E504C8, 0x007267FC, 0x00A4C08A, 0x008422AB, 0x005285DD, + 0x001F18F0, 0x00C9BF86, 0x00E95DA7, 0x003FFAD1, 0x00A899E5, 0x007E3E93, 0x005EDCB2, 0x00887BC4, + 0x002B1161, 0x00FDB617, 0x00DD5436, 0x000BF340, 0x009C9074, 0x004A3702, 0x006AD523, 0x00BC7255, + 0x00770BD2, 0x00A1ACA4, 0x00814E85, 0x0057E9F3, 0x00C08AC7, 0x00162DB1, 0x0036CF90, 0x00E068E6, + 0x00430243, 0x0095A535, 0x00B54714, 0x0063E062, 0x00F48356, 0x00222420, 0x0002C601, 0x00D46177, + 0x00CF3EB4, 0x001999C2, 0x00397BE3, 0x00EFDC95, 0x0078BFA1, 0x00AE18D7, 0x008EFAF6, 0x00585D80, + 0x00FB3725, 0x002D9053, 0x000D7272, 0x00DBD504, 0x004CB630, 0x009A1146, 0x00BAF367, 0x006C5411, + 0x00A72D96, 0x00718AE0, 0x005168C1, 0x0087CFB7, 0x0010AC83, 0x00C60BF5, 0x00E6E9D4, 0x00304EA2, + 0x00932407, 0x00458371, 0x00656150, 0x00B3C626, 0x0024A512, 0x00F20264, 0x00D2E045, 0x00044733, + 0x00E45FC3, 0x0032F8B5, 0x00121A94, 0x00C4BDE2, 0x0053DED6, 0x008579A0, 0x00A59B81, 0x00733CF7, + 0x00D05652, 0x0006F124, 0x00261305, 0x00F0B473, 0x0067D747, 0x00B17031, 0x00919210, 0x00473566, + 0x008C4CE1, 0x005AEB97, 0x007A09B6, 0x00ACAEC0, 0x003BCDF4, 0x00ED6A82, 0x00CD88A3, 0x001B2FD5, + 0x00B84570, 0x006EE206, 0x004E0027, 0x0098A751, 0x000FC465, 0x00D96313, 0x00F98132, 0x002F2644, + 0x00347987, 0x00E2DEF1, 0x00C23CD0, 0x00149BA6, 0x0083F892, 0x00555FE4, 0x0075BDC5, 0x00A31AB3, + 0x00007016, 0x00D6D760, 0x00F63541, 0x00209237, 0x00B7F103, 0x00615675, 0x0041B454, 0x00971322, + 0x005C6AA5, 0x008ACDD3, 0x00AA2FF2, 0x007C8884, 0x00EBEBB0, 0x003D4CC6, 0x001DAEE7, 0x00CB0991, + 0x00686334, 0x00BEC442, 0x009E2663, 0x00488115, 0x00DFE221, 0x00094557, 0x0029A776, 0x00FF0000 +}; + +/*! compute RLP FCS according to 3GPP TS 24.022 Section 4.4. + * \paramin in input data over which to compute FCS + * \paramin in_len length of input data (in octets) + * \returns computed frame check sequence (FCS). */ +uint32_t osmo_rlp_fcs_compute(const uint8_t *in, size_t in_len) +{ + uint32_t divider = 0; + size_t i; + + for (i = 0; i < in_len; i++) { + uint8_t input = ini ^ (divider & 0xff); + divider = (divider >> 8) ^ rlp_fcs_tableinput; + } + + return divider; +} + +/*! @} */
View file
libosmocore_1.9.3.tar.xz/src/gsm/rsl.c -> libosmocore_1.10.0.tar.xz/src/gsm/rsl.c
Changed
@@ -126,6 +126,7 @@ RSL_IE_OSMO_TRAINING_SEQUENCE = { TLV_TYPE_TLV }, RSL_IE_OSMO_TEMP_OVP_ACCH_CAP = { TLV_TYPE_TLV }, RSL_IE_OSMO_OSMUX_CID = { TLV_TYPE_TLV }, + RSL_IE_OSMO_RTP_EXTENSIONS = { TLV_TYPE_TLV }, RSL_IE_IPAC_SRTP_CONFIG = { TLV_TYPE_TLV }, RSL_IE_IPAC_PROXY_UDP = { TLV_TYPE_FIXED, 2 }, RSL_IE_IPAC_BSCMPL_TOUT = { TLV_TYPE_TV },
View file
libosmocore_1.9.3.tar.xz/src/isdn/Makefile.am -> libosmocore_1.10.0.tar.xz/src/isdn/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=1:0:1 +LIBVERSION=2:0:2 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include AM_CFLAGS = -Wall $(TALLOC_CFLAGS) @@ -13,7 +13,7 @@ noinst_LTLIBRARIES = libisdnint.la lib_LTLIBRARIES = libosmoisdn.la -libisdnint_la_SOURCES = i460_mux.c lapd_core.c v110.c +libisdnint_la_SOURCES = i460_mux.c lapd_core.c v110.c v110_ta.c libisdnint_la_LDFLAGS = -no-undefined libisdnint_la_LIBADD = $(top_builddir)/src/core/libosmocore.la
View file
libosmocore_1.9.3.tar.xz/src/isdn/lapd_core.c -> libosmocore_1.10.0.tar.xz/src/isdn/lapd_core.c
Changed
@@ -108,7 +108,7 @@ static void lapd_t200_cb(void *data); static void lapd_t203_cb(void *data); -static int lapd_send_i(struct lapd_msg_ctx *lctx, int line); +static int lapd_send_i(struct lapd_datalink *dl, int line, bool rts); static int lapd_est_req(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx); /* UTILITY FUNCTIONS */ @@ -169,12 +169,17 @@ } } -static void lapd_dl_flush_tx(struct lapd_datalink *dl) +static void lapd_dl_flush_tx_queue(struct lapd_datalink *dl) { struct msgb *msg; while ((msg = msgb_dequeue(&dl->tx_queue))) msgb_free(msg); +} + +static void lapd_dl_flush_tx(struct lapd_datalink *dl) +{ + lapd_dl_flush_tx_queue(dl); lapd_dl_flush_hist(dl); } @@ -199,11 +204,35 @@ static void lapd_start_t200(struct lapd_datalink *dl) { - if (osmo_timer_pending(&dl->t200)) - return; - LOGDL(dl, LOGL_INFO, "start T200 (timeout=%d.%06ds)\n", - dl->t200_sec, dl->t200_usec); - osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec); + if ((dl->lapd_flags & LAPD_F_RTS)) { + if (dl->t200_rts != LAPD_T200_RTS_OFF) + return; + LOGDL(dl, LOGL_INFO, "Start T200. (pending until triggered by RTS)\n"); + dl->t200_rts = LAPD_T200_RTS_PENDING; + } else { + if (osmo_timer_pending(&dl->t200)) + return; + LOGDL(dl, LOGL_INFO, "Start T200 (timeout=%d.%06ds).\n", dl->t200_sec, dl->t200_usec); + osmo_timer_schedule(&dl->t200, dl->t200_sec, dl->t200_usec); + } +} + +/*! Handle timeout condition of T200 in RTS mode. + * The caller (LAPDm code) implements the T200 timer and must detect timeout condition. + * The function gets called by LAPDm code when it detects a timeout of T200. + * \paramin dl caller-allocated datalink structure */ +int lapd_t200_timeout(struct lapd_datalink *dl) +{ + OSMO_ASSERT((dl->lapd_flags & LAPD_F_RTS)); + + if (dl->t200_rts != LAPD_T200_RTS_RUNNING) + return -EINVAL; + + dl->t200_rts = LAPD_T200_RTS_OFF; + + lapd_t200_cb(dl); + + return 0; } static void lapd_start_t203(struct lapd_datalink *dl) @@ -216,10 +245,24 @@ static void lapd_stop_t200(struct lapd_datalink *dl) { - if (!osmo_timer_pending(&dl->t200)) - return; + if ((dl->lapd_flags & LAPD_F_RTS)) { + if (dl->t200_rts == LAPD_T200_RTS_OFF) + return; + dl->t200_rts = LAPD_T200_RTS_OFF; + } else { + if (!osmo_timer_pending(&dl->t200)) + return; + osmo_timer_del(&dl->t200); + } LOGDL(dl, LOGL_INFO, "stop T200\n"); - osmo_timer_del(&dl->t200); +} + +static bool lapd_is_t200_started(struct lapd_datalink *dl) +{ + if ((dl->lapd_flags & LAPD_F_RTS)) + return (dl->t200_rts != LAPD_T200_RTS_OFF); + else + return osmo_timer_pending(&dl->t200); } static void lapd_stop_t203(struct lapd_datalink *dl) @@ -354,6 +397,21 @@ lapd_dl_newstate(dl, LAPD_STATE_IDLE); } +/*! Set lapd_flags to change behaviour + * \paramin dl \ref lapd_datalink instance + * \paramin flags \ref lapd_flags */ +int lapd_dl_set_flags(struct lapd_datalink *dl, unsigned int flags) +{ + if (lapd_is_t200_started(dl) && (flags & LAPD_F_RTS) != (dl->lapd_flags & LAPD_F_RTS)) { + LOGDL(dl, LOGL_ERROR, "Changing RTS flag not allowed while T200 is running.\n"); + return -EINVAL; + } + + dl->lapd_flags = flags; + + return 0; +} + /* reset and de-allocate history buffer */ void lapd_dl_exit(struct lapd_datalink *dl) { @@ -593,6 +651,8 @@ switch (dl->state) { case LAPD_STATE_SABM_SENT: /* 5.4.1.3 */ + /* increment re-transmission counter */ + dl->retrans_ctr++; if (dl->retrans_ctr >= dl->n200_est_rel + 1) { /* flush tx and send buffers */ lapd_dl_flush_tx(dl); @@ -611,13 +671,13 @@ } /* retransmit SABM command */ lapd_send_resend(dl); - /* increment re-transmission counter */ - dl->retrans_ctr++; /* restart T200 (PH-READY-TO-SEND) */ lapd_start_t200(dl); break; case LAPD_STATE_DISC_SENT: /* 5.4.4.3 */ + /* increment re-transmission counter */ + dl->retrans_ctr++; if (dl->retrans_ctr >= dl->n200_est_rel + 1) { /* send MDL ERROR INIDCATION to L3 */ mdl_error(MDL_CAUSE_T200_EXPIRED, &dl->lctx); @@ -635,8 +695,6 @@ } /* retransmit DISC command */ lapd_send_resend(dl); - /* increment re-transmission counter */ - dl->retrans_ctr++; /* restart T200 (PH-READY-TO-SEND) */ lapd_start_t200(dl); break; @@ -738,8 +796,9 @@ lapd_start_t200(dl); } -/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value */ -static void lapd_acknowledge(struct lapd_msg_ctx *lctx) +/* 5.5.3.1: Common function to acknowlege frames up to the given N(R) value + * In case of a sequence error, the cause is returned with negative sign. */ +static int lapd_acknowledge(struct lapd_msg_ctx *lctx) { struct lapd_datalink *dl = lctx->dl; uint8_t nr = lctx->n_recv; @@ -780,7 +839,7 @@ */ if (sub_mod(nr, dl->v_ack, dl->v_range) > sub_mod(dl->v_send, dl->v_ack, dl->v_range)) { LOGDL(dl, LOGL_NOTICE, "N(R) sequence error\n"); - mdl_error(MDL_CAUSE_SEQ_ERR, lctx); + return -MDL_CAUSE_SEQ_ERR; } } @@ -801,11 +860,10 @@ /* Stop T203, if running */ lapd_stop_t203(dl); /* Start T203, if T200 is not running in MF EST state, if enabled */ - if (!osmo_timer_pending(&dl->t200) - && (dl->t203_sec || dl->t203_usec) - && (dl->state == LAPD_STATE_MF_EST)) { + if (!lapd_is_t200_started(dl) && (dl->t203_sec || dl->t203_usec) && (dl->state == LAPD_STATE_MF_EST)) lapd_start_t203(dl); - } + + return 0; } /* L1 -> L2 */ @@ -1242,7 +1300,7 @@ /* enter multiple-frame-established state */ lapd_dl_newstate(dl, LAPD_STATE_MF_EST); /* send outstanding frames, if any (resume / reconnect) */ - lapd_send_i(lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); /* send notification to L3 */ rc = send_dl_simple(PRIM_DL_EST, PRIM_OP_CONFIRM, lctx); msgb_free(msg); @@ -1365,7 +1423,7 @@ lapd_dl_newstate(dl, LAPD_STATE_MF_EST); } /* Send message, if possible due to acknowledged data */ - lapd_send_i(lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); break; case LAPD_S_RNR: @@ -1376,6 +1434,10 @@ /* 5.5.5 */ /* Set peer receiver busy condition */ dl->peer_busy = 1; + /* Flush pending messages in TX queue. */ + lapd_dl_flush_tx_queue(dl); + /* stop Timer T200 */ + lapd_stop_t200(dl); if (lctx->p_f) { if (lctx->cr == dl->cr.rem2loc.cmd) { @@ -1402,7 +1464,7 @@ LOGDL(dl, LOGL_INFO, "RNR not polling/final state received\n"); /* Send message, if possible due to acknowledged data */ - lapd_send_i(lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); break; case LAPD_S_REJ: @@ -1416,6 +1478,8 @@ dl->peer_busy = 0; /* V(S) and V(A) to the N(R) in the REJ frame */ dl->v_send = dl->v_ack = lctx->n_recv; + /* Flush pending messages in TX queue. */ + lapd_dl_flush_tx_queue(dl); /* stop Timer T200 */ lapd_stop_t200(dl); /* 5.5.3.2 */ @@ -1452,6 +1516,8 @@ dl->peer_busy = 0; /* V(S) and V(A) to the N(R) in the REJ frame */ dl->v_send = dl->v_ack = lctx->n_recv; + /* Flush pending messages in TX queue. */ + lapd_dl_flush_tx_queue(dl); /* stop Timer T200 */ lapd_stop_t200(dl); /* 5.5.7 Clear timer recovery condition */ @@ -1461,6 +1527,8 @@ dl->peer_busy = 0; /* V(S) and V(A) to the N(R) in the REJ frame */ dl->v_send = dl->v_ack = lctx->n_recv; + /* Flush pending messages in TX queue. */ + lapd_dl_flush_tx_queue(dl); /* 5.5.3.2 */ if (lctx->cr == dl->cr.rem2loc.cmd && lctx->p_f) { if (!dl->own_busy && !dl->seq_err_cond) { @@ -1487,8 +1555,8 @@ /* FIXME: 5.5.4.2 2) */ - /* Send message, if possible due to acknowledged data */ - lapd_send_i(lctx, __LINE__); + /* Send message, if possible due to acknowledged data and new V(S) and V(A). */ + lapd_send_i(dl, __LINE__, false); break; default: @@ -1510,6 +1578,8 @@ uint8_t ns = lctx->n_send; int length = lctx->length; int rc; + bool i_frame_in_queue = false; + int mdl_cause = 0; LOGDL(dl, LOGL_INFO, "I received in state %s on SAPI(%u)\n", lapd_state_name(dl->state), lctx->sapi); @@ -1567,9 +1637,8 @@ ns, dl->v_recv, lapd_state_name(dl->state)); /* discard data */ msgb_free(msg); - if (dl->seq_err_cond != 1) { - /* FIXME: help me understand what exactly todo here - */ + /* Send reject, but suppress second reject if LAPD_F_DROP_2ND_REJ flag is set. */ + if (dl->seq_err_cond != 1 || !(dl->lapd_flags & LAPD_F_DROP_2ND_REJ)) { dl->seq_err_cond = 1; lapd_send_rej(lctx, lctx->p_f); } else { @@ -1587,10 +1656,12 @@ } /* Even if N(s) sequence error, acknowledge to N(R)-1 */ /* 5.5.3.1: Acknowlege all transmitted frames up the N(R)-1 */ - lapd_acknowledge(lctx); /* V(A) is also set here */ + mdl_cause = lapd_acknowledge(lctx); /* V(A) is also set here */ + if (mdl_cause < 0) + mdl_error(-mdl_cause, lctx); /* Send message, if possible due to acknowledged data */ - lapd_send_i(lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); return 0; } @@ -1600,8 +1671,15 @@ dl->v_recv = inc_mod(dl->v_recv, dl->v_range); LOGDL(dl, LOGL_INFO, "incrementing V(R) to %u\n", dl->v_recv); + /* Update all pending frames in the queue to the new V(R) state. */ + if (dl->update_pending_frames) { + rc = dl->update_pending_frames(lctx); + if (!rc) + i_frame_in_queue = true; + } + /* 5.5.3.1: Acknowlege all transmitted frames up the the N(R)-1 */ - lapd_acknowledge(lctx); /* V(A) is also set here */ + mdl_cause = lapd_acknowledge(lctx); /* V(A) is also set here */ /* Only if we are not in own receiver busy condition */ if (!dl->own_busy) { @@ -1646,6 +1724,10 @@ } else LOGDL(dl, LOGL_INFO, "I frame ignored during own receiver busy condition\n"); + /* Indicate sequence error, if exists. */ + if (mdl_cause < 0) + mdl_error(-mdl_cause, lctx); + /* Check for P bit */ if (lctx->p_f) { /* 5.5.2.1 */ @@ -1664,14 +1746,8 @@ /* check if we are not in own receiver busy */ if (!dl->own_busy) { /* NOTE: V(R) is already set above */ - rc = lapd_send_i(lctx, __LINE__); - - /* if update_pending_iframe returns 0 it updated - * the lapd header of an iframe in the tx queue */ - if (rc && dl->update_pending_frames) - rc = dl->update_pending_frames(lctx); - - if (rc) { + rc = lapd_send_i(dl, __LINE__, false); + if (rc && !i_frame_in_queue) { LOGDL(dl, LOGL_INFO, "we are not busy and have no pending data, " "send RR\n"); /* Send RR with F=0 */ @@ -1687,7 +1763,7 @@ } /* Send message, if possible due to acknowledged data */ - lapd_send_i(lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); return rc; } @@ -1715,6 +1791,31 @@ return rc; } +/*! Enqueue next LAPD frame and run pending T200. (Must be called when frame is ready to send.) + * The caller (LAPDm code) calls this function before it sends the next frame. + * If there is no frame in the TX queue, LAPD will enqueue next I-frame, if possible. + * If the T200 is pending, it is changed to running state. + * \paramin lctx LAPD context + * \paramout rc set to 1, if timer T200 state changed to running, set to 0, if not. */ +int lapd_ph_rts_ind(struct lapd_msg_ctx *lctx) +{ + struct lapd_datalink *dl = lctx->dl; + + /* If there is no pending frame, try to enqueue next I frame. */ + if (llist_empty(&dl->tx_queue) && (dl->state == LAPD_STATE_MF_EST || dl->state == LAPD_STATE_TIMER_RECOV)) { + /* Send an I frame, if there are pending outgoing messages. */ + lapd_send_i(dl, __LINE__, true); + } + + /* Run T200 at RTS, if pending. Tell caller that is has been started. (rc = 1) */ + if (dl->t200_rts == LAPD_T200_RTS_PENDING) { + dl->t200_rts = LAPD_T200_RTS_RUNNING; + return 1; + } + + return 0; +} + /* L3 -> L2 */ /* send unit data */ @@ -1825,15 +1926,15 @@ msgb_enqueue(&dl->send_queue, msg); /* Send message, if possible */ - lapd_send_i(&dl->lctx, __LINE__); + lapd_send_i(dl, __LINE__, false); return 0; } /* Send next I frame from queued/buffered data */ -static int lapd_send_i(struct lapd_msg_ctx *lctx, int line) +static int lapd_send_i(struct lapd_datalink *dl, int line, bool rts) { - struct lapd_datalink *dl = lctx->dl; + struct lapd_msg_ctx *lctx = &dl->lctx; uint8_t k = dl->k; uint8_t h; struct msgb *msg; @@ -1841,18 +1942,26 @@ int rc = - 1; /* we sent nothing */ struct lapd_msg_ctx nctx; + if (!rts) + LOGDL(dl, LOGL_INFO, "%s() called from line %d\n", __func__, line); - LOGDL(dl, LOGL_INFO, "%s() called from line %d\n", __func__, line); + if ((dl->lapd_flags & LAPD_F_RTS) && !llist_empty(&dl->tx_queue)) { + if (!rts) + LOGDL(dl, LOGL_INFO, "There is a frame in the TX queue, not checking for sending I frame.\n"); + return rc; + } next_frame: if (dl->peer_busy) { - LOGDL(dl, LOGL_INFO, "peer busy, not sending\n"); + if (!rts) + LOGDL(dl, LOGL_INFO, "Peer busy, not sending.\n"); return rc; } if (dl->state == LAPD_STATE_TIMER_RECOV) { - LOGDL(dl, LOGL_INFO, "timer recovery, not sending\n"); + if (!rts) + LOGDL(dl, LOGL_INFO, "Timer recovery, not sending.\n"); return rc; } @@ -1863,8 +1972,9 @@ * of the error recovery procedures as described in subclauses 5.5.4 and * 5.5.7. */ if (dl->v_send == add_mod(dl->v_ack, k, dl->v_range)) { - LOGDL(dl, LOGL_INFO, "k frames outstanding, not sending more " - "(k=%u V(S)=%u V(A)=%u)\n", k, dl->v_send, dl->v_ack); + if (!rts) + LOGDL(dl, LOGL_INFO, "k frames outstanding, not sending more. (k=%u V(S)=%u V(A)=%u)\n", + k, dl->v_send, dl->v_ack); return rc; } @@ -1906,7 +2016,7 @@ msg = lapd_msgb_alloc(length, "LAPD I"); msg->l3h = msgb_put(msg, length); /* assemble message */ - memcpy(&nctx, &dl->lctx, sizeof(nctx)); + memcpy(&nctx, lctx, sizeof(nctx)); /* keep nctx.ldp */ /* keep nctx.sapi */ /* keep nctx.tei */ @@ -1936,7 +2046,7 @@ msg = lapd_msgb_alloc(length, "LAPD I resend"); msg->l3h = msgb_put(msg, length); /* assemble message */ - memcpy(&nctx, &dl->lctx, sizeof(nctx)); + memcpy(&nctx, lctx, sizeof(nctx)); /* keep nctx.ldp */ /* keep nctx.sapi */ /* keep nctx.tei */ @@ -1958,7 +2068,7 @@ /* If timer T200 is not running at the time right before transmitting a * frame, when the PH-READY-TO-SEND primitive is received from the * physical layer., it shall be set. */ - if (!osmo_timer_pending(&dl->t200)) { + if (!lapd_is_t200_started(dl)) { /* stop Timer T203, if running */ lapd_stop_t203(dl); /* start Timer T200 */ @@ -1967,7 +2077,11 @@ dl->send_ph_data_req(&nctx, msg); - rc = 0; /* we sent something */ + /* When using RTS, we send only one frame. */ + if ((dl->lapd_flags & LAPD_F_RTS)) + return 0; + + rc = 0; /* We sent an I frame, so sending RR frame is not required. */ goto next_frame; }
View file
libosmocore_1.9.3.tar.xz/src/isdn/libosmoisdn.map -> libosmocore_1.10.0.tar.xz/src/isdn/libosmoisdn.map
Changed
@@ -7,11 +7,14 @@ lapd_dl_init2; lapd_dl_set_name; lapd_dl_reset; +lapd_dl_set_flags; lapd_msgb_alloc; lapd_ph_data_ind; +lapd_ph_rts_ind; lapd_recv_dlsap; lapd_set_mode; lapd_state_names; +lapd_t200_timeout; osmo_i460_demux_in; osmo_i460_mux_enqueue; @@ -24,11 +27,26 @@ osmo_v110_decode_frame; osmo_v110_encode_frame; osmo_v110_ubit_dump; +osmo_v110_e1e2e3; osmo_v110_sync_ra1_get_user_data_chunk_bitlen; osmo_v110_sync_ra1_get_user_data_rate; osmo_v110_sync_ra1_get_intermediate_rate; osmo_v110_sync_ra1_user_to_ir; osmo_v110_sync_ra1_ir_to_user; +osmo_v110_ta_alloc; +osmo_v110_ta_free; +osmo_v110_ta_set_timer_val_ms; +osmo_v110_ta_frame_in; +osmo_v110_ta_frame_out; +osmo_v110_ta_sync_ind; +osmo_v110_ta_desync_ind; +osmo_v110_ta_get_status; +osmo_v110_ta_get_circuit; +osmo_v110_ta_set_circuit; + +osmo_v110_ta_circuit_names; +osmo_v110_ta_circuit_descs; + local: *; };
View file
libosmocore_1.9.3.tar.xz/src/isdn/v110.c -> libosmocore_1.10.0.tar.xz/src/isdn/v110.c
Changed
@@ -143,6 +143,22 @@ /* I actually couldn't find any reference as to the value of F(ill) bits */ #define F 1 +/*! E1/E2/E3 bit values as per Table 5/V.110 */ +const ubit_t osmo_v110_e1e2e3_NUM_OSMO_V110_SYNC_RA13 = { + OSMO_V110_SYNC_RA1_600 = { 1, 0, 0 }, + OSMO_V110_SYNC_RA1_1200 = { 0, 1, 0 }, + OSMO_V110_SYNC_RA1_2400 = { 1, 1, 0 }, + OSMO_V110_SYNC_RA1_4800 = { 0, 1, 1 }, + OSMO_V110_SYNC_RA1_7200 = { 1, 0, 1 }, + OSMO_V110_SYNC_RA1_9600 = { 0, 1, 1 }, + OSMO_V110_SYNC_RA1_12000 = { 0, 0, 1 }, + OSMO_V110_SYNC_RA1_14400 = { 1, 0, 1 }, + OSMO_V110_SYNC_RA1_19200 = { 0, 1, 1 }, + OSMO_V110_SYNC_RA1_24000 = { 0, 0, 1 }, + OSMO_V110_SYNC_RA1_28800 = { 1, 0, 1 }, + OSMO_V110_SYNC_RA1_38400 = { 0, 1, 1 }, +}; + /*! Adapt from 6 synchronous 600bit/s input bits to a decoded V.110 frame. * \paramout fr caller-allocated output frame to which E+D bits are stored * \paramin d_in input user bits @@ -154,9 +170,7 @@ return -EINVAL; /* Table 6a / V.110 */ - fr->e_bits0 = 1; - fr->e_bits1 = 0; - fr->e_bits2 = 0; + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_600); for (int i = 0; i < 6; i++) memset(fr->d_bits + i*8, d_ini, 8); @@ -168,7 +182,7 @@ if (out_len < 6) return -ENOSPC; - if (fr->e_bits0 != 1 || fr->e_bits1 != 0 || fr->e_bits2 != 0) + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_600)) return -EINVAL; for (int i = 0; i < 6; i++) { @@ -190,9 +204,7 @@ return -EINVAL; /* Table 6b / V.110 */ - fr->e_bits0 = 0; - fr->e_bits1 = 1; - fr->e_bits2 = 0; + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_1200); for (int i = 0; i < 12; i++) memset(fr->d_bits + i*4, d_ini, 4); @@ -204,7 +216,7 @@ if (out_len < 12) return -ENOSPC; - if (fr->e_bits0 != 0 || fr->e_bits1 != 1 || fr->e_bits2 != 0) + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_1200)) return -EINVAL; for (int i = 0; i < 12; i++) { @@ -226,9 +238,7 @@ return -EINVAL; /* Table 6c / V.110 */ - fr->e_bits0 = 1; - fr->e_bits1 = 1; - fr->e_bits2 = 0; + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_2400); for (int i = 0; i < 24; i++) { fr->d_bitsi*2 + 0 = d_ini; fr->d_bitsi*2 + 1 = d_ini; @@ -243,7 +253,7 @@ return -ENOSPC; /* Table 6c / V.110 */ - if (fr->e_bits0 != 1 || fr->e_bits1 != 1 || fr->e_bits2 != 0) + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_2400)) return -EINVAL; for (int i = 0; i < 24; i++) { @@ -266,10 +276,8 @@ if (in_len != 36) return -EINVAL; - /* Table 6d / V.110 */ - fr->e_bits0 = 1; - fr->e_bits1 = 0; - fr->e_bits2 = 1; + /* Table 6d / V.110 (7200 is one of Nx3600) */ + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_7200); memcpy(fr->d_bits + d_idx, d_in + 0, 10); d_idx += 10; /* D1..D10 */ memset(fr->d_bits + d_idx, F, 2); d_idx += 2; @@ -297,7 +305,8 @@ if (out_len < 36) return -ENOSPC; - if (fr->e_bits0 != 1 || fr->e_bits1 != 0 || fr->e_bits2 != 1) + /* Table 6d / V.110 (7200 is one of Nx3600) */ + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_7200)) return -EINVAL; memcpy(d_out + 0, fr->d_bits + d_idx, 10); d_idx += 10; /* D1..D10 */ @@ -330,10 +339,8 @@ if (in_len != 48) return -EINVAL; - /* Table 6e / V.110 */ - fr->e_bits0 = 0; - fr->e_bits1 = 1; - fr->e_bits2 = 1; + /* Table 6e / V.110 (4800 is one of Nx4800) */ + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_4800); memcpy(fr->d_bits, d_in, 48); @@ -345,7 +352,8 @@ if (out_len < 48) return -ENOSPC; - if (fr->e_bits0 != 0 || fr->e_bits1 != 1 || fr->e_bits2 != 1) + /* Table 6e / V.110 (4800 is one of Nx4800) */ + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_4800)) return -EINVAL; memcpy(d_out, fr->d_bits, 48); @@ -365,10 +373,8 @@ if (in_len != 30) return -EINVAL; - /* Table 6f / V.110 */ - fr->e_bits0 = 0; - fr->e_bits1 = 0; - fr->e_bits2 = 1; + /* Table 6f / V.110 (12000 is one of Nx12000) */ + osmo_v110_e1e2e3_set(fr->e_bits, OSMO_V110_SYNC_RA1_12000); memcpy(fr->d_bits + d_idx, d_in + 0, 10); d_idx += 10; /* D1..D10 */ memset(fr->d_bits + d_idx, F, 2); d_idx += 2; @@ -399,7 +405,8 @@ if (out_len < 30) return -ENOSPC; - if (fr->e_bits0 != 0 || fr->e_bits1 != 0 || fr->e_bits2 != 1) + /* Table 6f / V.110 (12000 is one of Nx12000) */ + if (osmo_v110_e1e2e3_cmp(fr->e_bits, OSMO_V110_SYNC_RA1_12000)) return -EINVAL; memcpy(d_out + 0, fr->d_bits + d_idx, 10); d_idx += 10; /* D1..D10 */
View file
libosmocore_1.10.0.tar.xz/src/isdn/v110_ta.c
Added
@@ -0,0 +1,881 @@ +/*! \file v110_ta.c + * TA (Terminal Adapter) implementation as per ITU-T V.110. */ +/* + * (C) 2022 by Harald Welte <laforge@gnumonks.org> + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * + * Initial (Work-in-Progress) implementation by Harald Welte, + * completed and co-authored by Vadim Yanitskiy. + * + * All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 2 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. + * + */ + +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/bits.h> +#include <osmocom/core/tdef.h> +#include <osmocom/core/fsm.h> + +#include <osmocom/isdn/v110.h> +#include <osmocom/isdn/v110_ta.h> + +#define S(x) (1 << (x)) + +#define V24_FLAGMASK_IS_ON(flags, circuit) \ + (((flags) & S(circuit)) != 0) + +#define V24_FLAGMASK_IS_OFF(flags, circuit) \ + (((flags) & S(circuit)) == 0) + +#define V24_FLAGMASK_SET_ON(flags, circuit) \ + (flags) |= S(circuit) + +#define V24_FLAGMASK_SET_OFF(flags, circuit) \ + (flags) &= ~S(circuit) + +/* inverse logic: ON = binary 0; OFF = binary 1 */ +#define V110_SX_BIT_ON 0 +#define V110_SX_BIT_OFF 1 + +const struct value_string osmo_v110_ta_circuit_names = { + { OSMO_V110_TA_C_105, "105/RTS" }, + { OSMO_V110_TA_C_106, "106/CTS" }, + { OSMO_V110_TA_C_107, "107/DSR" }, + { OSMO_V110_TA_C_108, "108/DTR" }, + { OSMO_V110_TA_C_109, "109/DCD" }, + { OSMO_V110_TA_C_133, "133" }, + { 0, NULL } +}; + +const struct value_string osmo_v110_ta_circuit_descs = { + { OSMO_V110_TA_C_105, "Request to Send" }, + { OSMO_V110_TA_C_106, "Clear to Send" }, + { OSMO_V110_TA_C_107, "Data Set Ready" }, + { OSMO_V110_TA_C_108, "Data Terminal Ready" }, + { OSMO_V110_TA_C_109, "Data Carrier Detect" }, + { OSMO_V110_TA_C_133, "Ready for receiving" }, + { 0, NULL } +}; + +static const struct osmo_tdef v110_ta_tdef = { + { .T = OSMO_V110_TA_TIMER_X1, + .unit = OSMO_TDEF_MS, .default_val = 3000, /* suggested in 7.1.5 e) */ + .desc = "ITU-T V.110 7.1.5 Loss of frame synchronization: sync recovery timer" }, + { .T = OSMO_V110_TA_TIMER_T1, + .unit = OSMO_TDEF_MS, .default_val = 10000, /* suggested in 7.1.2.2 */ + .desc = "ITU-T V.110 7.1.2 Connect TA to line: sync establishment timer" }, + { .T = OSMO_V110_TA_TIMER_T2, + .unit = OSMO_TDEF_MS, .default_val = 5000, /* suggested in 7.1.4.1 */ + .desc = "ITU-T V.110 7.1.4 Disconnect mode: disconnect confirmation timer" }, + { /* end of list */ } +}; + +/********************************************************************************* + * V.110 TERMINAL ADAPTER FSM + *********************************************************************************/ + +enum v110_ta_fsm_state { + V110_TA_ST_IDLE_READY, /* 7.1.1 Idle (or ready) state */ + V110_TA_ST_CON_TA_TO_LINE, /* 7.1.2 Connect TA to line state */ + V110_TA_ST_DATA_TRANSFER, /* 7.1.3 Data transfer state */ + V110_TA_ST_DISCONNECTING, /* 7.1.4 Disconnect mode */ + V110_TA_ST_RESYNCING, /* 7.1.5 Re-synchronizing state */ +}; + +enum v110_ta_fsm_event { + V110_TA_EV_RX_FRAME_IND, /* a V.110 frame was received by the lower layer */ + V110_TA_EV_TX_FRAME_RTS, /* a V.110 frame is to be sent by the lower layer */ + V110_TA_EV_V24_STATUS_CHG, /* V.24 flag-mask has been updated by TE */ + V110_TA_EV_SYNC_IND, /* the lower layer has synchronized to the frame clock */ + V110_TA_EV_DESYNC_IND, /* the lower layer has lost frame clock synchronization */ + V110_TA_EV_TIMEOUT, /* generic event for handling a timeout condition */ +}; + +static const struct value_string v110_ta_fsm_event_names = { + { V110_TA_EV_RX_FRAME_IND, "RX_FRAME_IND" }, + { V110_TA_EV_TX_FRAME_RTS, "TX_FRAME_RTS" }, + { V110_TA_EV_V24_STATUS_CHG, "V24_STATUS_CHG" }, + { V110_TA_EV_SYNC_IND, "SYNC_IND" }, + { V110_TA_EV_DESYNC_IND, "DESYNC_IND" }, + { V110_TA_EV_TIMEOUT, "TIMEOUT" }, + { 0, NULL } +}; + +enum v110_ta_d_bit_mode { + V110_TA_DBIT_M_ALL_ZERO = 0, /* set all bits to binary '0' */ + V110_TA_DBIT_M_ALL_ONE = 1, /* set all bits to binary '1' */ + V110_TA_DBIT_M_FORWARD, /* forward D-bits to/from DTE */ +}; + +struct v110_ta_state { + /*! V.24 status flags shared between DTE (user) and DCE (TA, us) */ + unsigned int v24_flags; + struct { + /* what kind of D-bits to transmit in V.110 frames */ + enum v110_ta_d_bit_mode d_bit_mode; + /* what to put in S-bits of transmitted V.110 frames */ + ubit_t s_bits; + /* what to put in X-bits of transmitted V.110 frames */ + ubit_t x_bits; + } tx; + struct { + enum v110_ta_d_bit_mode d_bit_mode; + } rx; +}; + +struct osmo_v110_ta { + const char *name; + struct osmo_tdef *Tdefs; + struct osmo_fsm_inst *fi; + struct osmo_v110_ta_cfg *cfg; + struct v110_ta_state state; +}; + +static inline bool v110_df_x_bits_are(const struct osmo_v110_decoded_frame *df, ubit_t cmp) +{ + return (df->x_bits0 == cmp) && (df->x_bits1 == cmp); +} + +static inline bool v110_df_s_bits_are(const struct osmo_v110_decoded_frame *df, ubit_t cmp) +{ + /* ITU-T Table 2/V.110 (see also 5.1.2.3) defines the following S-bits: + * S1, S3, S4, S6, S8, S9 (6 bits total). However, fr->s_bits contains + * 9 (MAX_S_BITS) bits, including the undefined bits S2, S5, S7. + * Hence we must skip those undefined bits. */ + static const uint8_t sbit_map = { 0, 2, 3, 5, 7, 8 }; + + for (unsigned int i = 0; i < ARRAY_SIZE(sbit_map); i++) { + uint8_t idx = sbit_mapi; + if (df->s_bitsidx != cmp) + return false; + } + + return true; +} + +static inline bool v110_df_d_bits_are(const struct osmo_v110_decoded_frame *df, ubit_t cmp) +{ + for (unsigned int i = 0; i < MAX_D_BITS; i++) { + if (df->d_bitsi != cmp) + return false; + } + + return true; +} + +/* handle one V.110 frame and forward user bits to the application */ +static void v110_ta_handle_frame(const struct osmo_v110_ta *ta, + const struct osmo_v110_decoded_frame *df) +{ + const struct osmo_v110_ta_cfg *cfg = ta->cfg; + const struct v110_ta_state *ts = &ta->state; + ubit_t user_bitsMAX_D_BITS; + int num_user_bits; + int rc; + + switch (ts->rx.d_bit_mode) { + case V110_TA_DBIT_M_ALL_ZERO: + case V110_TA_DBIT_M_ALL_ONE: + /* generate as many user bits as needed for the configured rate */ + num_user_bits = osmo_v110_sync_ra1_get_user_data_chunk_bitlen(cfg->rate); + OSMO_ASSERT(num_user_bits > 0); + /* set them all to binary '0' or binary '1' */ + memset(&user_bits0, (int)ts->rx.d_bit_mode, num_user_bits); + cfg->rx_cb(cfg->priv, &user_bits0, num_user_bits); + break; + case V110_TA_DBIT_M_FORWARD: + rc = osmo_v110_sync_ra1_ir_to_user(cfg->rate, &user_bits0, sizeof(user_bits), df); + if (rc > 0) + cfg->rx_cb(cfg->priv, &user_bits0, rc); + /* XXX else: indicate an error somehow? */ + break; + } +} + +/* build one V.110 frame to transmit */ +static void v110_ta_build_frame(const struct osmo_v110_ta *ta, + struct osmo_v110_decoded_frame *df) +{ + const struct osmo_v110_ta_cfg *cfg = ta->cfg; + const struct v110_ta_state *ts = &ta->state; + ubit_t user_bitsMAX_D_BITS; + int num_user_bits; + int rc; + + /* E-bits (E1/E2/E3 may be overwritten below) */ + memset(df->e_bits, 1, sizeof(df->e_bits)); + /* S-bits */ + memset(df->s_bits, ts->tx.s_bits, sizeof(df->s_bits)); + /* X-bits */ + memset(df->x_bits, ts->tx.x_bits, sizeof(df->x_bits)); + + /* D-bits */ + switch (ts->tx.d_bit_mode) { + case V110_TA_DBIT_M_ALL_ZERO: + case V110_TA_DBIT_M_ALL_ONE: + /* set them all to binary '0' or binary '1' */ + memset(df->d_bits, (int)ts->tx.d_bit_mode, sizeof(df->d_bits)); + break; + case V110_TA_DBIT_M_FORWARD: + /* how many user bits to retrieve */ + num_user_bits = osmo_v110_sync_ra1_get_user_data_chunk_bitlen(cfg->rate); + OSMO_ASSERT(num_user_bits > 0); + /* retrieve user bits from the application */ + cfg->tx_cb(cfg->priv, &user_bits0, num_user_bits); + /* convert user bits to intermediate rate (store to df) */ + rc = osmo_v110_sync_ra1_user_to_ir(cfg->rate, df, &user_bits0, num_user_bits); + OSMO_ASSERT(rc == 0); + break; + } +} + +static void v110_ta_flags_update(struct osmo_v110_ta *ta, unsigned int v24_flags) +{ + struct osmo_v110_ta_cfg *cfg = ta->cfg; + + if (ta->state.v24_flags == v24_flags) + return; + if (cfg->status_update_cb != NULL) + cfg->status_update_cb(cfg->priv, v24_flags); + ta->state.v24_flags = v24_flags; +} + +static const struct osmo_tdef_state_timeout v110_ta_fsm_timeouts32 = { + V110_TA_ST_RESYNCING = { .T = OSMO_V110_TA_TIMER_X1 }, + V110_TA_ST_CON_TA_TO_LINE = { .T = OSMO_V110_TA_TIMER_T1 }, + V110_TA_ST_DISCONNECTING = { .T = OSMO_V110_TA_TIMER_T2 }, +}; + +#define v110_ta_fsm_state_chg(state) \ + osmo_tdef_fsm_inst_state_chg(fi, state, \ + v110_ta_fsm_timeouts, \ + ((struct osmo_v110_ta *)(fi->priv))->Tdefs, \ + 0) + +/* ITU-T V.110 Section 7.1.1 */ +static void v110_ta_fsm_idle_ready_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + unsigned int v24_flags = ta->state.v24_flags; + + /* 7.1.1.2 During the idle (or ready) state the TA will transmit continuous binary 1s into the B-channel */ + ts->tx.d_bit_mode = V110_TA_DBIT_M_ALL_ONE; /* circuit 103: continuous binary '1' */ + ts->tx.s_bits = V110_SX_BIT_OFF; /* OFF is binary '1' */ + ts->tx.x_bits = V110_SX_BIT_OFF; /* OFF is binary '1' */ + + /* 7.1.1.3 During the idle (or ready) state the TA (DCE) will transmit the following toward the DTE: */ + /* - circuit 104: continuous binary '1' */ + ts->rx.d_bit_mode = V110_TA_DBIT_M_ALL_ONE; + /* - circuits 107, 106, 109 = OFF */ + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_106); + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_107); + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_109); + v110_ta_flags_update(ta, v24_flags); +} + +/* ITU-T V.110 Section 7.1.1 */ +static void v110_ta_fsm_idle_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + + switch (event) { + case V110_TA_EV_V24_STATUS_CHG: + /* When the TA is to be switched to the data mode, circuit 108 must be ON */ + if (V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_108)) { + /* 7.12.2: Start timer T1 when switching to CON_TA_LINE */ + v110_ta_fsm_state_chg(V110_TA_ST_CON_TA_TO_LINE); + } + break; + case V110_TA_EV_RX_FRAME_IND: + v110_ta_handle_frame(ta, (const struct osmo_v110_decoded_frame *)data); + break; + case V110_TA_EV_TX_FRAME_RTS: + v110_ta_build_frame(ta, (struct osmo_v110_decoded_frame *)data); + break; + default: + OSMO_ASSERT(0); + } +} + +/* ITU-T V.110 Section 7.1.2 */ +static void v110_ta_fsm_connect_ta_to_line_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + + /* 7.1.2.1 Switching to the data mode causes the TA to transmit the following towards the ISDN: */ + /* a) frame synchronization pattern as described in 5.1.3.1 and 5.2.1 (done by the API user) */ + /* b) circuit 103: continuous binary '1' */ + ts->tx.d_bit_mode = V110_TA_DBIT_M_ALL_ONE; + /* c) status bits S = OFF and X = OFF */ + ts->tx.s_bits = V110_SX_BIT_OFF; /* OFF is binary '1' */ + ts->tx.x_bits = V110_SX_BIT_OFF; /* OFF is binary '1' */ + + /* 7.1.2.2 ... the receiver in the TA will begin to search for the frame synchronization + * pattern in the received bit stream (see 5.1.3.1 and 5.2.1) and start timer T1. */ + OSMO_ASSERT(fi->T == OSMO_V110_TA_TIMER_T1); +} + +/* ITU-T V.110 Section 7.1.2 */ +static void v110_ta_fsm_connect_ta_to_line(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + + switch (event) { + case V110_TA_EV_V24_STATUS_CHG: + /* If circuit 108 is OFF, we go back to IDLE/READY */ + if (V24_FLAGMASK_IS_OFF(ts->v24_flags, OSMO_V110_TA_C_108)) + v110_ta_fsm_state_chg(V110_TA_ST_IDLE_READY); + break; + case V110_TA_EV_SYNC_IND: + /* 7.1.2.3 When the receiver recognizes the frame synchronization pattern, it causes the S- + * and X-bits in the transmitted frames to be turned ON (provided that circuit 108 is ON). */ + OSMO_ASSERT(V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_108)); + ts->tx.s_bits = V110_SX_BIT_ON; + ts->tx.x_bits = V110_SX_BIT_ON; + break; + case V110_TA_EV_RX_FRAME_IND: + { + const struct osmo_v110_decoded_frame *df = data; + unsigned int v24_flags = ta->state.v24_flags; + + /* 7.1.2.4 When the receiver recognizes that the status of bits S and X are ON */ + if (v110_df_s_bits_are(df, V110_SX_BIT_ON) && + v110_df_x_bits_are(df, V110_SX_BIT_ON)) { + /* ... it will perform the following functions: */ + /* a) Turn ON circuit 107 toward the DTE and stop timer T1 */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_107); + osmo_timer_del(&fi->timer); + /* b) Then, circuit 103 may be connected to the data bits in the frame; however, the + * DTE must maintain a binary 1 condition on circuit 103 until circuit 106 is turned + * ON in the next portion of the sequence. */ + /* c) Turn ON circuit 109 and connect the data bits to circuit 104. */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_109); + ts->rx.d_bit_mode = V110_TA_DBIT_M_FORWARD; + /* d) After an interval of N bits (see 6.3), it will turn ON circuit 106. */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_106); + ts->tx.d_bit_mode = V110_TA_DBIT_M_FORWARD; + v110_ta_flags_update(ta, v24_flags); + /* Circuit 106 transitioning from OFF to ON will cause the transmitted data to + * transition from binary 1 to the data mode. */ + v110_ta_fsm_state_chg(V110_TA_ST_DATA_TRANSFER); + } + + v110_ta_handle_frame(ta, df); + break; + } + case V110_TA_EV_TX_FRAME_RTS: + v110_ta_build_frame(ta, (struct osmo_v110_decoded_frame *)data); + break; + case V110_TA_EV_TIMEOUT: + v110_ta_fsm_state_chg(V110_TA_ST_IDLE_READY); + break; + default: + OSMO_ASSERT(0); + } +} + +/* ITU-T V.110 Section 7.1.3 */ +static void v110_ta_fsm_data_transfer_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + unsigned int v24_flags = ta->state.v24_flags; + + /* 7.1.3.1 While in the data transfer state, the following circuit conditions exist: + * a): 105, 107, 108, and 109 are in the ON condition */ + /* XXX: OSMO_ASSERT(V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_105)); */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_107); + /* XXX: OSMO_ASSERT(V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_108)); */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_109); + /* b) data is being transmitted on circuit 103 and received on circuit 104 */ + ts->rx.d_bit_mode = V110_TA_DBIT_M_FORWARD; + ts->tx.d_bit_mode = V110_TA_DBIT_M_FORWARD; + /* c) circuits 133 (when implemented) and 106 are in the ON condition unless local out-of-band + * flow control is being used, either or both circuits may be in the ON or the OFF condition. */ + if (!ta->cfg->flow_ctrl.end_to_end) { + /* XXX: OSMO_ASSERT(V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_133)); */ + V24_FLAGMASK_SET_ON(v24_flags, OSMO_V110_TA_C_106); + } + v110_ta_flags_update(ta, v24_flags); + + /* 7.1.3.2 While in the data transfer state, the following status bit conditions exist: */ + /* a) status bits S in both directions are in the ON condition; */ + ts->tx.s_bits = V110_SX_BIT_ON; + /* b) status bits X in both directions are in the ON condition unless end-to-end flow control + * is being used, in which case status bit X in either or both directions may be in the + * ON or the OFF condition. */ + if (!ta->cfg->flow_ctrl.end_to_end) + ts->tx.x_bits = V110_SX_BIT_ON; +} + +/* ITU-T V.110 Section 7.1.3 */ +static void v110_ta_fsm_data_transfer(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + + /* 7.1.3.3 While in the data transfer state: */ + /* a) the S status bits shall *not* be mapped to/from the interchange circuits */ + /* b) the X status bits shall *not* be mapped according to Table 3, + * unless end-to-end flow control is implemented */ + /* TODO: if (ta->cfg->flow_ctrl.end_to_end) { ... } */ + + switch (event) { + case V110_TA_EV_V24_STATUS_CHG: + /* 7.1.4.1 At the completion of the data transfer phase, the local DTE will indicate a + * disconnect request by turning OFF circuit 108 */ + if (V24_FLAGMASK_IS_ON(ts->v24_flags, OSMO_V110_TA_C_108)) + break; + v110_ta_fsm_state_chg(V110_TA_ST_DISCONNECTING); + break; + case V110_TA_EV_DESYNC_IND: + v110_ta_fsm_state_chg(V110_TA_ST_RESYNCING); + break; + case V110_TA_EV_TX_FRAME_RTS: + v110_ta_build_frame(ta, (struct osmo_v110_decoded_frame *)data); + break; + case V110_TA_EV_RX_FRAME_IND: + { + const struct osmo_v110_decoded_frame *df = data; + unsigned int v24_flags = ta->state.v24_flags; + + /* 7.1.4.2 ... this TA will recognize the transition of the status bits S from + * ON to OFF and the data bits from data to binary 0 as a disconnect request */ + if (v110_df_s_bits_are(df, V110_SX_BIT_OFF) && v110_df_d_bits_are(df, 0)) { + /* ... and it will turn OFF circuits 107 and 109. */ + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_107); + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_109); + v110_ta_flags_update(ta, v24_flags); + /* DTE should respond by turning OFF circuit 108 */ + break; /* XXX: shall we forward D-bits to DTE anyway? */ + } + + v110_ta_handle_frame(ta, df); + break; + } + default: + OSMO_ASSERT(0); + } +} + +/* ITU-T V.110 Section 7.1.4 */ +static void v110_ta_fsm_disconnect_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + unsigned int v24_flags = ta->state.v24_flags; + + /* 7.1.4.1 At the completion of the data transfer phase, the local DTE will indicate a + * disconnect request by turning OFF circuit 108. This will cause the following to occur: */ + /* a) the status bits S in the frame toward ISDN will turn OFF, status bits X are kept ON */ + ts->tx.s_bits = V110_SX_BIT_OFF; + /* b) circuit 106 will be turned OFF */ + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_106); + v110_ta_flags_update(ta, v24_flags); + /* c) the data bits in the frame will be set to binary 0. */ + ts->tx.d_bit_mode = V110_TA_DBIT_M_ALL_ZERO; + + /* To guard against the failure of the remote TA to respond to the disconnect request, + * the local TA may start a timer T2 (suggested value 5 s) which is stopped by the + * reception or transmission of any D-channel clearing message (DISCONNECT, RELEASE, + * RELEASE COMPLETE). */ + OSMO_ASSERT(fi->T == OSMO_V110_TA_TIMER_T2); +} + +/* ITU-T V.110 Section 7.1.4 */ +static void v110_ta_fsm_disconnect(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + + switch (event) { + case V110_TA_EV_V24_STATUS_CHG: + break; /* nothing to do */ + case V110_TA_EV_TX_FRAME_RTS: + v110_ta_build_frame(ta, (struct osmo_v110_decoded_frame *)data); + break; + case V110_TA_EV_RX_FRAME_IND: + { + const struct osmo_v110_decoded_frame *df = data; + + /* 7.1.4.3 The TA at the station that originated the disconnect request will + * recognize reception of S = OFF or the loss of framing signals as a disconnect + * acknowledgement and turn OFF circuits 107 and 109. */ + if (v110_df_s_bits_are(df, V110_SX_BIT_OFF)) { + /* circuits 107 and 109 set to off in .onenter() */ + v110_ta_fsm_state_chg(V110_TA_ST_IDLE_READY); + } + + v110_ta_handle_frame(ta, df); + break; + } + case V110_TA_EV_DESYNC_IND: + case V110_TA_EV_TIMEOUT: + /* circuits 107 and 109 set to off in .onenter() */ + v110_ta_fsm_state_chg(V110_TA_ST_IDLE_READY); + break; + default: + OSMO_ASSERT(0); + } +} + +/* ITU-T V.110 Section 7.1.5 */ +static void v110_ta_fsm_resyncing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + + /* 7.1.5 In the event of loss of frame synchronization, the (local) TA should + * attempt to resynchronize as follows: */ + /* a) Place circuit 104 in binary 1 condition (passes from the data mode) */ + ts->rx.d_bit_mode = V110_TA_DBIT_M_ALL_ONE; + /* b) Turn OFF status bit X in the transmitted frame */ + ts->tx.x_bits = V110_SX_BIT_OFF; + + /* guard timeout, see 7.1.5 e) */ + OSMO_ASSERT(fi->T == OSMO_V110_TA_TIMER_X1); +} + +/* ITU-T V.110 Section 7.1.5 */ +static void v110_ta_fsm_resyncing(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + struct osmo_v110_ta *ta = (struct osmo_v110_ta *)fi->priv; + struct v110_ta_state *ts = &ta->state; + unsigned int v24_flags = ta->state.v24_flags; + + switch (event) { + case V110_TA_EV_V24_STATUS_CHG: + break; /* TODO: handle circuit 108 being set to OFF? */ + case V110_TA_EV_TX_FRAME_RTS: + v110_ta_build_frame(ta, (struct osmo_v110_decoded_frame *)data); + break; + case V110_TA_EV_SYNC_IND: + /* f) If resynchronization is achieved, the local TA should turn ON status bit X */ + ts->tx.x_bits = V110_SX_BIT_ON; + v110_ta_fsm_state_chg(V110_TA_ST_DATA_TRANSFER); + break; + case V110_TA_EV_TIMEOUT: + /* e) If after an interval of X1 seconds the local TA cannot attain synchronization, + * it should send a disconnect request by turning OFF all of the status bits for several + * (at least three) frames with data bits set to binary 0 and then disconnect by turning + * OFF circuit 107 and transferring to the disconnected mode as discussed in 7.1.4.2. */ + ts->tx.s_bits = V110_SX_BIT_OFF; + ts->tx.x_bits = V110_SX_BIT_OFF; + ts->tx.d_bit_mode = V110_TA_DBIT_M_ALL_ZERO; + /* TODO: actually Tx those frames (delay state transition) */ + V24_FLAGMASK_SET_OFF(v24_flags, OSMO_V110_TA_C_107); + v110_ta_flags_update(ta, v24_flags); + v110_ta_fsm_state_chg(V110_TA_ST_DISCONNECTING); + break; + default: + OSMO_ASSERT(0); + } +} + +static int v110_ta_timer_cb(struct osmo_fsm_inst *fi) +{ + osmo_fsm_inst_dispatch(fi, V110_TA_EV_TIMEOUT, NULL); + return 0; +} + +static const struct osmo_fsm_state v110_ta_states = { + V110_TA_ST_IDLE_READY = { + .name = "IDLE_READY", + .in_event_mask = S(V110_TA_EV_V24_STATUS_CHG) + | S(V110_TA_EV_TX_FRAME_RTS) + | S(V110_TA_EV_RX_FRAME_IND), + .out_state_mask = S(V110_TA_ST_IDLE_READY) + | S(V110_TA_ST_CON_TA_TO_LINE), + .action = &v110_ta_fsm_idle_ready, + .onenter = &v110_ta_fsm_idle_ready_onenter, + }, + V110_TA_ST_CON_TA_TO_LINE = { + .name = "CONNECT_TA_TO_LINE", + .in_event_mask = S(V110_TA_EV_V24_STATUS_CHG) + | S(V110_TA_EV_TIMEOUT) + | S(V110_TA_EV_SYNC_IND) + | S(V110_TA_EV_TX_FRAME_RTS) + | S(V110_TA_EV_RX_FRAME_IND), + .out_state_mask = S(V110_TA_ST_DATA_TRANSFER) + | S(V110_TA_ST_IDLE_READY), + .action = &v110_ta_fsm_connect_ta_to_line, + .onenter = &v110_ta_fsm_connect_ta_to_line_onenter, + }, + V110_TA_ST_DATA_TRANSFER = { + .name = "DATA_TRANSFER", + .in_event_mask = S(V110_TA_EV_V24_STATUS_CHG) + | S(V110_TA_EV_DESYNC_IND) + | S(V110_TA_EV_TX_FRAME_RTS) + | S(V110_TA_EV_RX_FRAME_IND), + .out_state_mask = S(V110_TA_ST_RESYNCING) + | S(V110_TA_ST_DISCONNECTING), + .action = &v110_ta_fsm_data_transfer, + .onenter = &v110_ta_fsm_data_transfer_onenter, + }, + V110_TA_ST_DISCONNECTING = { + .name = "DISCONNECTING", + .in_event_mask = S(V110_TA_EV_V24_STATUS_CHG) + | S(V110_TA_EV_TIMEOUT) + | S(V110_TA_EV_TX_FRAME_RTS) + | S(V110_TA_EV_RX_FRAME_IND) + | S(V110_TA_EV_DESYNC_IND), + .out_state_mask = S(V110_TA_ST_IDLE_READY), + .action = &v110_ta_fsm_disconnect, + .onenter = &v110_ta_fsm_disconnect_onenter, + }, + V110_TA_ST_RESYNCING = { + .name = "RESYNCING", + .in_event_mask = S(V110_TA_EV_V24_STATUS_CHG) + | S(V110_TA_EV_TIMEOUT) + | S(V110_TA_EV_TX_FRAME_RTS) + | S(V110_TA_EV_SYNC_IND), + .out_state_mask = S(V110_TA_ST_IDLE_READY) + | S(V110_TA_ST_DATA_TRANSFER), + .action = &v110_ta_fsm_resyncing, + .onenter = &v110_ta_fsm_resyncing_onenter, + }, +}; + +static struct osmo_fsm osmo_v110_ta_fsm = { + .name = "V110-TA", + .states = v110_ta_states, + .num_states = ARRAY_SIZE(v110_ta_states), + .timer_cb = v110_ta_timer_cb, + .log_subsys = DLGLOBAL, + .event_names = v110_ta_fsm_event_names, +}; + +static __attribute__((constructor)) void on_dso_load(void) +{ + OSMO_ASSERT(osmo_fsm_register(&osmo_v110_ta_fsm) == 0); +} + +/*! Allocate a V.110 TA (Terminal Adapter) instance. + * \paramin ctx parent talloc context. + * \paramin name name of the TA instance. + * \paramin cfg initial configuration of the TA instance. + * \returns pointer to allocated TA instance; NULL on error. */ +struct osmo_v110_ta *osmo_v110_ta_alloc(void *ctx, const char *name, + const struct osmo_v110_ta_cfg *cfg) +{ + struct osmo_v110_ta *ta; + + OSMO_ASSERT(cfg != NULL); + OSMO_ASSERT(cfg->rx_cb != NULL); + OSMO_ASSERT(cfg->tx_cb != NULL); + + /* local (TE-TA) flow control is not implemented */ + if (cfg->flow_ctrl.local != OSMO_V110_LOCAL_FLOW_CTRL_NONE) { + LOGP(DLGLOBAL, LOGL_ERROR, "Local (TE-TA) flow control is not implemented\n"); + return NULL; + } + + ta = talloc_zero(ctx, struct osmo_v110_ta); + if (ta == NULL) + return NULL; + + ta->name = talloc_strdup(ta, name); + ta->cfg = talloc_memdup(ta, cfg, sizeof(*cfg)); + if (ta->name == NULL || ta->cfg == NULL) + goto exit_free; + + ta->Tdefs = talloc_memdup(ta, v110_ta_tdef, sizeof(v110_ta_tdef)); + if (ta->Tdefs == NULL) + goto exit_free; + osmo_tdefs_reset(ta->Tdefs); /* apply default values */ + + ta->fi = osmo_fsm_inst_alloc(&osmo_v110_ta_fsm, ta, ta, LOGL_DEBUG, name); + if (ta->fi == NULL) + goto exit_free; + + /* perform a loop transition to init the internal state */ + osmo_fsm_inst_state_chg(ta->fi, V110_TA_ST_IDLE_READY, 0, 0); + + return ta; + +exit_free: + if (ta->fi != NULL) + osmo_fsm_inst_free(ta->fi); + talloc_free(ta); + return NULL; +} + +/*! Release memory taken by the given V.110 TA instance. + * \paramin ta TA instance to be free()d. */ +void osmo_v110_ta_free(struct osmo_v110_ta *ta) +{ + if (ta == NULL) + return; + if (ta->fi != NULL) + osmo_fsm_inst_free(ta->fi); + talloc_free(ta); /* also free()s name and cfg */ +} + +/*! Configure a timer of the given V.110 TA instance. + * \paramin ta TA instance to be configured. + * \paramin timer a timer to be configured. + * \paramin val_ms the new timeout value to set (in milliseconds). + * \returns 0 in case of success; negative on error. */ +int osmo_v110_ta_set_timer_val_ms(struct osmo_v110_ta *ta, + enum osmo_v110_ta_timer timer, + unsigned long val_ms) +{ + return osmo_tdef_set(ta->Tdefs, (int)timer, val_ms, OSMO_TDEF_MS); +} + +/*! Feed a decoded V.110 frame into the given TA instance. + * + * This function, like its _out counterpart, is intended to be used by the lower layers + * receiving V.110 frames over some medium. The caller of this function is responsible + * for finding the synchronization pattern (if needed), aligning to the frame boundaries, + * and decoding frames using osmo_v110_decode_frame() or osmo_csd_*_decode_frame(). + * + * Bits E1/E2/E3 are expected to be set by the caller (if not being transmitted + * over the medium) in accordance with the configured synchronous user rate. + * + * Bits D1..D48 are passed to the bit rate adaption function RA1. The resulting output + * is then passed to the upper layer (application) via the configured .rx_cb(). Though, + * in certain states of the TA's FSM, bits D1..D48 are ignored and the upper layer + * gets a sequence of binary '0' or '1'. + * + * \paramin ta TA instance to feed the given frame into. + * \paramin in pointer to a decoded V.110 frame. + * \returns 0 in case of success; negative on error. */ +int osmo_v110_ta_frame_in(struct osmo_v110_ta *ta, const struct osmo_v110_decoded_frame *in) +{ + return osmo_fsm_inst_dispatch(ta->fi, V110_TA_EV_RX_FRAME_IND, (void *)in); +} + +/*! Pull a decoded V.110 frame out of the given TA instance. + * + * This function, like its _in counterpart, is intended to be used by the lower layers + * transmitting V.110 frames over some medium. The caller of this function is responsible + * for encoding the output frame using osmo_v110_encode_frame() or osmo_csd_*_encode_frame(). + * + * Bits E1/E2/E3 are set in accordance with the configured synchronous user rate. + * Bits E4/E5/E6/E7 are unconditionally set to binary '1'. + * + * Bits D1..D48 are set depending on the state of TA's FSM: + * + * - In data transfer mode, the user bits are obtained from the upper layer (application) + * via the configured .tx_cb(), and then passed to the bit rate adaption function RA1, + * which generates bits D1..D48. + * - In other modes, bits D1..D48 are all set to binary '0' or '1'. + * + * \paramin ta TA instance to pull a frame from. + * \paramout out where to store a decoded V.110 frame. + * \returns 0 in case of success; negative on error. */ +int osmo_v110_ta_frame_out(struct osmo_v110_ta *ta, struct osmo_v110_decoded_frame *out) +{ + return osmo_fsm_inst_dispatch(ta->fi, V110_TA_EV_TX_FRAME_RTS, (void *)out); +} + +/*! Indicate a synchronization establishment event. + * + * This function is intended to be called when the lower layer + * achieves synchronization to the frame clock. + * + * \paramin ta TA instance to indicate the event to. + * \returns 0 in case of success; negative on error. */ +int osmo_v110_ta_sync_ind(struct osmo_v110_ta *ta) +{ + return osmo_fsm_inst_dispatch(ta->fi, V110_TA_EV_SYNC_IND, NULL); +} + +/*! Indicate a synchronization loss event. + * + * This function is intended to be called when the lower layer + * experiences a loss of synchronization with the frame clock. + * + * \paramin ta TA instance to indicate the event to. + * \returns 0 in case of success; negative on error. */ +int osmo_v110_ta_desync_ind(struct osmo_v110_ta *ta) +{ + return osmo_fsm_inst_dispatch(ta->fi, V110_TA_EV_DESYNC_IND, NULL); +} + +/*! Get the V.24 status bit-mask of the given TA instance. + * \paramin ta TA instance to get the circuit bit-mask. + * \returns bitmask of OSMO_V110_TA_C_*. */ +unsigned int osmo_v110_ta_get_status(const struct osmo_v110_ta *ta) +{ + return ta->state.v24_flags; +} + +/*! Set the V.24 status bit-mask of the given TA instance. + * \paramin ta TA instance to update the circuit state. + * \paramin status bit-mask of OSMO_V110_TA_C_*. + * \returns 0 on success; negative on error. */ +static int v110_ta_set_status(struct osmo_v110_ta *ta, unsigned int status) +{ + const unsigned int old_status = ta->state.v24_flags; + int rc = 0; + + ta->state.v24_flags = status; + if (status != old_status) + rc = osmo_fsm_inst_dispatch(ta->fi, V110_TA_EV_V24_STATUS_CHG, NULL); + + return rc; +} + +/*! Get state of a V.24 circuit of the given TA instance. + * \paramin ta TA instance to get the circuit state. + * \paramin circuit a V.24 circuit, one of OSMO_V110_TA_C_*. + * \returns circuit state: active (true) or inactive (false). */ +bool osmo_v110_ta_get_circuit(const struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit) +{ + return V24_FLAGMASK_IS_ON(ta->state.v24_flags, circuit); +} + +/*! Activate/deactivate a V.24 circuit of the given TA instance. + * \paramin ta TA instance to update the circuit state. + * \paramin circuit a V.24 circuit, one of OSMO_V110_TA_C_* (DTE->DCE). + * \paramin active activate (true) or deactivate (false) the circuit. + * \returns 0 on success; negative on error. */ +int osmo_v110_ta_set_circuit(struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit, bool active) +{ + unsigned int status = ta->state.v24_flags; + + /* permit setting only DTE->DCE circuits */ + switch (circuit) { + case OSMO_V110_TA_C_105: + case OSMO_V110_TA_C_108: + case OSMO_V110_TA_C_133: + break; + default: + LOGPFSML(ta->fi, LOGL_ERROR, + "Setting circuit %s is not permitted (wrong direction?)\n", + osmo_v110_ta_circuit_name(circuit)); + return -EACCES; + } + + if (active) + V24_FLAGMASK_SET_ON(status, circuit); + else + V24_FLAGMASK_SET_OFF(status, circuit); + + return v110_ta_set_status(ta, status); +}
View file
libosmocore_1.9.3.tar.xz/src/pseudotalloc/pseudotalloc.c -> libosmocore_1.10.0.tar.xz/src/pseudotalloc/pseudotalloc.c
Changed
@@ -55,21 +55,21 @@ { } -char *talloc_strdup(const void *context, const char *p) +void *talloc_memdup(const void *ctx, const void *p, size_t size) { - char *ptr; - size_t len; + void *ptr; - if (!p) - return NULL; - len = strlen(p); + ptr = talloc_size(ctx, size); + if (ptr && p) + memcpy(ptr, p, size); + return ptr; +} - ptr = talloc_size(context, len+1); - if (!ptr) +char *talloc_strdup(const void *ctx, const char *p) +{ + if (!p) return NULL; - memcpy(ptr, p, len+1); - - return ptr; + return talloc_memdup(ctx, p, strlen(p) + 1); } void *talloc_pool(const void *context, size_t size)
View file
libosmocore_1.9.3.tar.xz/src/pseudotalloc/talloc.h -> libosmocore_1.10.0.tar.xz/src/pseudotalloc/talloc.h
Changed
@@ -50,7 +50,8 @@ void *talloc_named_const(const void *context, size_t size, const char *name); void *talloc_named(const void *context, size_t size, const char *fmt, ...); void talloc_set_name_const(const void *ptr, const char *name); -char *talloc_strdup(const void *t, const char *p); +void *talloc_memdup(const void *ctx, const void *p, size_t size); +char *talloc_strdup(const void *ctx, const char *p); void *talloc_pool(const void *context, size_t size); #define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name);
View file
libosmocore_1.9.3.tar.xz/src/sim/class_tables.c -> libosmocore_1.10.0.tar.xz/src/sim/class_tables.c
Changed
@@ -19,7 +19,15 @@ #include <osmocom/core/utils.h> #include <osmocom/sim/class_tables.h> -static const uint8_t iso7816_ins_tbl = { +/* Quick reminder about the "cases" as per ISO7816-3 / ETSI TS 102 221 Section 7.3.1.1 + * + * Case 1: Command Length 0, Response Length 0 + * Case 2: Command Length 0, Response Length from P3 + * Case 3: Command Length P3, Response Length 0 + * Case 4: Command Length P3, followed by 61xx for response length + GET RESPONSE + */ + +static const uint8_t iso7816_ins_tbl256 = { 0xB0 = 2, /* READ BIN */ 0xD0 = 3, /* WRITE BIN */ 0xD6 = 3, /* UPDATE BIN */ @@ -243,6 +251,7 @@ 0xE8 = 4, /* LOAD */ 0xD8 = 4, /* PUT KEY */ 0xF0 = 3, /* SET STATUS */ + 0xC0 = 2, /* GET RESPONSE */ }; static const struct osim_cla_ins_case uicc_ins_case = { @@ -377,6 +386,13 @@ 0x88 = 4, /* AUTHENTICATE */ }; +/* https://learn.microsoft.com/en-us/windows-hardware/drivers/smartcard/discovery-process */ +static const uint8_t microsoft_discovery_ins_tbl256 = { + 0xA4 = 4, /* SELECT FILE */ + 0xCA = 2, /* GET DATA */ + 0xC0 = 2, /* GET RESPONSE */ +}; + int osim_determine_apdu_case(const struct osim_cla_ins_card_profile *prof, const uint8_t *hdr) { @@ -401,5 +417,16 @@ return rc; } } + /* special handling for Microsoft who insists to use INS=0xCA in CLA=0x00 which is not + * really part of GSM SIM, ETSI UICC or 3GPP USIM specifications, but only ISO7816. Rather than adding + * it to each and every card profile, let's add the instructions listed at + * https://learn.microsoft.com/en-us/windows-hardware/drivers/smartcard/discovery-process explicitly + * here. They will only be used in case no more specific match was found in the actual profile above. */ + if (cla == 0x00) { + rc = microsoft_discovery_ins_tblins; + if (rc) + return rc; + } + return 0; }
View file
libosmocore_1.9.3.tar.xz/src/vty/Makefile.am -> libosmocore_1.10.0.tar.xz/src/vty/Makefile.am
Changed
@@ -1,7 +1,7 @@ # This is _NOT_ the library release version, it's an API version. # Please read chapter "Library interface versions" of the libtool documentation # before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html -LIBVERSION=13:0:0 +LIBVERSION=13:1:0 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) AM_CFLAGS = -Wall $(TALLOC_CFLAGS) $(PTHREAD_CFLAGS)
View file
libosmocore_1.9.3.tar.xz/src/vty/command.c -> libosmocore_1.10.0.tar.xz/src/vty/command.c
Changed
@@ -4297,7 +4297,7 @@ /* Set config filename. Called from vty.c */ void host_config_set(const char *filename) { - host.config = talloc_strdup(tall_vty_cmd_ctx, filename); + osmo_talloc_replace_string(tall_vty_cmd_ctx, &host.config, filename); } const char *host_config_file(void)
View file
libosmocore_1.9.3.tar.xz/src/vty/fsm_vty.c -> libosmocore_1.10.0.tar.xz/src/vty/fsm_vty.c
Changed
@@ -158,6 +158,44 @@ return CMD_SUCCESS; } +DEFUN(show_fsm_state_graph, show_fsm_state_graph_cmd, + "show fsm-state-graph NAME", + SHOW_STR "Generate a state transition graph (using DOT language)\n" + "FSM name\n") +{ + const struct osmo_fsm *fsm; + + fsm = osmo_fsm_find_by_name(argv0); + if (!fsm) { + vty_out(vty, "Error: FSM with name '%s' doesn't exist!%s", + argv0, VTY_NEWLINE); + return CMD_WARNING; + } + + vty_out(vty, "digraph \"%s\" {%s", fsm->name, VTY_NEWLINE); + + for (unsigned int i = 0; i < fsm->num_states; i++) { + const struct osmo_fsm_state *st = &fsm->statesi; + + vty_out(vty, "\t\"%s\"; # out_state_mask=0x%08x%s", + st->name, st->out_state_mask, VTY_NEWLINE); + + for (unsigned int j = 0; j < sizeof(st->out_state_mask) * 8; j++) { + if (~st->out_state_mask & (1 << j)) + continue; + vty_out(vty, "\t\"%s\" -> \"%s\";%s", + st->name, osmo_fsm_state_name(fsm, j), + VTY_NEWLINE); + } + + vty_out(vty, "%s", VTY_NEWLINE); + } + + vty_out(vty, "}%s", VTY_NEWLINE); + + return CMD_SUCCESS; +} + DEFUN(show_fsm_insts, show_fsm_insts_cmd, "show fsm-instances all", SH_FSMI_STR @@ -214,6 +252,7 @@ install_lib_element_ve(&show_fsm_cmd); install_lib_element_ve(&show_fsms_cmd); + install_lib_element_ve(&show_fsm_state_graph_cmd); install_lib_element_ve(&show_fsm_inst_cmd); install_lib_element_ve(&show_fsm_insts_cmd); osmo_fsm_vty_cmds_installed = true;
View file
libosmocore_1.9.3.tar.xz/src/vty/logging_vty.c -> libosmocore_1.10.0.tar.xz/src/vty/logging_vty.c
Changed
@@ -382,6 +382,10 @@ tgt->categoriescategory.enabled = 1; tgt->categoriescategory.loglevel = level; +#if !defined(EMBEDDED) + log_cache_update(category, 1, level); +#endif + RET_WITH_UNLOCK(CMD_SUCCESS); } @@ -406,6 +410,9 @@ cat->enabled = 1; cat->loglevel = level; +#if !defined(EMBEDDED) + log_cache_update(i, 1, level); +#endif } RET_WITH_UNLOCK(CMD_SUCCESS); }
View file
libosmocore_1.9.3.tar.xz/src/vty/utils.c -> libosmocore_1.10.0.tar.xz/src/vty/utils.c
Changed
@@ -415,6 +415,7 @@ if (ret < 0) goto err; OSMO_SNPRINTF_RET(ret, rem, offset, len); + (void)len; /* suppress warnings about len being set but not used */ err: strsize-1 = '\0'; return str;
View file
libosmocore_1.9.3.tar.xz/tests/Makefile.am -> libosmocore_1.10.0.tar.xz/tests/Makefile.am
Changed
@@ -15,11 +15,12 @@ gsm0808/gsm0808_test gsm0408/gsm0408_test \ gprs/gprs_test kasumi/kasumi_test gea/gea_test \ logging/logging_test codec/codec_test \ + logging/logging_gsmtap_test \ loggingrb/loggingrb_test strrb/strrb_test \ comp128/comp128_test \ bitvec/bitvec_test msgb/msgb_test bits/bitcomp_test \ bits/bitfield_test \ - tlv/tlv_test gsup/gsup_test oap/oap_test \ + tlv/tlv_test oap/oap_test \ write_queue/wqueue_test socket/socket_test \ coding/coding_test conv/conv_gsm0503_test \ abis/abis_test endian/endian_test sercomm/sercomm_test \ @@ -53,8 +54,12 @@ auth/xor2g_test \ v110/frame_test \ v110/ra1_test \ + v110/ta_test \ gsm44021/frame_csd_test \ osmo_io/osmo_io_test \ + soft_uart/soft_uart_test \ + rlp/rlp_test \ + jhash/jhash_test \ $(NULL) if ENABLE_MSGFILE @@ -83,9 +88,11 @@ if !EMBEDDED check_PROGRAMS += \ + gsup/gsup_test \ stats/stats_test \ stats/stats_vty_test \ - exec/exec_test + exec/exec_test \ + $(NULL) endif if ENABLE_GB @@ -240,6 +247,8 @@ logging_logging_vty_test_SOURCES = logging/logging_vty_test.c logging_logging_vty_test_LDADD = $(top_builddir)/src/vty/libosmovty.la $(LDADD) +logging_logging_gsmtap_test_SOURCES = logging/logging_gsmtap_test.c + vty_vty_transcript_test_SOURCES = vty/vty_transcript_test.c vty_vty_transcript_test_LDADD = $(top_builddir)/src/vty/libosmovty.la $(LDADD) @@ -368,6 +377,9 @@ v110_ra1_test_SOURCES = v110/ra1_test.c v110_ra1_test_LDADD = $(top_builddir)/src/isdn/libosmoisdn.la $(LDADD) +v110_ta_test_SOURCES = v110/ta_test.c +v110_ta_test_LDADD = $(top_builddir)/src/isdn/libosmoisdn.la $(LDADD) + gsm44021_frame_csd_test_SOURCES = gsm44021/frame_csd_test.c gsm44021_frame_csd_test_LDADD = $(top_builddir)/src/isdn/libosmoisdn.la \ $(top_builddir)/src/gsm/libosmogsm.la \ @@ -375,6 +387,12 @@ osmo_io_osmo_io_test_SOURCES = osmo_io/osmo_io_test.c +soft_uart_soft_uart_test_SOURCES = soft_uart/soft_uart_test.c + +rlp_rlp_test_SOURCES = rlp/rlp_test.c +rlp_rlp_test_LDADD = $(top_builddir)/src/gsm/libosmogsm.la $(LDADD) + +jhash_jhash_test_SOURCES = jhash/jhash_test.c # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac @@ -404,14 +422,18 @@ gsm0408/gsm0408_test.ok gsm0408/gsm0408_test.err \ gsm0808/gsm0808_test.ok gb/bssgp_fc_tests.err \ gb/bssgp_fc_tests.ok gb/bssgp_fc_tests.sh \ - gb/gprs_bssgp_test.ok gb/gprs_ns_test.ok gea/gea_test.ok \ + gb/gprs_bssgp_test.ok gea/gea_test.ok \ gb/gprs_bssgp_rim_test.ok \ gb/gprs_ns2_vty.vty gb/osmoappdesc.py gb/osmo-ns-dummy.cfg \ + gb/gprs_ns_test.ok \ + gb/gprs_ns_test.err \ gb/gprs_ns2_test.ok \ + gb/gprs_ns2_test.err \ gprs/gprs_test.ok kasumi/kasumi_test.ok \ msgfile/msgfile_test.ok msgfile/msgconfig.cfg \ logging/logging_test.ok logging/logging_test.err \ logging/logging_vty_test.vty \ + logging/logging_gsmtap_test.err \ fr/fr_test.ok loggingrb/logging_test.ok \ loggingrb/logging_test.err strrb/strrb_test.ok \ codec/codec_test.ok \ @@ -452,6 +474,7 @@ oap/oap_client_test.ok oap/oap_client_test.err \ vty/vty_transcript_test.vty \ tdef/tdef_test.ok \ + tdef/tdef_test.err \ tdef/tdef_test_range_64bit.ok \ tdef/tdef_vty_config_root_test.vty \ tdef/tdef_vty_config_subnode_test.vty \ @@ -472,18 +495,23 @@ gsm48/rest_octets_test.ok \ base64/base64_test.ok \ iuup/iuup_test.ok \ + iuup/iuup_test.err \ smscb/smscb_test.ok \ smscb/gsm0341_test.ok \ smscb/cbsp_test.ok \ v110/frame_test.ok \ v110/ra1_test.ok \ + v110/ta_test.err \ gsm44021/frame_csd_test.ok \ osmo_io/osmo_io_test.ok osmo_io/osmo_io_test.err \ + soft_uart/soft_uart_test.ok \ + rlp/rlp_test.ok \ + socket/socket_sctp_test.ok socket/socket_sctp_test.err \ + jhash/jhash_test.ok \ $(NULL) if ENABLE_LIBSCTP if ENABLE_SCTP_TESTS -EXTRA_DIST += socket/socket_sctp_test.ok socket/socket_sctp_test.err check_PROGRAMS += socket/socket_sctp_test socket_socket_sctp_test_SOURCES = socket/socket_sctp_test.c endif @@ -525,8 +553,7 @@ gea/gea_test \ >$(srcdir)/gea/gea_test.ok if ENABLE_MSGFILE - cp $(srcdir)/msgfile/msgconfig.cfg . - msgfile/msgfile_test \ + msgfile/msgfile_test $(srcdir)/msgfile/msgconfig.cfg \ >$(srcdir)/msgfile/msgfile_test.ok endif sms/sms_test \ @@ -565,6 +592,8 @@ logging/logging_test \ >$(srcdir)/logging/logging_test.ok \ 2>$(srcdir)/logging/logging_test.err + logging/logging_gsmtap_test \ + 2>&1 |grep -v "enqueueing message failed" >$(srcdir)/logging/logging_gsmtap_test.err codec/codec_test \ >$(srcdir)/codec/codec_test.ok codec/codec_ecu_fr_test \ @@ -579,8 +608,7 @@ strrb/strrb_test \ >$(srcdir)/strrb/strrb_test.ok if ENABLE_VTY - cp $(srcdir)/vty/*.cfg . - vty/vty_test \ + vty/vty_test $(srcdir)/vty \ >$(srcdir)/vty/vty_test.ok \ 2>$(srcdir)/vty/vty_test.err endif @@ -590,9 +618,11 @@ gb/gprs_bssgp_rim_test \ >$(srcdir)/gb/gprs_bssgp_rim_test.ok gb/gprs_ns_test \ - >$(srcdir)/gb/gprs_ns_test.ok + >$(srcdir)/gb/gprs_ns_test.ok \ + 2>$(srcdir)/gb/gprs_ns_test.err gb/gprs_ns2_test \ - >$(srcdir)/gb/gprs_ns2_test.ok + >$(srcdir)/gb/gprs_ns2_test.ok \ + 2>$(srcdir)/gb/gprs_ns2_test.err endif if ENABLE_UTILITIES utils/utils_test \ @@ -620,9 +650,11 @@ >$(srcdir)/timer/clk_override_test.ok tlv/tlv_test \ >$(srcdir)/tlv/tlv_test.ok +if !EMBEDDED gsup/gsup_test \ >$(srcdir)/gsup/gsup_test.ok \ 2>$(srcdir)/gsup/gsup_test.err +endif if ENABLE_CTRL fsm/fsm_test \ >$(srcdir)/fsm/fsm_test.ok \ @@ -655,7 +687,8 @@ gsm23236/gsm23236_test \ >$(srcdir)/gsm23236/gsm23236_test.ok tdef/tdef_test \ - >$(srcdir)/tdef/tdef_test.ok + >$(srcdir)/tdef/tdef_test.ok \ + 2>$(srcdir)/tdef/tdef_test.err sockaddr_str/sockaddr_str_test \ >$(srcdir)/sockaddr_str/sockaddr_str_test.ok use_count/use_count_test \ @@ -683,26 +716,35 @@ time_cc/time_cc_test \ >$(srcdir)/time_cc/time_cc_test.ok iuup/iuup_test \ - >$(srcdir)/iuup/iuup_test.ok + >$(srcdir)/iuup/iuup_test.ok \ + 2>$(srcdir)/iuup/iuup_test.err v110/frame_test \ >$(srcdir)/v110/frame_test.ok v110/ra1_test \ >$(srcdir)/v110/ra1_test.ok + v110/ta_test \ + 2>$(srcdir)/v110/ta_test.err gsm44021/frame_csd_test \ >$(srcdir)/gsm44021/frame_csd_test.ok osmo_io/osmo_io_test \ >$(srcdir)/osmo_io/osmo_io_test.ok \ 2>$(srcdir)/osmo_io/osmo_io_test.err + soft_uart/soft_uart_test \ + >$(srcdir)/soft_uart/soft_uart_test.ok + rlp/rlp_test \ + >$(srcdir)/rlp/rlp_test.ok + jhash/jhash_test \ + >$(srcdir)/jhash/jhash_test.ok check-local: atconfig $(TESTSUITE) -e /proc/cpuinfo && cat /proc/cpuinfo - $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) + $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) ENABLE_URING=$(ENABLE_URING) ENABLE_URING_TESTS=$(ENABLE_URING_TESTS) $(MAKE) $(AM_MAKEFLAGS) ext-tests installcheck-local: atconfig $(TESTSUITE) $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ - $(TESTSUITEFLAGS) + $(TESTSUITEFLAGS) ENABLE_URING=$(ENABLE_URING) ENABLE_URING_TESTS=$(ENABLE_URING_TESTS) clean-local: test ! -f '$(TESTSUITE)' || \
View file
libosmocore_1.9.3.tar.xz/tests/a5/a5_test.c -> libosmocore_1.10.0.tar.xz/tests/a5/a5_test.c
Changed
@@ -66,7 +66,7 @@ _a5_3(key, count, dlout, NULL, false); _a5_3(key, count, NULL, ulout, false); - return print_a5(3, 8, "DL", dlout, block1) & print_a5(3, 8, "UL", ulout, block2); + return print_a5(3, 8, "DL", dlout, block1) && print_a5(3, 8, "UL", ulout, block2); } static inline bool test_a54(const char * kc, uint32_t count, const char * block1, const char * block2) @@ -78,7 +78,7 @@ _a5_4(key, count, dlout, NULL, false); _a5_4(key, count, NULL, ulout, false); - return print_a5(4, 8, "DL", dlout, block1) & print_a5(4, 8, "UL", ulout, block2); + return print_a5(4, 8, "DL", dlout, block1) && print_a5(4, 8, "UL", ulout, block2); }
View file
libosmocore_1.9.3.tar.xz/tests/coding/coding_test.c -> libosmocore_1.10.0.tar.xz/tests/coding/coding_test.c
Changed
@@ -441,11 +441,11 @@ case 34: case 54: l2len - 1 &= 0x7f; - resultlen - 1 &= 0x7f; + resultlen - 1 = 0x00; break; case 40: l2len - 1 &= 0x07; - resultlen - 1 &= 0x07; + resultlen - 1 = 0x00; break; }
View file
libosmocore_1.9.3.tar.xz/tests/coding/coding_test.ok -> libosmocore_1.10.0.tar.xz/tests/coding/coding_test.ok
Changed
@@ -270,7 +270,7 @@ 7f 7f 7f 81 7f 81 81 81 81 81 81 81 81 81 7f 7f 7f 7f 7f 81 81 81 81 7f 81 81 7f 7f 7f 7f 7f 81 81 7f 7f 7f 7f 7f 7f 81 7f 7f 81 81 7f 7f 7f 81 81 7f 81 7f 7f 7f 81 81 7f 81 7f 7f 81 81 7f 81 7f 7f 81 81 7f 81 7f 7f 81 7f 7f 81 7f 81 81 7f 7f 7f 7f 7f 81 7f 81 7f 7f 7f 7f 81 81 7f 7f 81 81 7f 7f 7f 7f 81 81 7f 81 81 7f 81 81 7f 7f 81 81 7f 81 81 7f 81 81 81 81 7f 81 7f 7f 7f 81 81 7f 7f 7f 7f 81 81 81 7f 7f 7f 81 7f 81 7f 7f 7f 81 81 81 7f 81 81 81 7f 7f 7f 81 81 81 7f 81 81 7f 81 81 7f 7f 81 81 7f 81 81 81 81 81 7f 7f 7f 7f 7f 81 81 81 81 7f 7f 7f 81 81 81 7f 7f 7f 81 81 7f 81 7f 7f 7f 81 81 7f 81 81 81 7f 7f 81 7f 81 81 81 7f 81 81 81 81 81 7f 81 7f 81 81 81 81 81 7f 81 81 7f 7f 81 81 Decoded: a3 af 5f c6 36 43 44 ab d9 6d 7d 62 24 c9 d2 92 fa 27 5d 71 7a 59 a8 42 a3 af 5f c6 36 43 44 ab a3 2f -pdtch_decode: n_errors=132 n_bits_total=588 ber=0.22 +pdtch_decode: n_errors=0 n_bits_total=456 ber=0.00 Encoding: a3 af 5f c6 36 43 44 ab d9 6d 7d 62 24 c9 d2 92 fa 27 5d 71 7a 59 a8 42 a3 af 5f c6 36 43 44 ab a3 af 5f c6 36 43 44 03 U-Bits: @@ -284,7 +284,7 @@ 81 81 7f 7f 7f 81 81 7f 7f 7f 7f 7f 7f 7f 81 7f 7f 7f 7f 81 7f 81 7f 81 7f 81 81 81 81 81 81 7f 81 7f 81 81 7f 7f 7f 81 81 81 7f 81 7f 81 81 81 81 81 7f 7f 81 81 81 81 7f 7f 7f 81 7f 7f 7f 7f 81 81 7f 81 81 7f 7f 7f 81 81 7f 7f 81 81 7f 81 81 7f 7f 81 81 7f 81 81 7f 7f 7f 7f 81 7f 81 7f 7f 7f 7f 7f 81 7f 7f 7f 7f 7f 81 7f 81 81 7f 7f 81 81 81 7f 7f 81 81 81 7f 7f 7f 7f 81 7f 81 7f 7f 7f 7f 81 7f 7f 81 7f 7f 81 7f 81 7f 7f 81 7f 7f 7f 81 7f 7f 81 81 7f 81 7f 7f 81 81 81 7f 81 7f 7f 7f 7f 81 7f 81 81 81 7f 7f 7f 7f 7f 81 81 81 81 81 7f 7f 81 81 7f 7f 7f 7f 7f 81 81 7f 7f 81 7f 7f 81 81 7f 81 81 81 7f 81 7f 7f 81 81 81 81 7f 81 7f 7f 81 7f 81 7f 7f 81 81 81 81 7f 81 7f 7f 81 81 7f 7f 81 81 Decoded: a3 af 5f c6 36 43 44 ab d9 6d 7d 62 24 c9 d2 92 fa 27 5d 71 7a 59 a8 42 a3 af 5f c6 36 43 44 ab a3 af 5f c6 36 43 44 03 -pdtch_decode: n_errors=220 n_bits_total=676 ber=0.33 +pdtch_decode: n_errors=0 n_bits_total=456 ber=0.00 Encoding: a3 af 5f c6 36 43 44 ab d9 6d 7d 62 24 c9 d2 92 fa 27 5d 71 7a 59 a8 42 a3 af 5f c6 36 43 44 ab a3 af 5f c6 36 43 44 ab d9 6d 7d 62 24 c9 d2 92 fa 27 5d 71 7a 28 U-Bits: @@ -326,7 +326,7 @@ 7f 7f 81 7f 81 81 7f 7f 7f 81 7f 7f 7f 81 81 7f 81 7f 81 7f 7f 7f 7f 7f 81 7f 81 81 81 7f 81 7f 7f 7f 81 7f 7f 81 7f 7f 81 7f 7f 7f 81 7f 81 81 81 81 7f 81 7f 81 7f 7f 81 81 7f 7f 7f 7f 81 81 7f 7f 7f 7f 7f 81 81 7f 7f 7f 81 7f 7f 7f 81 81 7f 7f 7f 81 7f 7f 81 7f 81 7f 7f 7f 81 7f 7f 7f 7f 81 7f 7f 7f 7f 7f 7f 81 7f 7f 81 7f 81 7f 7f 81 7f 81 81 81 7f 81 7f 7f 81 7f 7f 81 81 7f 7f 81 7f 81 7f 7f 81 81 81 7f 81 7f 81 81 7f 81 7f 81 7f 81 7f 81 7f 7f 7f 7f 7f 7f 81 81 7f 81 7f 7f 7f 81 7f 7f 7f 7f 7f 81 7f 81 7f 81 7f 7f 7f 81 7f 81 7f 7f 81 7f 81 81 81 7f 7f 81 7f 7f 7f 81 7f 7f 7f 7f 81 81 7f 81 81 81 7f 7f 7f 81 7f 7f 7f 7f 81 81 81 7f 7f 7f 7f 81 7f 7f 81 7f 81 7f 7f 81 81 7f 7f 81 7f Decoded: 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 00 00 00 00 00 00 00 00 00 00 00 -pdtch_decode: n_errors=132 n_bits_total=588 ber=0.22 +pdtch_decode: n_errors=0 n_bits_total=456 ber=0.00 Encoding: 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 U-Bits: @@ -340,7 +340,7 @@ 81 7f 81 7f 81 81 7f 7f 7f 81 7f 81 7f 7f 81 7f 7f 7f 81 7f 7f 81 7f 7f 7f 7f 81 7f 7f 7f 7f 7f 81 81 7f 7f 7f 7f 7f 81 81 81 7f 7f 7f 7f 81 81 7f 81 7f 7f 7f 7f 7f 81 7f 7f 7f 7f 81 7f 81 81 7f 7f 7f 81 7f 81 81 7f 81 7f 7f 7f 81 7f 7f 7f 7f 81 7f 7f 7f 81 7f 7f 81 7f 7f 7f 7f 81 7f 81 7f 81 7f 7f 81 7f 81 7f 7f 7f 7f 7f 7f 7f 7f 81 81 81 7f 7f 7f 7f 81 7f 7f 7f 7f 81 7f 81 7f 7f 81 7f 7f 7f 7f 81 7f 81 7f 7f 7f 81 7f 7f 81 7f 7f 7f 81 81 7f 81 7f 7f 7f 81 7f 81 7f 7f 7f 7f 81 81 7f 81 7f 81 7f 7f 81 7f 81 7f 81 7f 81 7f 7f 7f 7f 7f 7f 81 7f 81 81 81 81 7f 7f 7f 7f 7f 7f 81 7f 7f 7f 81 81 7f 81 7f 81 7f 7f 7f 81 7f 7f 81 7f 81 81 7f 81 7f 81 7f 7f 7f 7f 81 7f 7f 7f 81 81 81 81 7f 7f 7f Decoded: 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -pdtch_decode: n_errors=220 n_bits_total=676 ber=0.33 +pdtch_decode: n_errors=0 n_bits_total=456 ber=0.00 Encoding: 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 U-Bits:
View file
libosmocore_1.9.3.tar.xz/tests/fsm/fsm_test.c -> libosmocore_1.10.0.tar.xz/tests/fsm/fsm_test.c
Changed
@@ -41,6 +41,18 @@ { 0, NULL } }; +static void test_fsm_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ + LOGPFSM(fi, "%s() prev_state=%s\n", + __func__, osmo_fsm_state_name(fi->fsm, prev_state)); +} + +static void test_fsm_onleave(struct osmo_fsm_inst *fi, uint32_t next_state) +{ + LOGPFSM(fi, "%s() next_state=%s\n", + __func__, osmo_fsm_state_name(fi->fsm, next_state)); +} + static void test_fsm_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) { switch (event) { @@ -86,17 +98,23 @@ .out_state_mask = (1 << ST_ONE), .name = "NULL", .action = test_fsm_null, + .onenter = test_fsm_onenter, + .onleave = test_fsm_onleave, }, ST_ONE= { .in_event_mask = (1 << EV_B), .out_state_mask = (1 << ST_TWO), .name = "ONE", .action= test_fsm_one, + .onenter = test_fsm_onenter, + .onleave = test_fsm_onleave, }, ST_TWO= { .in_event_mask = 0, .name = "TWO", .action = NULL, + .onenter = test_fsm_onenter, + .onleave = test_fsm_onleave, }, };
View file
libosmocore_1.9.3.tar.xz/tests/fsm/fsm_test.err -> libosmocore_1.10.0.tar.xz/tests/fsm/fsm_test.err
Changed
@@ -3,9 +3,13 @@ Test_FSM(my_id){NULL}: Received Event EV_B Test_FSM(my_id){NULL}: Event EV_B not permitted Test_FSM(my_id){NULL}: Received Event EV_A +Test_FSM(my_id){NULL}: test_fsm_onleave() next_state=ONE Test_FSM(my_id){NULL}: State change to ONE (no timeout) +Test_FSM(my_id){ONE}: test_fsm_onenter() prev_state=NULL Test_FSM(my_id){ONE}: Received Event EV_B +Test_FSM(my_id){ONE}: test_fsm_onleave() next_state=TWO Test_FSM(my_id){ONE}: State change to TWO (T2342, 1s) +Test_FSM(my_id){TWO}: test_fsm_onenter() prev_state=ONE Test_FSM(my_id){TWO}: Timeout of T2342 Timer Test_FSM(my_id){TWO}: Deallocated @@ -83,16 +87,24 @@ --- test_state_chg_keep_timer() Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (no timeout) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL +Test_FSM{ONE}: test_fsm_onleave() next_state=TWO Test_FSM{ONE}: State change to TWO (no timeout) +Test_FSM{TWO}: test_fsm_onenter() prev_state=ONE Test_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST) Test_FSM{TWO}: Freeing instance Test_FSM{TWO}: Deallocated Total time passed: 0.000000 s Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (T10, 10s) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL Total time passed: 2.000342 s +Test_FSM{ONE}: test_fsm_onleave() next_state=TWO Test_FSM{ONE}: State change to TWO (keeping T10, 7.999s remaining) +Test_FSM{TWO}: test_fsm_onenter() prev_state=ONE Total time passed: 2.000342 s Total time passed: 9.999999 s Total time passed: 10.000000 s @@ -104,14 +116,22 @@ --- test_state_chg_T() Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (T42, 23s) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL +Test_FSM{ONE}: test_fsm_onleave() next_state=TWO Test_FSM{ONE}: State change to TWO (no timeout) +Test_FSM{TWO}: test_fsm_onenter() prev_state=ONE Test_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST) Test_FSM{TWO}: Freeing instance Test_FSM{TWO}: Deallocated Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (T42, 23s) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL +Test_FSM{ONE}: test_fsm_onleave() next_state=TWO Test_FSM{ONE}: State change to TWO (no timeout) +Test_FSM{TWO}: test_fsm_onenter() prev_state=ONE Test_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST) Test_FSM{TWO}: Freeing instance Test_FSM{TWO}: Deallocated @@ -120,7 +140,9 @@ --- test_state_chg_Ts() Total time passed: 0.000000 s Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (T4242, 8s) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL Total time passed: 3.000000 s Total time passed: 5.500000 s Total time passed: 8.000000 s @@ -133,7 +155,9 @@ --- test_state_chg_Tms() Total time passed: 0.000000 s Test_FSM{NULL}: Allocated +Test_FSM{NULL}: test_fsm_onleave() next_state=ONE Test_FSM{NULL}: State change to ONE (T4242, 1337ms) +Test_FSM{ONE}: test_fsm_onenter() prev_state=NULL Total time passed: 0.500000 s Total time passed: 0.750000 s Total time passed: 1.100000 s
View file
libosmocore_1.10.0.tar.xz/tests/gb/gprs_ns2_test.err
Added
@@ -0,0 +1,139 @@ +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01001)-NSVC(none) Tx NS-BLOCK cause=O&M intervention +NSE(01001)-NSVC(none) Tx NS-ALIVE +NSE(01001)-NSVC(none) Tx NS-UNBLOCK +NSE(01001)-NSVC(none) Rx NS-UNBLOCK-ACK +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=84, first=0, mtu=119 +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01001)-NSVC(none) Tx NS-BLOCK cause=O&M intervention +NSE(01001)-NSVC(none) Tx NS-ALIVE +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) Tx NS-BLOCK cause=O&M intervention +NSE(01001)-NSVC(none) Tx NS-ALIVE +NSE(01001)-NSVC(none) Tx NS-UNBLOCK +NSE(01001)-NSVC(none) Rx NS-UNBLOCK-ACK +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=42, first=0, mtu=119 +NSE(01001) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01001)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=42, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=84, first=0, mtu=119 +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-BLOCK cause=O&M intervention +NSE(01004)-NSVC(none) Tx NS-BLOCK-ACK +NSE(01004)-NSVC(none) Rx NS-BLOCK-ACK +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-STATUS cause=NS-VC blocked +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-ALIVE-ACK +NSE(01004)-NSVC(none) Rx NS-ALIVE-ACK +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=42, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-ALIVE-ACK +NSE(01004)-NSVC(none) Rx NS-ALIVE-ACK +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=84, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-ALIVE-ACK +NSE(01004)-NSVC(none) Rx NS-ALIVE-ACK +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=126, first=0, mtu=119 +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +NSE(01004)-NSVC(none) Tx NS-UNITDATA +count_pdus(bind0) = 2 +count_pdus(bind1) = 4 +count_pdus(bind2) = 6 +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=42, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=84, first=0, mtu=119 +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE recovery, transfer=42, first=1, mtu=119 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=42, first=0, mtu=119 +NSE(01004)-NSVC(none) Tx NS-RESET cause=O&M intervention +NSE(01004)-NSVC(none) Rx NS-RESET +NSE(01004)-NSVC(none) Tx NS-RESET-ACK +NSE(01004)-NSVC(none) Tx NS-ALIVE +NSE(01004)-NSVC(none) Tx NS-UNBLOCK +NSE(01004)-NSVC(none) Rx NS-UNBLOCK +NSE(01004)-NSVC(none) Tx NS-UNBLOCK-ACK +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC recovery, transfer=84, first=0, mtu=119 +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004)-NSVC(none) Rx NS-UNITDATA +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE MTU changed, transfer=84, first=0, mtu=96 +NSE(01004) NS-STATUS.ind(bvci=00000): cause=NSE failure, transfer=0, first=0, mtu=96 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=96 +NSE(01004)-NSVC(none) NS-STATUS.ind(bvci=00000): cause=NSVC failure, transfer=0, first=0, mtu=96
View file
libosmocore_1.10.0.tar.xz/tests/gb/gprs_ns_test.err
Added
@@ -0,0 +1,147 @@ +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +Ignoring NS STATUS from 1.2.3.4:1111 for non-existing NS-VC +Ignoring NS ALIVE ACK from 1.2.3.4:1111 for non-existing NS-VC +Ignoring NS RESET ACK from 1.2.3.4:1111 for non-existing NS-VC +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4386, NSVCI=4386, cause=O&M intervention) +NSEI=4386 Tx NS RESET ACK (NSVCI=4386) +NSEI=4386 Rx NS UNBLOCK +NSVCI=4386 Rx NS RESET (NSEI=4386, NSVCI=4386, cause=O&M intervention) +NSEI=4386 Tx NS RESET ACK (NSVCI=4386) +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:3333 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4386, NSVCI=13124, cause=O&M intervention) +NSEI=4386 Tx NS RESET ACK (NSVCI=13124) +NS-VC changed NSEI (NSVCI=4386) from 4386 to 13124 +NSVCI=4386 Rx NS RESET (NSEI=13124, NSVCI=4386, cause=O&M intervention) +NSEI=13124 Tx NS RESET ACK (NSVCI=4386) +NSVCI=13124 Rx NS RESET (NSEI=4386, NSVCI=4386, cause=O&M intervention) +NS-VC changed link (NSVCI=4386) from 1.2.3.4:3333 to 1.2.3.4:4444 +NSEI=4386 Tx NS RESET ACK (NSVCI=4386) +NSVCI=4386 Rx NS RESET (NSEI=4386, NSVCI=4386, cause=O&M intervention) +NSEI=4386 Tx NS RESET ACK (NSVCI=4386) +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:1111 +NSVCI=65535(invalid) Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSEI=4096 Rx NS UNBLOCK +NSVCI=65535 Creating NS-VC with Signal weight 1, Data weight 1 +Creating NS-VC for BSS at 1.2.3.4:2222 +NSVCI=65535(invalid) Rx NS RESET (NSEI=8192, NSVCI=8193, cause=O&M intervention) +NSEI=8192 Tx NS RESET ACK (NSVCI=8193) +NSEI=8192 Rx NS UNBLOCK +NSEI=4096 RESET procedure based on API request +NSEI=4096 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NSEI=8192 RESET procedure based on API request +NSEI=8192 Tx NS RESET (NSVCI=8193, cause=O&M intervention) +NSVCI=8193 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NS-VC changed link (NSVCI=4097) from 1.2.3.4:2222 to 1.2.3.4:1111 +NSEI=8192 RESET procedure based on API request +NSEI=8192 Tx NS RESET (NSVCI=8193, cause=O&M intervention) +failed to send NS message via UDP: Operation not permitted +NSEI=8192, error resetting NS-VC +NSEI=4096 RESET procedure based on API request +NSEI=4096 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NSVCI=8193 Rx NS RESET (NSEI=8192, NSVCI=8193, cause=O&M intervention) +NSEI=8192 Tx NS RESET ACK (NSVCI=8193) +NSEI=8192 Rx NS UNBLOCK +NSVCI=4097 Rx NS RESET (NSEI=61440, NSVCI=4097, cause=O&M intervention) +NSEI=61440 Tx NS RESET ACK (NSVCI=4097) +NSVCI=4097 Rx NS RESET (NSEI=4096, NSVCI=61441, cause=O&M intervention) +Creating NS-VC 61441 replacing 4097 at 1.2.3.4:2222 +NSVCI=61441 Creating NS-VC with Signal weight 1, Data weight 1 +NSEI=4096 Tx NS RESET ACK (NSVCI=61441) +NSVCI=61441 Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NS-VC changed link (NSVCI=4097) from 1.2.3.4:2222 to 0.0.0.0:0 +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NS RESET ACK Discarding unexpected message for NS-VCI 4097 from SGSN NSEI=4096 +NSEI=4096 RESET procedure based on API request +NSEI=4096 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSVCI=4097 Rx NS RESET ACK (NSEI=61440, NSVCI=4097) +NSEI=61440 RESET procedure based on API request +NSEI=61440 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=61441) +NS-VC changed link (NSVCI=61441) from 1.2.3.4:2222 to 0.0.0.0:0 +NSVCI=61441 Rx NS RESET (NSEI=4096, NSVCI=4097, cause=O&M intervention) +NS-VC changed link (NSVCI=4097) from 1.2.3.4:2222 to 0.0.0.0:0 +NSEI=4096 Tx NS RESET ACK (NSVCI=4097) +NSEI=4096 Rx NS UNBLOCK +NSEI=4096 RESET procedure based on API request +NSEI=4096 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSEI=4096 Rx NS UNBLOCK ACK +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NS RESET ACK Discarding unexpected message for NS-VCI 4097 from SGSN NSEI=4096 +NSEI=4096 Reset timed out but RESET flag is not set +NSEI=4096 Tx NS RESET (NSVCI=4097, cause=O&M intervention) +NSVCI=4097 Rx NS RESET ACK (NSEI=4096, NSVCI=4097) +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +NSVCI=257 Creating NS-VC with Signal weight 1, Data weight 1 +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=O&M intervention) +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=257) +NSEI=256 Tx NS UNBLOCK (NSVCI=257) +NSEI=256 Rx NS UNBLOCK ACK +NSVCI=257 Rx NS RESET (NSEI=256, NSVCI=257, cause=O&M intervention) +NSEI=256 Tx NS RESET ACK (NSVCI=257) +NSVCI=257 Rx NS RESET (NSEI=61440, NSVCI=257, cause=O&M intervention) +NSEI=256 Tx NS RESET ACK (NSVCI=257) +NSVCI=257 Rx NS RESET (NSEI=256, NSVCI=61441, cause=O&M intervention) +NSEI=256 Tx NS RESET ACK (NSVCI=257) +NSVCI=257 Rx NS RESET (NSEI=256, NSVCI=257, cause=O&M intervention) +NSEI=256 Tx NS RESET ACK (NSVCI=257) +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=257) +NS RESET ACK Discarding unexpected message for NS-VCI 257 from SGSN NSEI=256 +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=O&M intervention) +NSVCI=257 Rx NS RESET ACK (NSEI=57344, NSVCI=257) +NS RESET ACK Unknown NSEI 57344 (NS-VCI=257) from 5.6.7.8:32000 +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=O&M intervention) +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=57345) +NS RESET ACK Unknown NS-VCI 57345 (SGSN NSEI=256) from 5.6.7.8:32000 +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +NSVCI=257 Creating NS-VC with Signal weight 1, Data weight 1 +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=O&M intervention) +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=257) +NSEI=256 Tx NS UNBLOCK (NSVCI=257) +NSEI=256 Rx NS UNBLOCK ACK +NSEI=256 Tns-alive expired more then 10 times, blocking NS-VC +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=PDU not compatible with protocol state) +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=257) +NSEI=256 Tx NS UNBLOCK (NSVCI=257) +NSEI=256 Rx NS UNBLOCK ACK +NSVCI=65534 Creating NS-VC with Signal weight 1, Data weight 1 +Unable to resolve NSEI 256 to NS-VC! +NSVCI=257 Creating NS-VC with Signal weight 1, Data weight 1 +NSEI=256 RESET procedure based on API request +NSEI=256 Tx NS RESET (NSVCI=257, cause=O&M intervention) +All NS-VCs for NSEI 256 are either dead or blocked! +NSVCI=257 Rx NS RESET ACK (NSEI=256, NSVCI=257) +NSEI=256 Tx NS UNBLOCK (NSVCI=257) +All NS-VCs for NSEI 256 are either dead or blocked! +NSEI=256 Rx NS UNBLOCK ACK
View file
libosmocore_1.9.3.tar.xz/tests/gsm0408/gsm0408_test.c -> libosmocore_1.10.0.tar.xz/tests/gsm0408/gsm0408_test.c
Changed
@@ -31,35 +31,79 @@ #include <osmocom/core/msgb.h> -static const uint8_t csd_9600_v110_lv = { 0x07, 0xa1, 0xb8, 0x89, 0x21, 0x15, 0x63, 0x80 }; +static const uint8_t csd_9600_v110_lv = { 0x07, 0xa1, 0x88, 0x89, 0x21, 0x15, 0x63, 0x80 }; static const struct gsm_mncc_bearer_cap bcap_csd_9600_v110 = { - .transfer = GSM48_BCAP_ITCAP_UNR_DIG_INF, - .mode = GSM48_BCAP_TMOD_CIRCUIT, - .coding = GSM48_BCAP_CODING_GSM_STD, - .radio = GSM48_BCAP_RRQ_FR_ONLY, - .speech_ver0= -1, + .transfer = GSM48_BCAP_ITCAP_UNR_DIG_INF, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_FR_ONLY, + .speech_ver0 = -1, .data = { - .rate_adaption = GSM48_BCAP_RA_V110_X30, - .sig_access = GSM48_BCAP_SA_I440_I450, - .async = 1, - .nr_stop_bits = 1, - .nr_data_bits = 8, - .user_rate = GSM48_BCAP_UR_9600, - .parity = GSM48_BCAP_PAR_NONE, - .interm_rate = GSM48_BCAP_IR_16k, - .transp = GSM48_BCAP_TR_TRANSP, - .modem_type = GSM48_BCAP_MT_NONE, + .rate_adaption = GSM48_BCAP_RA_V110_X30, + .sig_access = GSM48_BCAP_SA_I440_I450, + .async = 1, + .nr_stop_bits = 1, + .nr_data_bits = 8, + .user_rate = GSM48_BCAP_UR_9600, + .parity = GSM48_BCAP_PAR_NONE, + .interm_rate = GSM48_BCAP_IR_16k, + .transp = GSM48_BCAP_TR_TRANSP, + .modem_type = GSM48_BCAP_MT_NONE, + }, +}; + +static const uint8_t csd_4800_rlp_lv = { 0x07, 0xa1, 0x88, 0x89, 0x21, 0x14, 0x63, 0xa0 }; + +static const struct gsm_mncc_bearer_cap bcap_csd_4800_rlp = { + .transfer = GSM48_BCAP_ITCAP_UNR_DIG_INF, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_FR_ONLY, + .speech_ver0 = -1, + .data = { + .rate_adaption = GSM48_BCAP_RA_V110_X30, + .sig_access = GSM48_BCAP_SA_I440_I450, + .async = 1, + .nr_stop_bits = 1, + .nr_data_bits = 8, + .user_rate = GSM48_BCAP_UR_4800, + .parity = GSM48_BCAP_PAR_NONE, + .interm_rate = GSM48_BCAP_IR_16k, + .transp = GSM48_BCAP_TR_RLP, + .modem_type = GSM48_BCAP_MT_NONE, + }, +}; + +static const uint8_t csd_2400_v22bis_lv = { 0x07, 0xa2, 0xb8, 0x81, 0x21, 0x13, 0x43, 0x83 }; + +static const struct gsm_mncc_bearer_cap bcap_csd_2400_v22bis = { + .transfer = GSM48_BCAP_ITCAP_3k1_AUDIO, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_FR_ONLY, + .speech_ver0 = -1, + .data = { + .rate_adaption = GSM48_BCAP_RA_NONE, + .sig_access = GSM48_BCAP_SA_I440_I450, + .async = 1, + .nr_stop_bits = 1, + .nr_data_bits = 8, + .user_rate = GSM48_BCAP_UR_2400, + .parity = GSM48_BCAP_PAR_NONE, + .interm_rate = GSM48_BCAP_IR_8k, + .transp = GSM48_BCAP_TR_TRANSP, + .modem_type = GSM48_BCAP_MT_V22bis, }, }; static const uint8_t speech_all_lv = { 0x06, 0x60, 0x04, 0x02, 0x00, 0x05, 0x81 }; static const struct gsm_mncc_bearer_cap bcap_speech_all = { - .transfer = GSM48_BCAP_ITCAP_SPEECH, - .mode = GSM48_BCAP_TMOD_CIRCUIT, - .coding = GSM48_BCAP_CODING_GSM_STD, - .radio = GSM48_BCAP_RRQ_DUAL_FR, + .transfer = GSM48_BCAP_ITCAP_SPEECH, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_DUAL_FR, .speech_ver = { 4, 2, 0, 5, 1, -1, }, @@ -68,10 +112,10 @@ static const uint8_t speech_no3a_lv = { 0x01, 0xa0 }; static const struct gsm_mncc_bearer_cap bcap_speech_no3a = { - .transfer = GSM48_BCAP_ITCAP_SPEECH, - .mode = GSM48_BCAP_TMOD_CIRCUIT, - .coding = GSM48_BCAP_CODING_GSM_STD, - .radio = GSM48_BCAP_RRQ_FR_ONLY, + .transfer = GSM48_BCAP_ITCAP_SPEECH, + .mode = GSM48_BCAP_TMOD_CIRCUIT, + .coding = GSM48_BCAP_CODING_GSM_STD, + .radio = GSM48_BCAP_RRQ_FR_ONLY, .speech_ver = { 0, -1, }, @@ -86,6 +130,10 @@ static const struct bcap_test bcap_tests = { { csd_9600_v110_lv, &bcap_csd_9600_v110, "CSD 9600/V.110/transparent" }, + { csd_4800_rlp_lv, &bcap_csd_4800_rlp, "CSD 4800/RLP/non-transparent" }, + { /* XXX: this testcase is expected to fail because octet 4 is not represented in + * 'struct gsm_mncc_bearer_cap' and the encoder unconditionally hard-codes it to 0x88. */ + csd_2400_v22bis_lv, &bcap_csd_2400_v22bis, "CSD 2400/V.22bis/transparent" }, { speech_all_lv, &bcap_speech_all, "Speech, all codecs" }, { speech_no3a_lv, &bcap_speech_no3a, "Speech, without octet 3a" }, };
View file
libosmocore_1.9.3.tar.xz/tests/gsm0408/gsm0408_test.err -> libosmocore_1.10.0.tar.xz/tests/gsm0408/gsm0408_test.err
Changed
@@ -1,3 +1,6 @@ +Incorrect encoded result of CSD 2400/V.22bis/transparent: + should: 07 a2 b8 81 21 13 43 83 + is: 07 a2 88 81 21 13 43 83 Incorrect encoded result of Speech, without octet 3a: should: 01 a0 is: 02 20 80
View file
libosmocore_1.9.3.tar.xz/tests/gsm0408/gsm0408_test.ok -> libosmocore_1.10.0.tar.xz/tests/gsm0408/gsm0408_test.ok
Changed
@@ -1,4 +1,6 @@ Test `CSD 9600/V.110/transparent' passed +Test `CSD 4800/RLP/non-transparent' passed +Test `CSD 2400/V.22bis/transparent' failed Test `Speech, all codecs' passed Test `Speech, without octet 3a' failed Simple TMSI encoding test....passed
View file
libosmocore_1.9.3.tar.xz/tests/gsm0502/gsm0502_test.c -> libosmocore_1.10.0.tar.xz/tests/gsm0502/gsm0502_test.c
Changed
@@ -148,8 +148,28 @@ printf("\n"); } +static void test_gsm0502_fncmp(void) +{ + OSMO_ASSERT(gsm0502_fncmp(1337, 1337) == 0); + OSMO_ASSERT(gsm0502_fncmp(42, 1337) == -1); + OSMO_ASSERT(gsm0502_fncmp(1337, 42) == 1); + OSMO_ASSERT(gsm0502_fncmp(42, 0) == 1); + + /* 2715642 is very close to the Fn period (GSM_TDMA_HYPERFRAME) */ + OSMO_ASSERT(gsm0502_fncmp(2715642, 42) == -1); + OSMO_ASSERT(gsm0502_fncmp(42, 2715642) == 1); + OSMO_ASSERT(gsm0502_fncmp(0, 2715642) == 1); + + /* 1357824 is half of the Fn period (GSM_TDMA_HYPERFRAME) */ + OSMO_ASSERT(gsm0502_fncmp(1357820, 1357824) == -1); + OSMO_ASSERT(gsm0502_fncmp(1357820, 1357825) == -1); + OSMO_ASSERT(gsm0502_fncmp(1357824, 1357820) == 1); + OSMO_ASSERT(gsm0502_fncmp(1357825, 1357820) == 1); +} + int main(int argc, char **argv) { test_gsm0502_fn_remap(); + test_gsm0502_fncmp(); return EXIT_SUCCESS; }
View file
libosmocore_1.9.3.tar.xz/tests/gsm0808/gsm0808_test.c -> libosmocore_1.10.0.tar.xz/tests/gsm0808/gsm0808_test.c
Changed
@@ -1296,8 +1296,8 @@ rc = gsm0808_dec_cell_id_list2(&dec_cil, enc_cil, sizeof(enc_cil)); OSMO_ASSERT(rc == sizeof(enc_cil)); - OSMO_ASSERT(dec_cil.id_discr = CELL_IDENT_SAI); - OSMO_ASSERT(dec_cil.id_list_len = 1); + OSMO_ASSERT(dec_cil.id_discr == CELL_IDENT_SAI); + OSMO_ASSERT(dec_cil.id_list_len == 1); } static void test_gsm0808_enc_dec_cell_id_list_lac(void)
View file
libosmocore_1.9.3.tar.xz/tests/gsup/gsup_test.c -> libosmocore_1.10.0.tar.xz/tests/gsup/gsup_test.c
Changed
@@ -454,32 +454,32 @@ 0x51, /* GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS */ }; - static const uint8_t send_e_process_access_signalling_req = { - 0x40, /* OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST */ + static const uint8_t send_e_send_end_signal_res = { + 0x3E, /* OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT */ TEST_IMSI_IE, - /* Session ID and state (continue) */ + /* Session ID and state (end) */ 0x30, 0x04, 0xde, 0xad, 0xbe, 0xef, - 0x31, 0x01, 0x02, + 0x31, 0x01, 0x03, TEST_CLASS_INTER_MSC_IE, TEST_SOURCE_NAME_IE, TEST_DESTINATION_NAME_IE, - TEST_AN_APDU_IE, /* (Handover Detect) */ + TEST_AN_APDU_IE, /* (Handover Complete) */ }; - static const uint8_t send_e_send_end_signal_res = { - 0x3E, /* OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT */ + static const uint8_t send_e_process_access_signalling_req = { + 0x40, /* OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST */ TEST_IMSI_IE, - /* Session ID and state (end) */ + /* Session ID and state (continue) */ 0x30, 0x04, 0xde, 0xad, 0xbe, 0xef, - 0x31, 0x01, 0x03, + 0x31, 0x01, 0x02, TEST_CLASS_INTER_MSC_IE, TEST_SOURCE_NAME_IE, TEST_DESTINATION_NAME_IE, - TEST_AN_APDU_IE, /* (Handover Complete) */ + TEST_AN_APDU_IE, /* (Handover Detect) */ }; static const uint8_t send_e_forward_access_signalling_req = {
View file
libosmocore_1.9.3.tar.xz/tests/gsup/gsup_test.err -> libosmocore_1.10.0.tar.xz/tests/gsup/gsup_test.err
Changed
@@ -164,7 +164,7 @@ message 2: tested 21248 modifications, 2577 parse failures message 3: tested 2816 modifications, 510 parse failures message 4: tested 3584 modifications, 770 parse failures - message 5: tested 20736 modifications, 4025 parse failures + message 5: tested 20736 modifications, 4517 parse failures message 6: tested 3584 modifications, 771 parse failures message 7: tested 3584 modifications, 770 parse failures message 8: tested 2816 modifications, 510 parse failures
View file
libosmocore_1.9.3.tar.xz/tests/it_q/it_q_test.c -> libosmocore_1.10.0.tar.xz/tests/it_q/it_q_test.c
Changed
@@ -68,6 +68,44 @@ osmo_it_q_destroy(q1); } +static void tc_enqueue_dequeue(void) +{ + const unsigned int qlen = 12; + struct it_q_test1 *item; + struct osmo_it_q *q1; + int rc; + + ENTER_TC; + + printf("allocating q1\n"); + q1 = osmo_it_q_alloc(OTC_GLOBAL, "q1", 12, NULL, NULL); + OSMO_ASSERT(q1); + + printf("try dequeueing from an empty queue\n"); + osmo_it_q_dequeue(q1, &item, list); + OSMO_ASSERT(item == NULL); + + printf("adding queue entries up to the limit\n"); + for (unsigned int i = 0; i < qlen; i++) { + item = talloc_zero(OTC_GLOBAL, struct it_q_test1); + rc = osmo_it_q_enqueue(q1, item, list); + OSMO_ASSERT(rc == 0); + } + + printf("removing queue entries up to the limit\n"); + for (unsigned int i = 0; i < qlen; i++) { + osmo_it_q_dequeue(q1, &item, list); + OSMO_ASSERT(item != NULL); + talloc_free(item); + } + + printf("try dequeueing from an empty queue\n"); + osmo_it_q_dequeue(q1, &item, list); + OSMO_ASSERT(item == NULL); + + osmo_it_q_destroy(q1); +} + static int g_read_cb_count; static void q_read_cb(struct osmo_it_q *q, struct llist_head *item) @@ -115,6 +153,7 @@ { tc_alloc(); tc_queue_length(); + tc_enqueue_dequeue(); tc_eventfd(); return 0; }
View file
libosmocore_1.9.3.tar.xz/tests/it_q/it_q_test.ok -> libosmocore_1.10.0.tar.xz/tests/it_q/it_q_test.ok
Changed
@@ -9,6 +9,13 @@ adding queue entries up to the limit attempting to add more than the limit +== Entering test case tc_enqueue_dequeue +allocating q1 +try dequeueing from an empty queue +adding queue entries up to the limit +removing queue entries up to the limit +try dequeueing from an empty queue + == Entering test case tc_eventfd allocating q1 adding 30 queue entries up to the limit
View file
libosmocore_1.9.3.tar.xz/tests/iuup/iuup_test.c -> libosmocore_1.10.0.tar.xz/tests/iuup/iuup_test.c
Changed
@@ -26,7 +26,6 @@ {.used = 1, .id = 2, .IPTI = 1, .subflow_sizes = {0, 0, 0} }, }, /* .delivery_err_sdu = All set to 0 (YES) by default, */ - .IPTIs_present = true, .t_init = { .t_ms = IUUP_TIMER_INIT_T_DEFAULT, .n_max = IUUP_TIMER_INIT_N_DEFAULT }, .t_ta = { .t_ms = IUUP_TIMER_TA_T_DEFAULT, .n_max = IUUP_TIMER_TA_N_DEFAULT }, .t_rc = { .t_ms = IUUP_TIMER_RC_T_DEFAULT, .n_max = IUUP_TIMER_RC_N_DEFAULT }, @@ -727,14 +726,18 @@ rnp = osmo_iuup_rnl_prim_alloc(iuup_test_ctx, OSMO_IUUP_RNL_CONFIG, PRIM_OP_REQUEST, IUUP_MSGB_SIZE); rnp->u.config = def_configure_req; rnp->u.config.active = false; - OSMO_ASSERT((rc = osmo_iuup_rnl_prim_down(iui, rnp)) == 0); + + rc = osmo_iuup_rnl_prim_down(iui, rnp); + OSMO_ASSERT(rc == 0); /* Send Init: */ tnp = osmo_iuup_tnl_prim_alloc(iuup_test_ctx, OSMO_IUUP_TNL_UNITDATA, PRIM_OP_INDICATION, IUUP_MSGB_SIZE); tnp->oph.msg->l2h = msgb_put(tnp->oph.msg, sizeof(iuup_init)); hdr14 = (struct iuup_pdutype14_hdr *)msgb_l2(tnp->oph.msg); memcpy(hdr14, iuup_init, sizeof(iuup_init)); - OSMO_ASSERT((rc = osmo_iuup_tnl_prim_up(iui, tnp)) == 0); + + rc = osmo_iuup_tnl_prim_up(iui, tnp); + OSMO_ASSERT(rc == 0); osmo_iuup_instance_free(iui); }
View file
libosmocore_1.10.0.tar.xz/tests/iuup/iuup_test.err
Added
@@ -0,0 +1,55 @@ +DLIUUP IuUP(test_tinit_timeout_retrans){NULL}: Allocated +DLIUUP IuUP(test_tinit_timeout_retrans){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_tinit_timeout_retrans){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_tinit_timeout_retrans){Initialisation}: Timeout of T1 +DLIUUP IuUP(test_tinit_timeout_retrans){Initialisation}: Timeout of T1 +DLIUUP IuUP(test_tinit_timeout_retrans){Initialisation}: Timeout of T1 +DLIUUP IuUP(test_tinit_timeout_retrans){Initialisation}: Timeout of T1 +DLIUUP IuUP(test_tinit_timeout_retrans){Initialisation}: Deallocated +DLIUUP IuUP(test_init_nack_retrans){NULL}: Allocated +DLIUUP IuUP(test_init_nack_retrans){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_init_nack_retrans){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Received Event INIT_NACK +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Rx Initialization NACK N=0/3 +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Received Event INIT_NACK +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Rx Initialization NACK N=1/3 +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Received Event INIT_NACK +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Rx Initialization NACK N=2/3 +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Received Event INIT_NACK +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Rx Initialization NACK N=3/3 +DLIUUP IuUP(test_init_nack_retrans){Initialisation}: Deallocated +DLIUUP IuUP(test_init_ack){NULL}: Allocated +DLIUUP IuUP(test_init_ack){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_init_ack){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_init_ack){Initialisation}: Received Event LAST_INIT_ACK +DLIUUP IuUP(test_init_ack){Initialisation}: state_chg to SMpSDU_Data_Transfer_Ready +DLIUUP IuUP(test_init_ack){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-ind +DLIUUP IuUP(test_init_ack){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-req +DLIUUP IuUP(test_init_ack){SMpSDU_Data_Transfer_Ready}: Deallocated +DLIUUP IuUP(test_passive_init){NULL}: Allocated +DLIUUP IuUP(test_passive_init){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_passive_init){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_passive_init){Initialisation}: Received Event INIT +DLIUUP IuUP(test_passive_init){Initialisation}: Tx Initialization ACK +DLIUUP IuUP(test_passive_init){Initialisation}: state_chg to SMpSDU_Data_Transfer_Ready +DLIUUP IuUP(test_passive_init){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-ind +DLIUUP IuUP(test_passive_init){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-req +DLIUUP IuUP(test_passive_init){SMpSDU_Data_Transfer_Ready}: Deallocated +DLIUUP IuUP(test_passive_init_retrans){NULL}: Allocated +DLIUUP IuUP(test_passive_init_retrans){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_passive_init_retrans){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_passive_init_retrans){Initialisation}: Received Event INIT +DLIUUP IuUP(test_passive_init_retrans){Initialisation}: Tx Initialization ACK +DLIUUP IuUP(test_passive_init_retrans){Initialisation}: state_chg to SMpSDU_Data_Transfer_Ready +DLIUUP IuUP(test_passive_init_retrans){SMpSDU_Data_Transfer_Ready}: Received Event INIT +DLIUUP IuUP(test_passive_init_retrans){SMpSDU_Data_Transfer_Ready}: Tx Initialization ACK +DLIUUP IuUP(test_passive_init_retrans){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-ind +DLIUUP IuUP(test_passive_init_retrans){SMpSDU_Data_Transfer_Ready}: Received Event IuUP-DATA-req +DLIUUP IuUP(test_passive_init_retrans){SMpSDU_Data_Transfer_Ready}: Deallocated +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){NULL}: Allocated +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){NULL}: Received Event IuUP-CONFIG-req +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){NULL}: state_chg to Initialisation +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){Initialisation}: Received Event INIT +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){Initialisation}: Tx Initialization ACK +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){Initialisation}: state_chg to SMpSDU_Data_Transfer_Ready +DLIUUP IuUP(test_decode_passive_init_2_rfci_no_iptis){SMpSDU_Data_Transfer_Ready}: Deallocated
View file
libosmocore_1.10.0.tar.xz/tests/jhash
Added
+(directory)
View file
libosmocore_1.10.0.tar.xz/tests/jhash/jhash_test.c
Added
@@ -0,0 +1,56 @@ +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/hashtable.h> +#include <osmocom/core/jhash.h> + +struct item { + const char blob32; + struct hlist_node node; +}; + +struct item items = { + { "blob one", }, + { "blob two and five are the same", }, + { "third blob", }, + { "fourth blob", }, + { "blob two and five are the same", }, +}; + +uint32_t item_hash(const struct item *item) +{ + return osmo_jhash(item->blob, strlen(item->blob), 0); +} + +int main(void) +{ + int i; + struct item *item; + + DECLARE_HASHTABLE(haystack, 5); + hash_init(haystack); + + printf("add:\n"); + for (i = 0; i < ARRAY_SIZE(items); i++) { + uint32_t hash; + item = &itemsi; + hash_add(haystack, &item->node, hash = item_hash(item)); + printf("- adding items%d#%x = %s\n", i, hash, item->blob); + } + + printf("list:\n"); + hash_for_each (haystack, i, item, node) + printf("- %s %d\n", item->blob, (int)(item - items)); + + printf("find:\n"); + for (i = 0; i < ARRAY_SIZE(items); i++) { + uint32_t hash; + struct item *needle = &itemsi; + hash = item_hash(needle); + printf("- looking up items%d#%x = %s\n", i, hash, needle->blob); + hash_for_each_possible (haystack, item, node, hash) + printf(" - %s items%d\n", + (item == needle) ? "found" : "not", + (int)(item - items)); + } + + return 0; +}
View file
libosmocore_1.10.0.tar.xz/tests/jhash/jhash_test.ok
Added
@@ -0,0 +1,25 @@ +add: +- adding items0#b286bb61 = blob one +- adding items1#ad4eb7b = blob two and five are the same +- adding items2#6b8eae61 = third blob +- adding items3#24a546dc = fourth blob +- adding items4#ad4eb7b = blob two and five are the same +list: +- blob two and five are the same 4 +- blob two and five are the same 1 +- blob one 0 +- fourth blob 3 +- third blob 2 +find: +- looking up items0#b286bb61 = blob one + - found items0 +- looking up items1#ad4eb7b = blob two and five are the same + - not items4 + - found items1 +- looking up items2#6b8eae61 = third blob + - found items2 +- looking up items3#24a546dc = fourth blob + - found items3 +- looking up items4#ad4eb7b = blob two and five are the same + - found items4 + - not items1
View file
libosmocore_1.9.3.tar.xz/tests/lapd/lapd_test.c -> libosmocore_1.10.0.tar.xz/tests/lapd/lapd_test.c
Changed
@@ -506,7 +506,7 @@ cm2 = malloc(sizeof(cm)); memcpy(cm2, cm, sizeof(cm)); cm20 += 1; - send_sabm(&bts_to_ms_channel, 0, cm2, sizeof(cm2)); + send_sabm(&bts_to_ms_channel, 0, cm2, sizeof(cm)); free(cm2); rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH"); OSMO_ASSERT(rc == -ENODEV);
View file
libosmocore_1.10.0.tar.xz/tests/logging/logging_gsmtap_test.c
Added
@@ -0,0 +1,64 @@ +/* simple test for gsmtap logging */ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * 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 2 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. + * + */ + +#include <osmocom/core/select.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/utils.h> + +#include <stdlib.h> + +static const struct log_info_cat default_categories = {}; + +const struct log_info log_info = { + .cat = default_categories, + .num_cat = ARRAY_SIZE(default_categories), +}; + +extern struct log_info *osmo_log_info; + +int main(int argc, char **argv) +{ + struct log_target *stderr_target; + struct log_target *gsmtap_target; + + log_init(&log_info, NULL); + stderr_target = log_target_create_stderr(); + log_add_target(stderr_target); + log_set_all_filter(stderr_target, 1); + log_set_print_filename2(stderr_target, LOG_FILENAME_NONE); + log_set_print_category_hex(stderr_target, 0); + log_set_print_category(stderr_target, 1); + log_set_use_color(stderr_target, 0); + log_parse_category_mask(stderr_target, "DLGLOBAL,1"); + + gsmtap_target = log_target_create_gsmtap("127.0.0.2", 4729, "gsmtap", 1, 1); + log_add_target(gsmtap_target); + log_set_all_filter(gsmtap_target, 1); + log_parse_category_mask(gsmtap_target, "DLGLOBAL,1"); + + log_target_file_switch_to_stream(stderr_target); + + log_set_category_filter(stderr_target, DLIO, 1, LOGL_DEBUG); + + for (int i = 0; i < 200; i++) + DEBUGP(DLGLOBAL, "Repeating message (i = %d)\n", i); + + for (int i = 0; i < 200; i++) + osmo_select_main(1); + + return 0; +}
View file
libosmocore_1.10.0.tar.xz/tests/logging/logging_gsmtap_test.err
Added
@@ -0,0 +1,200 @@ +DLGLOBAL Repeating message (i = 0) +DLGLOBAL Repeating message (i = 1) +DLGLOBAL Repeating message (i = 2) +DLGLOBAL Repeating message (i = 3) +DLGLOBAL Repeating message (i = 4) +DLGLOBAL Repeating message (i = 5) +DLGLOBAL Repeating message (i = 6) +DLGLOBAL Repeating message (i = 7) +DLGLOBAL Repeating message (i = 8) +DLGLOBAL Repeating message (i = 9) +DLGLOBAL Repeating message (i = 10) +DLGLOBAL Repeating message (i = 11) +DLGLOBAL Repeating message (i = 12) +DLGLOBAL Repeating message (i = 13) +DLGLOBAL Repeating message (i = 14) +DLGLOBAL Repeating message (i = 15) +DLGLOBAL Repeating message (i = 16) +DLGLOBAL Repeating message (i = 17) +DLGLOBAL Repeating message (i = 18) +DLGLOBAL Repeating message (i = 19) +DLGLOBAL Repeating message (i = 20) +DLGLOBAL Repeating message (i = 21) +DLGLOBAL Repeating message (i = 22) +DLGLOBAL Repeating message (i = 23) +DLGLOBAL Repeating message (i = 24) +DLGLOBAL Repeating message (i = 25) +DLGLOBAL Repeating message (i = 26) +DLGLOBAL Repeating message (i = 27) +DLGLOBAL Repeating message (i = 28) +DLGLOBAL Repeating message (i = 29) +DLGLOBAL Repeating message (i = 30) +DLGLOBAL Repeating message (i = 31) +DLGLOBAL Repeating message (i = 32) +DLGLOBAL Repeating message (i = 33) +DLGLOBAL Repeating message (i = 34) +DLGLOBAL Repeating message (i = 35) +DLGLOBAL Repeating message (i = 36) +DLGLOBAL Repeating message (i = 37) +DLGLOBAL Repeating message (i = 38) +DLGLOBAL Repeating message (i = 39) +DLGLOBAL Repeating message (i = 40) +DLGLOBAL Repeating message (i = 41) +DLGLOBAL Repeating message (i = 42) +DLGLOBAL Repeating message (i = 43) +DLGLOBAL Repeating message (i = 44) +DLGLOBAL Repeating message (i = 45) +DLGLOBAL Repeating message (i = 46) +DLGLOBAL Repeating message (i = 47) +DLGLOBAL Repeating message (i = 48) +DLGLOBAL Repeating message (i = 49) +DLGLOBAL Repeating message (i = 50) +DLGLOBAL Repeating message (i = 51) +DLGLOBAL Repeating message (i = 52) +DLGLOBAL Repeating message (i = 53) +DLGLOBAL Repeating message (i = 54) +DLGLOBAL Repeating message (i = 55) +DLGLOBAL Repeating message (i = 56) +DLGLOBAL Repeating message (i = 57) +DLGLOBAL Repeating message (i = 58) +DLGLOBAL Repeating message (i = 59) +DLGLOBAL Repeating message (i = 60) +DLGLOBAL Repeating message (i = 61) +DLGLOBAL Repeating message (i = 62) +DLGLOBAL Repeating message (i = 63) +DLGLOBAL Repeating message (i = 64) +DLGLOBAL Repeating message (i = 65) +DLGLOBAL Repeating message (i = 66) +DLGLOBAL Repeating message (i = 67) +DLGLOBAL Repeating message (i = 68) +DLGLOBAL Repeating message (i = 69) +DLGLOBAL Repeating message (i = 70) +DLGLOBAL Repeating message (i = 71) +DLGLOBAL Repeating message (i = 72) +DLGLOBAL Repeating message (i = 73) +DLGLOBAL Repeating message (i = 74) +DLGLOBAL Repeating message (i = 75) +DLGLOBAL Repeating message (i = 76) +DLGLOBAL Repeating message (i = 77) +DLGLOBAL Repeating message (i = 78) +DLGLOBAL Repeating message (i = 79) +DLGLOBAL Repeating message (i = 80) +DLGLOBAL Repeating message (i = 81) +DLGLOBAL Repeating message (i = 82) +DLGLOBAL Repeating message (i = 83) +DLGLOBAL Repeating message (i = 84) +DLGLOBAL Repeating message (i = 85) +DLGLOBAL Repeating message (i = 86) +DLGLOBAL Repeating message (i = 87) +DLGLOBAL Repeating message (i = 88) +DLGLOBAL Repeating message (i = 89) +DLGLOBAL Repeating message (i = 90) +DLGLOBAL Repeating message (i = 91) +DLGLOBAL Repeating message (i = 92) +DLGLOBAL Repeating message (i = 93) +DLGLOBAL Repeating message (i = 94) +DLGLOBAL Repeating message (i = 95) +DLGLOBAL Repeating message (i = 96) +DLGLOBAL Repeating message (i = 97) +DLGLOBAL Repeating message (i = 98) +DLGLOBAL Repeating message (i = 99) +DLGLOBAL Repeating message (i = 100) +DLGLOBAL Repeating message (i = 101) +DLGLOBAL Repeating message (i = 102) +DLGLOBAL Repeating message (i = 103) +DLGLOBAL Repeating message (i = 104) +DLGLOBAL Repeating message (i = 105) +DLGLOBAL Repeating message (i = 106) +DLGLOBAL Repeating message (i = 107) +DLGLOBAL Repeating message (i = 108) +DLGLOBAL Repeating message (i = 109) +DLGLOBAL Repeating message (i = 110) +DLGLOBAL Repeating message (i = 111) +DLGLOBAL Repeating message (i = 112) +DLGLOBAL Repeating message (i = 113) +DLGLOBAL Repeating message (i = 114) +DLGLOBAL Repeating message (i = 115) +DLGLOBAL Repeating message (i = 116) +DLGLOBAL Repeating message (i = 117) +DLGLOBAL Repeating message (i = 118) +DLGLOBAL Repeating message (i = 119) +DLGLOBAL Repeating message (i = 120) +DLGLOBAL Repeating message (i = 121) +DLGLOBAL Repeating message (i = 122) +DLGLOBAL Repeating message (i = 123) +DLGLOBAL Repeating message (i = 124) +DLGLOBAL Repeating message (i = 125) +DLGLOBAL Repeating message (i = 126) +DLGLOBAL Repeating message (i = 127) +DLGLOBAL Repeating message (i = 128) +DLGLOBAL Repeating message (i = 129) +DLGLOBAL Repeating message (i = 130) +DLGLOBAL Repeating message (i = 131) +DLGLOBAL Repeating message (i = 132) +DLGLOBAL Repeating message (i = 133) +DLGLOBAL Repeating message (i = 134) +DLGLOBAL Repeating message (i = 135) +DLGLOBAL Repeating message (i = 136) +DLGLOBAL Repeating message (i = 137) +DLGLOBAL Repeating message (i = 138) +DLGLOBAL Repeating message (i = 139) +DLGLOBAL Repeating message (i = 140) +DLGLOBAL Repeating message (i = 141) +DLGLOBAL Repeating message (i = 142) +DLGLOBAL Repeating message (i = 143) +DLGLOBAL Repeating message (i = 144) +DLGLOBAL Repeating message (i = 145) +DLGLOBAL Repeating message (i = 146) +DLGLOBAL Repeating message (i = 147) +DLGLOBAL Repeating message (i = 148) +DLGLOBAL Repeating message (i = 149) +DLGLOBAL Repeating message (i = 150) +DLGLOBAL Repeating message (i = 151) +DLGLOBAL Repeating message (i = 152) +DLGLOBAL Repeating message (i = 153) +DLGLOBAL Repeating message (i = 154) +DLGLOBAL Repeating message (i = 155) +DLGLOBAL Repeating message (i = 156) +DLGLOBAL Repeating message (i = 157) +DLGLOBAL Repeating message (i = 158) +DLGLOBAL Repeating message (i = 159) +DLGLOBAL Repeating message (i = 160) +DLGLOBAL Repeating message (i = 161) +DLGLOBAL Repeating message (i = 162) +DLGLOBAL Repeating message (i = 163) +DLGLOBAL Repeating message (i = 164) +DLGLOBAL Repeating message (i = 165) +DLGLOBAL Repeating message (i = 166) +DLGLOBAL Repeating message (i = 167) +DLGLOBAL Repeating message (i = 168) +DLGLOBAL Repeating message (i = 169) +DLGLOBAL Repeating message (i = 170) +DLGLOBAL Repeating message (i = 171) +DLGLOBAL Repeating message (i = 172) +DLGLOBAL Repeating message (i = 173) +DLGLOBAL Repeating message (i = 174) +DLGLOBAL Repeating message (i = 175) +DLGLOBAL Repeating message (i = 176) +DLGLOBAL Repeating message (i = 177) +DLGLOBAL Repeating message (i = 178) +DLGLOBAL Repeating message (i = 179) +DLGLOBAL Repeating message (i = 180) +DLGLOBAL Repeating message (i = 181) +DLGLOBAL Repeating message (i = 182) +DLGLOBAL Repeating message (i = 183) +DLGLOBAL Repeating message (i = 184) +DLGLOBAL Repeating message (i = 185) +DLGLOBAL Repeating message (i = 186) +DLGLOBAL Repeating message (i = 187) +DLGLOBAL Repeating message (i = 188) +DLGLOBAL Repeating message (i = 189) +DLGLOBAL Repeating message (i = 190) +DLGLOBAL Repeating message (i = 191) +DLGLOBAL Repeating message (i = 192) +DLGLOBAL Repeating message (i = 193) +DLGLOBAL Repeating message (i = 194) +DLGLOBAL Repeating message (i = 195) +DLGLOBAL Repeating message (i = 196) +DLGLOBAL Repeating message (i = 197) +DLGLOBAL Repeating message (i = 198) +DLGLOBAL Repeating message (i = 199)
View file
libosmocore_1.9.3.tar.xz/tests/msgfile/msgfile_test.c -> libosmocore_1.10.0.tar.xz/tests/msgfile/msgfile_test.c
Changed
@@ -17,6 +17,7 @@ #include <osmocom/core/msgfile.h> #include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> #include <stdio.h> @@ -39,8 +40,8 @@ { struct osmo_config_list *entries; - /* todo use msgfile_test.c.in and replace the path */ - entries = osmo_config_list_parse(NULL, "msgconfig.cfg"); + OSMO_ASSERT(argc > 1); + entries = osmo_config_list_parse(NULL, argv1); dump_entries(entries); talloc_free(entries);
View file
libosmocore_1.10.0.tar.xz/tests/rlp
Added
+(directory)
View file
libosmocore_1.10.0.tar.xz/tests/rlp/rlp_test.c
Added
@@ -0,0 +1,217 @@ +#include <osmocom/core/utils.h> +#include <osmocom/gsm/rlp.h> + +struct rlp_testcase { + const char *name; + const char *encoded_hex; + struct osmo_rlp_frame_decoded decoded; +}; + + +const struct rlp_testcase testcases = { + { + .name = "XID1", + .encoded_hex = "f95f1100213d313d414e6108510600000000000000000000000000c13c6b", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_U, + .u_ftype = OSMO_RLP_U_FT_XID, + .s_ftype = 0, + .c_r = 1, + .p_f = 1, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0x6b3cc1, + .info = { 0x11, 0x00, 0x21, 0x3d, 0x31, 0x3d, 0x41, 0x4e, 0x61, 0x08, + 0x51, 0x06, }, + .info_len = 25, + }, + }, { + .name = "XID2", + .encoded_hex = "f95f1101213d313d41305106610774000008060000000000000000ba14a0", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_U, + .u_ftype = OSMO_RLP_U_FT_XID, + .s_ftype = 0, + .c_r = 1, + .p_f = 1, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0xa014ba, + .info = { 0x11, 0x01, 0x21, 0x3d, 0x31, 0x3d, 0x41, 0x30, 0x51, 0x06, + 0x61, 0x07, 0x74, 0x00, 0x00, 0x08, 0x06, }, + .info_len = 25, + }, + }, { + .name = "SABM", + .encoded_hex = "f91f0000000000000000000000000000000000000000000000000063b2f3", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_U, + .u_ftype = OSMO_RLP_U_FT_SABM, + .s_ftype = 0, + .c_r = 1, + .p_f = 1, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0xf3b263, + .info = {}, + .info_len = 0, + }, + }, { + .name = "UA", + .encoded_hex = "f8330000000000000000000000000000000000000000000000000029d801", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_U, + .u_ftype = OSMO_RLP_U_FT_UA, + .s_ftype = 0, + .c_r = 0, + .p_f = 1, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0x01d829, + .info = {}, + .info_len = 0, + }, + }, { + .name = "IS1", + .encoded_hex = "01001f000000000000000000000000000000000000000000000000f174ad", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_IS, + .u_ftype = 0, + .s_ftype = 0, + .c_r = 1, + .p_f = 0, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0xad74f1, + .info = { 0x1f, }, + .info_len = 25, + }, + }, { + .name = "IS2", + .encoded_hex = "010401661fffffffffffffffffffffffffffffffffffffffffffff388cd3", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_IS, + .u_ftype = 0, + .s_ftype = 0, + .c_r = 1, + .p_f = 0, + .s_bits = 0, + .n_s = 0, + .n_r = 1, + .fcs = 0xd38c38, + .info = { 0x01, 0x66, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff }, + .info_len = 25, + }, + }, { + .name = "DISC", + .encoded_hex = "f923000000000000000000000000000000000000000000000000007986f2", + .decoded = { + .version = 0, + .ftype = OSMO_RLP_FT_U, + .u_ftype = OSMO_RLP_U_FT_DISC, + .s_ftype = 0, + .c_r = 1, + .p_f = 1, + .s_bits = 0, + .n_s = 0, + .n_r = 0, + .fcs = 0xf28679, + .info = { }, + .info_len = 0, + }, + } +}; + +static void rlp_frame_print_u(const struct osmo_rlp_frame_decoded *rf) +{ + OSMO_ASSERT(rf->ftype == OSMO_RLP_FT_U); + printf("C/R=%u P/F=%u U %s (FCS=0x%06x) %s\n", rf->c_r, rf->p_f, + get_value_string(osmo_rlp_ftype_u_vals, rf->u_ftype), + rf->fcs, + rf->u_ftype == OSMO_RLP_U_FT_XID ? osmo_hexdump_nospc(rf->info, rf->info_len) : ""); +} + +static void rlp_frame_print_s(const struct osmo_rlp_frame_decoded *rf) +{ + OSMO_ASSERT(rf->ftype == OSMO_RLP_FT_S); + printf("C/R=%u P/F=%u S N(R)=%u %s (FCS=0x%06x)\n", rf->c_r, rf->p_f, + rf->n_r, get_value_string(osmo_rlp_ftype_s_vals, rf->s_ftype), + rf->fcs); +} + +static void rlp_frame_print_is(const struct osmo_rlp_frame_decoded *rf) +{ + OSMO_ASSERT(rf->ftype == OSMO_RLP_FT_IS); + printf("C/R=%u P/F=%u IS N(R)=%u N(S)=%u %s (FCS=0x%06x) %s\n", rf->c_r, rf->p_f, + rf->n_r, rf->n_s, get_value_string(osmo_rlp_ftype_s_vals, rf->s_ftype), + rf->fcs, osmo_hexdump_nospc(rf->info, rf->info_len)); +} + +static void rlp_frame_print(const struct osmo_rlp_frame_decoded *rf) +{ + switch (rf->ftype) { + case OSMO_RLP_FT_U: + rlp_frame_print_u(rf); + break; + case OSMO_RLP_FT_S: + rlp_frame_print_s(rf); + break; + case OSMO_RLP_FT_IS: + rlp_frame_print_is(rf); + break; + default: + OSMO_ASSERT(0); + } +} + +static void execute_rlp_test(const struct rlp_testcase *tc) +{ + struct osmo_rlp_frame_decoded decoded; + uint8_t inbuf240/8; + int rc; + + printf("=== STARTING TESTCASE '%s'\n", tc->name); + + rc = osmo_hexparse(tc->encoded_hex, inbuf, sizeof(inbuf)); + OSMO_ASSERT(rc == 240/8); + + printf("Decoding %s:\n", tc->encoded_hex); + rc = osmo_rlp_decode(&decoded, 0, inbuf, rc); + OSMO_ASSERT(rc == 0); + + printf("Comparing...\n"); + rlp_frame_print(&decoded); + if (memcmp(&decoded, &tc->decoded, sizeof(decoded))) { + printf("DOESN'T MATCH EXPECTED DECODE:\n"); + rlp_frame_print(&tc->decoded); + } + + printf("Reencoding...\n"); + uint8_t reencoded240/8; + rc = osmo_rlp_encode(reencoded, sizeof(reencoded), &tc->decoded); + OSMO_ASSERT(rc == 240/8); + if (memcmp(inbuf, reencoded, sizeof(inbuf))) + printf("DOESN'T MATCH EXPECTED ENCODE FROM ABOVE\n"); +} + +int main(int argc, char **argv) +{ + for (unsigned int i = 0; i < ARRAY_SIZE(testcases); i++) { + const struct rlp_testcase *tc = &testcasesi; + execute_rlp_test(tc); + } + +}
View file
libosmocore_1.10.0.tar.xz/tests/rlp/rlp_test.ok
Added
@@ -0,0 +1,35 @@ +=== STARTING TESTCASE 'XID1' +Decoding f95f1100213d313d414e6108510600000000000000000000000000c13c6b: +Comparing... +C/R=1 P/F=1 U XID (FCS=0x6b3cc1) 1100213d313d414e6108510600000000000000000000000000 +Reencoding... +=== STARTING TESTCASE 'XID2' +Decoding f95f1101213d313d41305106610774000008060000000000000000ba14a0: +Comparing... +C/R=1 P/F=1 U XID (FCS=0xa014ba) 1101213d313d41305106610774000008060000000000000000 +Reencoding... +=== STARTING TESTCASE 'SABM' +Decoding f91f0000000000000000000000000000000000000000000000000063b2f3: +Comparing... +C/R=1 P/F=1 U SABM (FCS=0xf3b263) +Reencoding... +=== STARTING TESTCASE 'UA' +Decoding f8330000000000000000000000000000000000000000000000000029d801: +Comparing... +C/R=0 P/F=1 U UA (FCS=0x01d829) +Reencoding... +=== STARTING TESTCASE 'IS1' +Decoding 01001f000000000000000000000000000000000000000000000000f174ad: +Comparing... +C/R=1 P/F=0 IS N(R)=0 N(S)=0 RR (FCS=0xad74f1) 1f000000000000000000000000000000000000000000000000 +Reencoding... +=== STARTING TESTCASE 'IS2' +Decoding 010401661fffffffffffffffffffffffffffffffffffffffffffff388cd3: +Comparing... +C/R=1 P/F=0 IS N(R)=1 N(S)=0 RR (FCS=0xd38c38) 01661fffffffffffffffffffffffffffffffffffffffffffff +Reencoding... +=== STARTING TESTCASE 'DISC' +Decoding f923000000000000000000000000000000000000000000000000007986f2: +Comparing... +C/R=1 P/F=1 U DISC (FCS=0xf28679) +Reencoding...
View file
libosmocore_1.9.3.tar.xz/tests/sockaddr_str/sockaddr_str_test.c -> libosmocore_1.10.0.tar.xz/tests/sockaddr_str/sockaddr_str_test.c
Changed
@@ -68,21 +68,18 @@ } } -static const struct value_string err_names = { - { -EINVAL, "-EINVAL" }, - {} -}; - -static inline const char *err_name(int err) -{ return get_value_string(err_names, err); } - static inline const char *rc_name(int rc) { - if (!rc) + switch (rc) { + case -EINVAL: + return "rc == -EINVAL"; + case -EAFNOSUPPORT: + return "rc == -EAFNOSUPPORT"; + case 0: return "rc == 0"; - if (rc < 0) - return "rc < 0"; - return "rc > 0"; + default: + return rc < 0 ? "rc < 0" : "rc > 0"; + } } void dump_oip(const struct osmo_sockaddr_str *oip)
View file
libosmocore_1.9.3.tar.xz/tests/sockaddr_str/sockaddr_str_test.ok -> libosmocore_1.10.0.tar.xz/tests/sockaddr_str/sockaddr_str_test.ok
Changed
@@ -6,14 +6,14 @@ osmo_sockaddr_str_is_nonzero() = true osmo_sockaddr_str_to_in_addr() rc == 0 in_addr=01020304 -> osmo_sockaddr_str_from_in_addr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 osmo_sockaddr_str_to_32() rc == 0 uint8_t4= 01 02 03 04 -> osmo_sockaddr_str_from_32() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } osmo_sockaddr_str_to_32h() rc == 0 uint8_t4= 04 03 02 01 -> osmo_sockaddr_str_from_32h() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } osmo_sockaddr_str_to_sockaddr_in() rc == 0 sockaddr_in=02000005010203040000000000000000 -> osmo_sockaddr_str_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0200000501020304000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } @@ -25,14 +25,14 @@ osmo_sockaddr_str_is_nonzero() = false osmo_sockaddr_str_to_in_addr() rc == 0 in_addr=00000000 -> osmo_sockaddr_str_from_in_addr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 osmo_sockaddr_str_to_32() rc == 0 uint8_t4= 00 00 00 00 -> osmo_sockaddr_str_from_32() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } osmo_sockaddr_str_to_32h() rc == 0 uint8_t4= 00 00 00 00 -> osmo_sockaddr_str_from_32h() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } osmo_sockaddr_str_to_sockaddr_in() rc == 0 sockaddr_in=02000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 0 } @@ -44,14 +44,14 @@ osmo_sockaddr_str_is_nonzero() = true osmo_sockaddr_str_to_in_addr() rc == 0 in_addr=ffffffff -> osmo_sockaddr_str_from_in_addr() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 osmo_sockaddr_str_to_32() rc == 0 uint8_t4= ff ff ff ff -> osmo_sockaddr_str_from_32() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } osmo_sockaddr_str_to_32h() rc == 0 uint8_t4= ff ff ff ff -> osmo_sockaddr_str_from_32h() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } osmo_sockaddr_str_to_sockaddr_in() rc == 0 sockaddr_in=0200ffffffffffff0000000000000000 -> osmo_sockaddr_str_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0200ffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "255.255.255.255", .port = 65535 } @@ -61,13 +61,13 @@ OSMO_SOCKADDR_STR_FMT: '0.0.0.256:1' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=02000001000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EINVAL in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=02000001000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "0.0.0.256", .port = 1 } @@ -75,26 +75,26 @@ OSMO_SOCKADDR_STR_FMT: 'not an ip address:1' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=02000001000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "not an ip address", .port = 1 } + osmo_sockaddr_str_to_in_addr() rc == -EINVAL in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=02000001000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0200000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_from_str() rc == -EINVAL { .af = AF_UNSPEC, .ip = "not an ip address", .port = 1 } { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 } OSMO_SOCKADDR_STR_FMT: '1:2:3::4:5' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = true - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=00010002000300000000000000000004 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 } - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000005000000000001000200030000000000000000000400000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 } osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0a00000500000000000100020003000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -106,12 +106,12 @@ OSMO_SOCKADDR_STR_FMT: ':::0' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000000 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 } - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::", .port = 0 } osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -123,12 +123,12 @@ OSMO_SOCKADDR_STR_FMT: '::1:0' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000001 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 } - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000000000000000000000000000000000000000000000100000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::1", .port = 0 } osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0a00000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -140,12 +140,12 @@ OSMO_SOCKADDR_STR_FMT: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:65535' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = true - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=ffffffffffffffffffffffffffffffff -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 } - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a00ffff00000000ffffffffffffffffffffffffffffffff00000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 } osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0a00ffff00000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -157,13 +157,13 @@ OSMO_SOCKADDR_STR_FMT: 'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:65535' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = true - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=ffffffffffffffffffffffffffffffff -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 } DIFFERS! - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a00ffff00000000ffffffffffffffffffffffffffffffff00000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", .port = 65535 } DIFFERS! @@ -177,13 +177,13 @@ OSMO_SOCKADDR_STR_FMT: '::fffff:1' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000001000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=0a000001000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET6, .ip = "::fffff", .port = 1 } @@ -191,27 +191,27 @@ OSMO_SOCKADDR_STR_FMT: 'not an ip address:1' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000001000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "not an ip address", .port = 1 } + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=0a000001000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0a00000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_from_str() rc == -EINVAL { .af = AF_UNSPEC, .ip = "not an ip address", .port = 1 } { .af = AF_INET6, .ip = "1.2.3.4", .port = 5 } OSMO_SOCKADDR_STR_FMT: '1.2.3.4:5' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } DIFFERS! @@ -220,13 +220,13 @@ OSMO_SOCKADDR_STR_FMT: '1:2:3::4:5' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=02000005000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EINVAL in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=02000005000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET6, .ip = "1:2:3::4", .port = 5 } DIFFERS! @@ -235,13 +235,13 @@ OSMO_SOCKADDR_STR_FMT: '1.2.3.4:5' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 5 } DIFFERS! @@ -250,13 +250,13 @@ OSMO_SOCKADDR_STR_FMT: ':5' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=02000005000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EINVAL in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=02000005000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "", .port = 5 } @@ -264,13 +264,13 @@ OSMO_SOCKADDR_STR_FMT: ':5' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc < 0 { .af = AF_UNSPEC, .ip = "", .port = 5 } @@ -280,14 +280,14 @@ osmo_sockaddr_str_is_nonzero() = false osmo_sockaddr_str_to_in_addr() rc == 0 in_addr=01020304 -> osmo_sockaddr_str_from_in_addr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 osmo_sockaddr_str_to_32() rc == 0 uint8_t4= 01 02 03 04 -> osmo_sockaddr_str_from_32() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } osmo_sockaddr_str_to_32h() rc == 0 uint8_t4= 04 03 02 01 -> osmo_sockaddr_str_from_32h() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } osmo_sockaddr_str_to_sockaddr_in() rc == 0 sockaddr_in=02000000010203040000000000000000 -> osmo_sockaddr_str_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0200000001020304000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "1.2.3.4", .port = 0 } @@ -297,13 +297,13 @@ OSMO_SOCKADDR_STR_FMT: '1.2.3:4:5:0' osmo_sockaddr_str_is_set() = false osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=02000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 - osmo_sockaddr_str_to_sockaddr() rc < 0 sockaddr_storage=0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_in_addr() rc == -EINVAL in_addr=00000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EINVAL uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=02000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr() rc == -EINVAL sockaddr_storage=0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET6, .ip = "1.2.3:4:5", .port = 0 } DIFFERS! @@ -312,13 +312,13 @@ OSMO_SOCKADDR_STR_FMT: '::1:10.9.8.7:1' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = true - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=0000000000000000000000010a090807 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::1:a09:807", .port = 1 } DIFFERS! - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000001000000000000000000000000000000010a09080700000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::1:a09:807", .port = 1 } DIFFERS! @@ -334,14 +334,14 @@ osmo_sockaddr_str_is_nonzero() = false osmo_sockaddr_str_to_in_addr() rc == 0 in_addr=00000000 -> osmo_sockaddr_str_from_in_addr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } - osmo_sockaddr_str_to_in6_addr() rc < 0 in6_addr=00000000000000000000000000000000 + osmo_sockaddr_str_to_in6_addr() rc == -EINVAL in6_addr=00000000000000000000000000000000 osmo_sockaddr_str_to_32() rc == 0 uint8_t4= 00 00 00 00 -> osmo_sockaddr_str_from_32() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } osmo_sockaddr_str_to_32h() rc == 0 uint8_t4= 00 00 00 00 -> osmo_sockaddr_str_from_32h() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } osmo_sockaddr_str_to_sockaddr_in() rc == 0 sockaddr_in=02000005000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr_in() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } - osmo_sockaddr_str_to_sockaddr_in6() rc < 0 sockaddr_in6=00000000000000000000000000000000000000000000000000000000 + osmo_sockaddr_str_to_sockaddr_in6() rc == -EINVAL sockaddr_in6=00000000000000000000000000000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0200000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } osmo_sockaddr_str_from_str() rc == 0 { .af = AF_INET, .ip = "0.0.0.0", .port = 5 } @@ -351,12 +351,12 @@ OSMO_SOCKADDR_STR_FMT: ':::5' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000000 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::", .port = 5 } - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::", .port = 5 } osmo_sockaddr_str_to_sockaddr() rc == 0 sockaddr_storage=0a00000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -368,13 +368,13 @@ OSMO_SOCKADDR_STR_FMT: '0:::5' osmo_sockaddr_str_is_set() = true osmo_sockaddr_str_is_nonzero() = false - osmo_sockaddr_str_to_in_addr() rc < 0 in_addr=00000000 + osmo_sockaddr_str_to_in_addr() rc == -EAFNOSUPPORT in_addr=00000000 osmo_sockaddr_str_to_in6_addr() rc == 0 in6_addr=00000000000000000000000000000000 -> osmo_sockaddr_str_from_in6_addr() rc == 0 { .af = AF_INET6, .ip = "::", .port = 5 } DIFFERS! - osmo_sockaddr_str_to_32() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_32h() rc < 0 uint8_t4= 00 00 00 00 - osmo_sockaddr_str_to_sockaddr_in() rc < 0 sockaddr_in=00000000000000000000000000000000 + osmo_sockaddr_str_to_32() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_32h() rc == -EAFNOSUPPORT uint8_t4= 00 00 00 00 + osmo_sockaddr_str_to_sockaddr_in() rc == -EINVAL sockaddr_in=00000000000000000000000000000000 osmo_sockaddr_str_to_sockaddr_in6() rc == 0 sockaddr_in6=0a000005000000000000000000000000000000000000000000000000 -> osmo_sockaddr_str_from_sockaddr_in6() rc == 0 { .af = AF_INET6, .ip = "::", .port = 5 } DIFFERS!
View file
libosmocore_1.9.3.tar.xz/tests/socket/socket_sctp_test.c -> libosmocore_1.10.0.tar.xz/tests/socket/socket_sctp_test.c
Changed
@@ -107,6 +107,7 @@ addrv4_rem, addrv4_size, listen_port_v4, OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT); OSMO_ASSERT(fd >= 0); + close(fd); printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv4 & IPv6\n"); fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP, @@ -128,6 +129,7 @@ addrv4_rem, addrv4_size, listen_port_v4, OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT); OSMO_ASSERT(fd >= 0); + close(fd); printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6\n"); fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP, @@ -135,6 +137,7 @@ addrv6_rem, addrv6_size, listen_port_v6, OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT); OSMO_ASSERT(fd >= 0); + close(fd); close(listen_fd_v4); close(listen_fd_v6);
View file
libosmocore_1.9.3.tar.xz/tests/socket/socket_test.c -> libosmocore_1.10.0.tar.xz/tests/socket/socket_test.c
Changed
@@ -315,6 +315,7 @@ const char *result; struct osmo_sockaddr localhost4 = {}; struct osmo_sockaddr localhost6 = {}; + struct osmo_sockaddr osa = {}; localhost4.u.sin = (struct sockaddr_in){ .sin_family = AF_INET, @@ -383,6 +384,18 @@ result = osmo_sockaddr_to_str(&localhost6); printf("Checking osmo_sockaddr_to_str_buf long IPv6 port static buffer\n"); OSMO_ASSERT(!strncmp("2003:1234:5678:90ab:cdef:1234:4321:4321:23420", result, sizeof(buf))); + + printf("Checking osmo_sockaddr_from_str_and_uint for 0.0.0.0\n"); + OSMO_ASSERT(osmo_sockaddr_from_str_and_uint(&osa, "0.0.0.0", 1234) == 0); + OSMO_ASSERT(osmo_sockaddr_is_any(&osa)); + + printf("Checking osmo_sockaddr_from_str_and_uint for ::\n"); + OSMO_ASSERT(osmo_sockaddr_from_str_and_uint(&osa, "::", 1234) == 0); + OSMO_ASSERT(osmo_sockaddr_is_any(&osa)); + + printf("Checking osmo_sockaddr_from_str_and_uint for 1.2.3.4\n"); + OSMO_ASSERT(osmo_sockaddr_from_str_and_uint(&osa, "1.2.3.4", 1234) == 0); + OSMO_ASSERT(!osmo_sockaddr_is_any(&osa)); } static void test_osa_netmask_prefixlen(void)
View file
libosmocore_1.9.3.tar.xz/tests/socket/socket_test.ok -> libosmocore_1.10.0.tar.xz/tests/socket/socket_test.ok
Changed
@@ -31,3 +31,6 @@ Checking osmo_sockaddr_to_str_buf long IPv6 Checking osmo_sockaddr_to_str_buf long IPv6 port Checking osmo_sockaddr_to_str_buf long IPv6 port static buffer +Checking osmo_sockaddr_from_str_and_uint for 0.0.0.0 +Checking osmo_sockaddr_from_str_and_uint for :: +Checking osmo_sockaddr_from_str_and_uint for 1.2.3.4
View file
libosmocore_1.10.0.tar.xz/tests/soft_uart
Added
+(directory)
View file
libosmocore_1.10.0.tar.xz/tests/soft_uart/soft_uart_test.c
Added
@@ -0,0 +1,658 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> + * + * All Rights Reserved + * + * 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 2 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. + * + */ + +#include <errno.h> +#include <stdio.h> +#include <stdint.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/soft_uart.h> + +#define SUART_TEST_BEGIN \ + do { \ + printf("\nExecuting %s\n", __func__); \ + } while (0) + +static struct { + size_t data_len; + const uint8_t *data; +} g_tx_cb_cfg; + +static void suart_rx_cb(void *priv, struct msgb *msg, unsigned int flags) +{ + fprintf(stdout, "%s(flags=%02x): %s\n", + __func__, flags, msgb_hexdump(msg)); + msgb_free(msg); +} + +static void suart_tx_cb(void *priv, struct msgb *msg) +{ + size_t n_bytes; + + n_bytes = OSMO_MIN(g_tx_cb_cfg.data_len, msg->data_len); + if (g_tx_cb_cfg.data != NULL && n_bytes > 0) + memcpy(msgb_put(msg, n_bytes), g_tx_cb_cfg.data, n_bytes); + + fprintf(stdout, "%s(len=%u/%u): %s\n", + __func__, msg->len, msg->data_len, msgb_hexdump(msg)); +} + +static void suart_status_change_cb(void *priv, unsigned int status) +{ + fprintf(stdout, "%s(status=0x%08x)\n", __func__, status); +} + +static const struct osmo_soft_uart_cfg suart_test_default_cfg = { + .num_data_bits = 8, + .num_stop_bits = 1, + .parity_mode = OSMO_SUART_PARITY_NONE, + .rx_buf_size = 128, + .rx_cb = &suart_rx_cb, + .tx_cb = &suart_tx_cb, + .status_change_cb = &suart_status_change_cb, +}; + +static void test_rx_exec(struct osmo_soft_uart *suart, + const char *input) +{ + for (unsigned int i = 0; inputi != '\0'; i++) { + ubit_t ubit; + int rc; + + switch (inputi) { + case '0': + case '1': + ubit = inputi - '0'; + rc = osmo_soft_uart_rx_ubits(suart, &ubit, 1); + OSMO_ASSERT(rc == 0); /* 0 on success */ + break; + case 'F': + printf("%s() @ %u: flush the Rx buffer\n", __func__, i); + osmo_soft_uart_flush_rx(suart); + break; + case ' ': /* padding */ + continue; + default: + printf("%s() @ %u: unknown opcode '%c'\n", + __func__, i, inputi); + break; + } + } +} + +static void test_rx(void) +{ + struct osmo_soft_uart_cfg cfg; + struct osmo_soft_uart *suart; + + SUART_TEST_BEGIN; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + osmo_soft_uart_set_rx(suart, true); + + printf("======== testing 8-N-1 (no data)\n"); + test_rx_exec(suart, "F11111F11111F"); + + printf("======== testing 8-N-1 (fill up flush)\n"); + cfg = suart_test_default_cfg; + cfg.rx_buf_size = 4; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, "11111" /* no data */ + "0 01111011 1" + "0 10110101 1" + "0 01111101 1" + "0 11110111 1" /* filled up, expect flush */ + "0 00000000 1" + "0 01010101 1" + "0 10101010 1" + "0 11111111 1" /* filled up, expect flush */ + "F" /* flush! (for sanity) */ + ); + + printf("======== testing 8-N-1 (HELLO)\n"); + cfg = suart_test_default_cfg; + cfg.num_stop_bits = 1; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, "111111" /* no data */ + "0 00010010 1F" /* 'H', flush! */ + "0 10100010 1F" /* 'E', flush! */ + "1111111111111" /* no data */ + "0 00110010 1F" /* 'L', flush! */ + "0 00110010 1F" /* 'L', flush! */ + "1111111111111" /* no data */ + "0 11110010 1F" /* 'O', flush! */ + ); + + printf("======== testing 8-N-1 (framing errors)\n"); + test_rx_exec(suart, "11111" /* no data */ + "0 00000000 0" /* stop bit != 1, expect flush */ + "0 01010101 0" /* stop bit != 1, expect flush */ + "0 11111111 1" /* stop bit == 1, recovery */ + "F" /* flush! */ + ); + + printf("======== testing 8-N-2 (HELLO)\n"); + cfg = suart_test_default_cfg; + cfg.num_stop_bits = 2; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, "11111111" /* no data */ + "0 00010010 1F1F" /* 'H', flush! */ + "0 10100010 1F1F" /* 'E', flush! */ + "111111111111111" /* no data */ + "0 00110010 1F1F" /* 'L', flush! */ + "0 00110010 1F1F" /* 'L', flush! */ + "111111111111111" /* no data */ + "0 11110010 1F1F" /* 'O', flush! */ + ); + + printf("======== testing 8-N-2 (framing errors)\n"); + test_rx_exec(suart, "11111" /* no data */ + "0 00000000 00" /* stop bit != 1, expect flush */ + "0 01010101 01" /* stop bit != 1, expect flush */ + "0 10101010 10" /* stop bit != 1, expect flush */ + "0 11111111 11" /* stop bit == 1, recovery */ + "F" /* flush! (for sanity) */ + ); + + + printf("======== testing 8-E-1 (invalid parity)\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_EVEN; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, "1111111" /* no data */ + "0 00000000 1 1" /* odd parity, expect flush */ + "0 10000000 0 1" /* odd parity, expect flush */ + "0 11111111 1 1" /* odd parity, expect flush */ + "F" /* flush! (for sanity) */ + ); + printf("======== testing 8-E-1 (valid parity)\n"); + test_rx_exec(suart, "1111111" /* no data */ + "0 00000000 0 1" + "0 11111111 0 1" + "0 01010101 0 1" + "0 10101010 0 1" + "F" /* flush! */ + "0 00000001 1 1" + "0 00000111 1 1" + "0 00011111 1 1" + "0 01111111 1 1" + "F" /* flush! */ + ); + + printf("======== testing 8-O-1 (invalid parity)\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_ODD; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, + "0 00000000 0 1" /* even parity, expect flush */ + "0 10000000 1 1" /* even parity, expect flush */ + "0 11111111 0 1" /* even parity, expect flush */ + "F" /* flush! (for sanity) */ + ); + printf("======== testing 8-O-1 (valid parity)\n"); + test_rx_exec(suart, "1111111" /* no data */ + "0 00000000 1 1" + "0 11111111 1 1" + "0 01010101 1 1" + "0 10101010 1 1" + "F" /* flush! */ + "0 00000001 0 1" + "0 00000111 0 1" + "0 00011111 0 1" + "0 01111111 0 1" + "F" /* flush! */ + ); + + osmo_soft_uart_free(suart); +} + +static void test_rx_flush(void) +{ + struct osmo_soft_uart_cfg cfg; + struct osmo_soft_uart *suart; + + SUART_TEST_BEGIN; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + printf("calling osmo_soft_uart_flush_rx() while Rx disabled\n"); + osmo_soft_uart_flush_rx(suart); + + printf("enabling the receiver\n"); + osmo_soft_uart_set_rx(suart, true); + + printf("calling osmo_soft_uart_flush_rx() while Rx enabled, but no data\n"); + osmo_soft_uart_flush_rx(suart); + + /* FIXME: this scenario demonstrates a problem that may occur when the user + * flushes the Rx buffer manually while the soft-UART state reflects flags + * of an incomplete symbol, for which we're waiting the stop bit. */ + printf("testing corner case: manual flushing during a parity error (8-E-1)\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_EVEN; + osmo_soft_uart_configure(suart, &cfg); + test_rx_exec(suart, "1111111" /* no data */ + "0 01010101 0 1" /* even parity, correct */ + "0 10101010 0 1" /* even parity, correct */ + "0 11111111 1" /* odd parity, incorrect, but stop bit is pending */ + "F" /* manual flush happens before receiving the stop bit */ + "1" /* finally, the stop bit is received */ + ); + /* test_rx_exec() @ 47: flush the Rx buffer + * suart_rx_cb(flags=02): aa 55 <--- this is wrong, should be flags=00 + * suart_rx_cb(flags=02): ff <--- this is expected due to odd parity */ + + + osmo_soft_uart_free(suart); +} + +static void test_tx_rx_exec_one(struct osmo_soft_uart *suart, + size_t n_bits_total, size_t n_bits_frame) +{ + ubit_t tx_bufn_bits_total; + ubit_t *ptr = &tx_buf0; + int rc; + + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, n_bits_total); + OSMO_ASSERT(rc == n_bits_total); + + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, n_bits_total); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + printf("%s(n_bits_total=%zu):", __func__, n_bits_total); + while (n_bits_total > 0) { + size_t n_bits = OSMO_MIN(n_bits_frame, n_bits_total); + printf(" %s", osmo_ubit_dump(ptr, n_bits)); + n_bits_total -= n_bits; + ptr += n_bits; + } + printf("\n"); +} + +static void test_tx_rx_exec(struct osmo_soft_uart *suart, size_t n_bits_frame) +{ + const uint8_t tx_data4 = { + { 0xde, 0xad, 0xbe, 0xef }, + { 0x00, 0xaa, 0x55, 0xff }, + { 0x01, 0x02, 0x04, 0x08 }, + { 0x10, 0x20, 0x40, 0x80 }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(tx_data); i++) { + g_tx_cb_cfg.data_len = 4; + g_tx_cb_cfg.data = tx_datai; + test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame); + } + + g_tx_cb_cfg.data_len = 0; + g_tx_cb_cfg.data = NULL; + test_tx_rx_exec_one(suart, 4 * n_bits_frame, n_bits_frame); +} + +static void test_tx_rx(void) +{ + struct osmo_soft_uart_cfg cfg; + struct osmo_soft_uart *suart; + int rc; + + SUART_TEST_BEGIN; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + /* expect -EAGAIN when the transmitter is not enabled */ + rc = osmo_soft_uart_tx_ubits(suart, NULL, 42); + OSMO_ASSERT(rc == -EAGAIN); + /* expect -EAGAIN when the receiver is not enabled */ + rc = osmo_soft_uart_rx_ubits(suart, NULL, 42); + OSMO_ASSERT(rc == -EAGAIN); + + osmo_soft_uart_set_tx(suart, true); + osmo_soft_uart_set_rx(suart, true); + + printf("======== testing 8-N-1\n"); + test_tx_rx_exec(suart, (1 + 8 + 1)); + + printf("======== testing 8-N-2\n"); + cfg = suart_test_default_cfg; + cfg.num_stop_bits = 2; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 8 + 2)); + + printf("======== testing 8-E-1\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_EVEN; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 8 + 1 + 1)); + + printf("======== testing 8-O-1\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_ODD; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 8 + 1 + 1)); + + printf("======== testing 8-M-1\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_MARK; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 8 + 1 + 1)); + + printf("======== testing 8-S-1\n"); + cfg = suart_test_default_cfg; + cfg.parity_mode = OSMO_SUART_PARITY_SPACE; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 8 + 1 + 1)); + + printf("======== testing 6-N-1\n"); + cfg = suart_test_default_cfg; + cfg.num_data_bits = 6; + osmo_soft_uart_configure(suart, &cfg); + test_tx_rx_exec(suart, (1 + 6 + 1)); + + osmo_soft_uart_free(suart); +} + +static void test_tx_rx_pull_n(unsigned int n) +{ + struct osmo_soft_uart *suart; + ubit_t tx_buf32; + int rc; + + SUART_TEST_BEGIN; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + osmo_soft_uart_set_tx(suart, true); + osmo_soft_uart_set_rx(suart, true); + + g_tx_cb_cfg.data = (void *)"\x55"; + g_tx_cb_cfg.data_len = 1; + + printf("======== pulling %lu bits (%u at a time)\n", sizeof(tx_buf), n); + for (unsigned int i = 0; i < sizeof(tx_buf); i += n) { + rc = osmo_soft_uart_tx_ubits(suart, &tx_bufi, n); + OSMO_ASSERT(rc == n); + } + printf("%s\n", osmo_ubit_dump(&tx_buf0, sizeof(tx_buf))); + + printf("======== feeding %lu bits into the receiver\n", sizeof(tx_buf)); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + osmo_soft_uart_free(suart); +} + +static void test_modem_status(void) +{ + struct osmo_soft_uart *suart; + unsigned int status; + + SUART_TEST_BEGIN; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + printf("initial status=0x%08x\n", osmo_soft_uart_get_status(suart)); + + printf("de-asserting DCD, which was not asserted\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DCD, false); + OSMO_ASSERT(osmo_soft_uart_get_status(suart) == 0x00); /* no change */ + + printf("asserting both RI and DCD, expecting the callback to be called twice\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RI, true); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DCD, true); + status = osmo_soft_uart_get_status(suart); + OSMO_ASSERT(status == (OSMO_SUART_STATUS_F_RI | OSMO_SUART_STATUS_F_DCD)); + + printf("de-asserting RI, expecting the callback to be called\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RI, false); + status = osmo_soft_uart_get_status(suart); + OSMO_ASSERT(status == (OSMO_SUART_STATUS_F_DCD)); + + printf("resetting to 0x00, expecting the callback to be called\n"); + osmo_soft_uart_set_status(suart, 0x00); + OSMO_ASSERT(osmo_soft_uart_get_status(suart) == 0x00); + + osmo_soft_uart_free(suart); +} + +static void test_flow_control_dtr_dsr(void) +{ + struct osmo_soft_uart_cfg cfg; + struct osmo_soft_uart *suart; + ubit_t tx_buf40; + int rc; + + SUART_TEST_BEGIN; + + g_tx_cb_cfg.data = (void *)"\x42\x42\x42\x42"; + g_tx_cb_cfg.data_len = 4; + + cfg = suart_test_default_cfg; + cfg.flow_ctrl_mode = OSMO_SUART_FLOW_CTRL_DTR_DSR; + + suart = osmo_soft_uart_alloc(NULL, __func__, &cfg); + OSMO_ASSERT(suart != NULL); + + osmo_soft_uart_set_tx(suart, true); + osmo_soft_uart_set_rx(suart, true); + + /* expect the initial status to be 0 (all lines de-asserted) */ + printf("initial status=0x%08x\n", osmo_soft_uart_get_status(suart)); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + printf("expecting osmo_soft_uart_tx_ubits() to yield nothing\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + + printf("expecting osmo_soft_uart_rx_ubits() to yield nothing\n"); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + /* both DTR and DSR are asserted, expect both Rx and Tx to work */ + printf("======== asserting both DTR and DSR\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DTR, true); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DSR, true); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield %zu bits (requesting %zu bits)\n", + sizeof(tx_buf), sizeof(tx_buf)); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == sizeof(tx_buf)); + printf("%s\n", osmo_ubit_dump(&tx_buf0, sizeof(tx_buf))); + + printf("expecting osmo_soft_uart_rx_ubits() to " + "consume %zu bits and yield %zu chars\n", + sizeof(tx_buf), sizeof(tx_buf) / 10); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + /* make the transmitter consume one char, but pull only 2 bits */ + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield 2 bits (requesting 2 bits)\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, 2); + OSMO_ASSERT(rc == 2); + + /* CTS gets de-asserted, the transmitter is shutting down */ + printf("======== de-asserting DSR\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_DSR, false); + + /* expect only the remaining 8 bits to be pulled out */ + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield 8 bits (requesting %zu bits)\n", sizeof(tx_buf)); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf2, sizeof(tx_buf) - 2); + OSMO_ASSERT(rc == 8); + + printf("expecting osmo_soft_uart_rx_ubits() to " + "consume %zu bits and yield a pending char\n", sizeof(tx_buf)); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + osmo_soft_uart_free(suart); +} + +static void test_flow_control_rts_cts(void) +{ + struct osmo_soft_uart_cfg cfg; + struct osmo_soft_uart *suart; + ubit_t tx_buf40; + int rc; + + SUART_TEST_BEGIN; + + g_tx_cb_cfg.data = (void *)"\x42\x42\x42\x42"; + g_tx_cb_cfg.data_len = 4; + + cfg = suart_test_default_cfg; + cfg.flow_ctrl_mode = OSMO_SUART_FLOW_CTRL_RTS_CTS; + + suart = osmo_soft_uart_alloc(NULL, __func__, &cfg); + OSMO_ASSERT(suart != NULL); + + osmo_soft_uart_set_tx(suart, true); + osmo_soft_uart_set_rx(suart, true); + + /* expect the initial status to be 0 (all lines de-asserted) */ + printf("initial status=0x%08x\n", osmo_soft_uart_get_status(suart)); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + printf("expecting osmo_soft_uart_tx_ubits() to yield nothing\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + + printf("expecting osmo_soft_uart_rx_ubits() to yield nothing\n"); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + /* both RTS/RTR and CTS are asserted, expect both Rx and Tx to work */ + printf("======== asserting both CTS and RTS/RTR\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_CTS, true); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_RTS_RTR, true); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield %zu bits (requesting %zu bits)\n", + sizeof(tx_buf), sizeof(tx_buf)); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == sizeof(tx_buf)); + printf("%s\n", osmo_ubit_dump(&tx_buf0, sizeof(tx_buf))); + + printf("expecting osmo_soft_uart_rx_ubits() to " + "consume %zu bits and yield %zu chars\n", + sizeof(tx_buf), sizeof(tx_buf) / 10); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + memset(&tx_buf0, 1, sizeof(tx_buf)); /* pre-initialize */ + + /* make the transmitter consume one char, but pull only 2 bits */ + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield 2 bits (requesting 2 bits)\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, 2); + OSMO_ASSERT(rc == 2); + + /* CTS gets de-asserted, the transmitter is shutting down */ + printf("======== de-asserting CTS\n"); + osmo_soft_uart_set_status_line(suart, OSMO_SUART_STATUS_F_CTS, false); + + /* expect only the remaining 8 bits to be pulled out */ + printf("expecting osmo_soft_uart_tx_ubits() to " + "yield 8 bits (requesting %zu bits)\n", sizeof(tx_buf)); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf2, sizeof(tx_buf) - 2); + OSMO_ASSERT(rc == 8); + + printf("expecting osmo_soft_uart_rx_ubits() to " + "consume %zu bits and yield a pending char\n", sizeof(tx_buf)); + rc = osmo_soft_uart_rx_ubits(suart, &tx_buf0, sizeof(tx_buf)); + OSMO_ASSERT(rc == 0); + osmo_soft_uart_flush_rx(suart); + + osmo_soft_uart_free(suart); +} + +static void test_tx_pull(void) +{ + struct osmo_soft_uart *suart; + ubit_t tx_buf25 * 2; + int rc; + + SUART_TEST_BEGIN; + + g_tx_cb_cfg.data = (void *)"\x42\x42\x42\x42\x42"; + g_tx_cb_cfg.data_len = 5; + + suart = osmo_soft_uart_alloc(NULL, __func__, &suart_test_default_cfg); + OSMO_ASSERT(suart != NULL); + + osmo_soft_uart_set_tx(suart, true); + + printf("pulling 25 bits (first time) out of the transmitter\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf0, sizeof(tx_buf) / 2); + OSMO_ASSERT(rc == 25); + + printf("pulling 25 bits (second time) out of the transmitter\n"); + rc = osmo_soft_uart_tx_ubits(suart, &tx_buf25, sizeof(tx_buf) / 2); + OSMO_ASSERT(rc == 25); + + /* FIXME: we pull total 25 + 25 == 50 bits out of the transmitter, which is enough + * to fit 5 characters (assuming 8-N-1). However, the current impelementation would + * pull only 2 + 2 == characters total, wasting 5 + 5 == 10 bits for padding. */ + + osmo_soft_uart_free(suart); +} + +int main(int argc, char **argv) +{ + test_rx(); + test_rx_flush(); + test_tx_rx(); + + /* test pulling small number of bits at a time */ + test_tx_rx_pull_n(1); + test_tx_rx_pull_n(2); + test_tx_rx_pull_n(4); + test_tx_rx_pull_n(8); + + test_tx_pull(); + + /* test flow control */ + test_modem_status(); + test_flow_control_dtr_dsr(); + test_flow_control_rts_cts(); + + return 0; +}
View file
libosmocore_1.10.0.tar.xz/tests/soft_uart/soft_uart_test.ok
Added
@@ -0,0 +1,278 @@ + +Executing test_rx +======== testing 8-N-1 (no data) +test_rx_exec() @ 0: flush the Rx buffer +test_rx_exec() @ 6: flush the Rx buffer +test_rx_exec() @ 12: flush the Rx buffer +======== testing 8-N-1 (fill up flush) +suart_rx_cb(flags=00): de ad be ef +suart_rx_cb(flags=00): 00 aa 55 ff +test_rx_exec() @ 101: flush the Rx buffer +======== testing 8-N-1 (HELLO) +test_rx_exec() @ 18: flush the Rx buffer +suart_rx_cb(flags=00): 48 +test_rx_exec() @ 31: flush the Rx buffer +suart_rx_cb(flags=00): 45 +test_rx_exec() @ 57: flush the Rx buffer +suart_rx_cb(flags=00): 4c +test_rx_exec() @ 70: flush the Rx buffer +suart_rx_cb(flags=00): 4c +test_rx_exec() @ 96: flush the Rx buffer +suart_rx_cb(flags=00): 4f +======== testing 8-N-1 (framing errors) +suart_rx_cb(flags=01): 00 +suart_rx_cb(flags=01): aa +test_rx_exec() @ 41: flush the Rx buffer +suart_rx_cb(flags=00): ff +======== testing 8-N-2 (HELLO) +test_rx_exec() @ 20: flush the Rx buffer +test_rx_exec() @ 22: flush the Rx buffer +suart_rx_cb(flags=00): 48 +test_rx_exec() @ 35: flush the Rx buffer +test_rx_exec() @ 37: flush the Rx buffer +suart_rx_cb(flags=00): 45 +test_rx_exec() @ 65: flush the Rx buffer +test_rx_exec() @ 67: flush the Rx buffer +suart_rx_cb(flags=00): 4c +test_rx_exec() @ 80: flush the Rx buffer +test_rx_exec() @ 82: flush the Rx buffer +suart_rx_cb(flags=00): 4c +test_rx_exec() @ 110: flush the Rx buffer +test_rx_exec() @ 112: flush the Rx buffer +suart_rx_cb(flags=00): 4f +======== testing 8-N-2 (framing errors) +suart_rx_cb(flags=01): 00 +suart_rx_cb(flags=01): aa +suart_rx_cb(flags=01): 55 +test_rx_exec() @ 57: flush the Rx buffer +suart_rx_cb(flags=00): ff +======== testing 8-E-1 (invalid parity) +suart_rx_cb(flags=02): 00 +suart_rx_cb(flags=02): 01 +suart_rx_cb(flags=02): ff +test_rx_exec() @ 49: flush the Rx buffer +======== testing 8-E-1 (valid parity) +test_rx_exec() @ 63: flush the Rx buffer +suart_rx_cb(flags=00): 00 ff aa 55 +test_rx_exec() @ 120: flush the Rx buffer +suart_rx_cb(flags=00): 80 e0 f8 fe +======== testing 8-O-1 (invalid parity) +suart_rx_cb(flags=02): 00 +suart_rx_cb(flags=02): 01 +suart_rx_cb(flags=02): ff +test_rx_exec() @ 42: flush the Rx buffer +======== testing 8-O-1 (valid parity) +test_rx_exec() @ 63: flush the Rx buffer +suart_rx_cb(flags=00): 00 ff aa 55 +test_rx_exec() @ 120: flush the Rx buffer +suart_rx_cb(flags=00): 80 e0 f8 fe + +Executing test_rx_flush +calling osmo_soft_uart_flush_rx() while Rx disabled +enabling the receiver +calling osmo_soft_uart_flush_rx() while Rx enabled, but no data +testing corner case: manual flushing during a parity error (8-E-1) +test_rx_exec() @ 47: flush the Rx buffer +suart_rx_cb(flags=02): aa 55 +suart_rx_cb(flags=02): ff + +Executing test_tx_rx +======== testing 8-N-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=40): 0011110111 0101101011 0011111011 0111101111 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=40): 0000000001 0010101011 0101010101 0111111111 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=40): 0100000001 0010000001 0001000001 0000100001 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=40): 0000010001 0000001001 0000000101 0000000011 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=40): 1111111111 1111111111 1111111111 1111111111 +======== testing 8-N-2 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=44): 00111101111 01011010111 00111110111 01111011111 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=44): 00000000011 00101010111 01010101011 01111111111 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=44): 01000000011 00100000011 00010000011 00001000011 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=44): 00000100011 00000010011 00000001011 00000000111 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=44): 11111111111 11111111111 11111111111 11111111111 +======== testing 8-E-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=44): 00111101101 01011010111 00111110101 01111011111 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=44): 00000000001 00101010101 01010101001 01111111101 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=44): 01000000011 00100000011 00010000011 00001000011 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=44): 00000100011 00000010011 00000001011 00000000111 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=44): 11111111111 11111111111 11111111111 11111111111 +======== testing 8-O-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=44): 00111101111 01011010101 00111110111 01111011101 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=44): 00000000011 00101010111 01010101011 01111111111 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=44): 01000000001 00100000001 00010000001 00001000001 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=44): 00000100001 00000010001 00000001001 00000000101 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=44): 11111111111 11111111111 11111111111 11111111111 +======== testing 8-M-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=44): 00111101111 01011010111 00111110111 01111011111 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=44): 00000000011 00101010111 01010101011 01111111111 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=44): 01000000011 00100000011 00010000011 00001000011 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=44): 00000100011 00000010011 00000001011 00000000111 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=44): 11111111111 11111111111 11111111111 11111111111 +======== testing 8-S-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): de ad be ef +test_tx_rx_exec_one(n_bits_total=44): 00111101101 01011010101 00111110101 01111011101 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 aa 55 ff +test_tx_rx_exec_one(n_bits_total=44): 00000000001 00101010101 01010101001 01111111101 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=44): 01000000001 00100000001 00010000001 00001000001 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 40 80 +test_tx_rx_exec_one(n_bits_total=44): 00000100001 00000010001 00000001001 00000000101 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=44): 11111111111 11111111111 11111111111 11111111111 +======== testing 6-N-1 +suart_tx_cb(len=4/4): de ad be ef +suart_rx_cb(flags=00): 1e 2d 3e 2f +test_tx_rx_exec_one(n_bits_total=32): 00111101 01011011 00111111 01111011 +suart_tx_cb(len=4/4): 00 aa 55 ff +suart_rx_cb(flags=00): 00 2a 15 3f +test_tx_rx_exec_one(n_bits_total=32): 00000001 00101011 01010101 01111111 +suart_tx_cb(len=4/4): 01 02 04 08 +suart_rx_cb(flags=00): 01 02 04 08 +test_tx_rx_exec_one(n_bits_total=32): 01000001 00100001 00010001 00001001 +suart_tx_cb(len=4/4): 10 20 40 80 +suart_rx_cb(flags=00): 10 20 00 00 +test_tx_rx_exec_one(n_bits_total=32): 00000101 00000011 00000001 00000001 +suart_tx_cb(len=0/4): +test_tx_rx_exec_one(n_bits_total=32): 11111111 11111111 11111111 11111111 + +Executing test_tx_rx_pull_n +======== pulling 32 bits (1 at a time) +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +01010101010101010101010101010101 +======== feeding 32 bits into the receiver +suart_rx_cb(flags=00): 55 55 55 + +Executing test_tx_rx_pull_n +======== pulling 32 bits (2 at a time) +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +01010101010101010101010101010101 +======== feeding 32 bits into the receiver +suart_rx_cb(flags=00): 55 55 55 + +Executing test_tx_rx_pull_n +======== pulling 32 bits (4 at a time) +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +01010101011101010101011101010101 +======== feeding 32 bits into the receiver +suart_rx_cb(flags=00): 55 55 + +Executing test_tx_rx_pull_n +======== pulling 32 bits (8 at a time) +suart_tx_cb(len=1/1): 55 +suart_tx_cb(len=1/1): 55 +01010101011111110101010101111111 +======== feeding 32 bits into the receiver +suart_rx_cb(flags=00): 55 55 + +Executing test_tx_pull +pulling 25 bits (first time) out of the transmitter +suart_tx_cb(len=2/2): 42 42 +pulling 25 bits (second time) out of the transmitter +suart_tx_cb(len=2/2): 42 42 + +Executing test_modem_status +initial status=0x00000000 +de-asserting DCD, which was not asserted +asserting both RI and DCD, expecting the callback to be called twice +suart_status_change_cb(status=0x00000008) +suart_status_change_cb(status=0x0000000a) +de-asserting RI, expecting the callback to be called +suart_status_change_cb(status=0x00000002) +resetting to 0x00, expecting the callback to be called +suart_status_change_cb(status=0x00000000) + +Executing test_flow_control_dtr_dsr +initial status=0x00000000 +expecting osmo_soft_uart_tx_ubits() to yield nothing +expecting osmo_soft_uart_rx_ubits() to yield nothing +======== asserting both DTR and DSR +suart_status_change_cb(status=0x00000001) +suart_status_change_cb(status=0x00000005) +expecting osmo_soft_uart_tx_ubits() to yield 40 bits (requesting 40 bits) +suart_tx_cb(len=4/4): 42 42 42 42 +0010000101001000010100100001010010000101 +expecting osmo_soft_uart_rx_ubits() to consume 40 bits and yield 4 chars +suart_rx_cb(flags=00): 42 42 42 42 +expecting osmo_soft_uart_tx_ubits() to yield 2 bits (requesting 2 bits) +suart_tx_cb(len=1/1): 42 +======== de-asserting DSR +suart_status_change_cb(status=0x00000001) +expecting osmo_soft_uart_tx_ubits() to yield 8 bits (requesting 40 bits) +expecting osmo_soft_uart_rx_ubits() to consume 40 bits and yield a pending char +suart_rx_cb(flags=00): 42 + +Executing test_flow_control_rts_cts +initial status=0x00000000 +expecting osmo_soft_uart_tx_ubits() to yield nothing +expecting osmo_soft_uart_rx_ubits() to yield nothing +======== asserting both CTS and RTS/RTR +suart_status_change_cb(status=0x00000020) +suart_status_change_cb(status=0x00000030) +expecting osmo_soft_uart_tx_ubits() to yield 40 bits (requesting 40 bits) +suart_tx_cb(len=4/4): 42 42 42 42 +0010000101001000010100100001010010000101 +expecting osmo_soft_uart_rx_ubits() to consume 40 bits and yield 4 chars +suart_rx_cb(flags=00): 42 42 42 42 +expecting osmo_soft_uart_tx_ubits() to yield 2 bits (requesting 2 bits) +suart_tx_cb(len=1/1): 42 +======== de-asserting CTS +suart_status_change_cb(status=0x00000010) +expecting osmo_soft_uart_tx_ubits() to yield 8 bits (requesting 40 bits) +expecting osmo_soft_uart_rx_ubits() to consume 40 bits and yield a pending char +suart_rx_cb(flags=00): 42
View file
libosmocore_1.9.3.tar.xz/tests/tdef/tdef_test.c -> libosmocore_1.10.0.tar.xz/tests/tdef/tdef_test.c
Changed
@@ -37,6 +37,9 @@ { .T=3, .default_val=50, .unit=OSMO_TDEF_M, .desc="50m" }, { .T=4, .default_val=100, .unit=OSMO_TDEF_CUSTOM, .desc="100 potatoes" }, + { .T=-5, .default_val=100, .unit=OSMO_TDEF_MS, .desc="X-100ms" }, + { .T=-6, .default_val=100, .unit=OSMO_TDEF_US, .desc="X-100us" }, + { .T=7, .default_val=50, .desc="Water Boiling Timeout", .min_val=20, .max_val=800 }, // default is .unit=OSMO_TDEF_S == 0 { .T=8, .default_val=300, .desc="Tea brewing" }, { .T=9, .default_val=5, .unit=OSMO_TDEF_M, .desc="Let tea cool down before drinking" }, @@ -83,14 +86,15 @@ printf("osmo_tdef_get(%d, %s)\t= %lu\n", T, osmo_tdef_unit_name(AS_UNIT), val); \ } while (0) -void print_tdef_info(unsigned int T) +void print_tdef_info(int T) { const struct osmo_tdef *t = osmo_tdef_get_entry(tdefs, T); if (!t) { - printf("T%d=NULL", T); + printf(OSMO_T_FMT "=NULL", OSMO_T_FMT_ARGS(T)); return; } - printf("T%d=%lu%s", T, t->val, osmo_tdef_unit_name(t->unit)); + printf(OSMO_T_FMT "=%lu%s", + OSMO_T_FMT_ARGS(T), t->val, osmo_tdef_unit_name(t->unit)); if (t->val != t->default_val) printf("(def=%lu)", t->default_val); printf("\n"); @@ -106,7 +110,7 @@ osmo_tdefs_reset(tdefs); // make all values the default for (i = 0; i < ARRAY_SIZE(tdefs)-1; i++) { - unsigned int T = tdefsi.T; + int T = tdefsi.T; print_tdef_info(T); for (as_unit = OSMO_TDEF_S; as_unit <= OSMO_TDEF_US; as_unit++) { print_tdef_get_short(tdefs, T, as_unit); @@ -117,7 +121,7 @@ return; for (i = 0; i < ARRAY_SIZE(tdefs_range)-1; i++) { - unsigned int T = tdefs_rangei.T; + int T = tdefs_rangei.T; print_tdef_info(T); for (as_unit = OSMO_TDEF_S; as_unit <= OSMO_TDEF_US; as_unit++) { print_tdef_get_short(tdefs_range, T, as_unit); @@ -196,6 +200,8 @@ S_B, S_C, S_D, + S_E, + S_F, S_G, S_H, S_I, @@ -205,6 +211,7 @@ S_M, S_N, S_O, + /* ... gap ... */ S_X, S_Y, S_Z, @@ -216,6 +223,9 @@ S_C = { .T = 3 }, S_D = { .T = 4 }, + S_E = { .T = -5 }, + S_F = { .T = -6 }, + S_G = { .T = 7 }, S_H = { .T = 8 }, S_I = { .T = 9 }, @@ -246,31 +256,15 @@ #define DEF_STATE(NAME) \ S_##NAME = { \ .name = #NAME, \ - .out_state_mask = 0 \ - | S(S_A) \ - | S(S_B) \ - | S(S_C) \ - | S(S_D) \ - | S(S_G) \ - | S(S_H) \ - | S(S_I) \ - | S(S_J) \ - | S(S_K) \ - | S(S_L) \ - | S(S_M) \ - | S(S_N) \ - | S(S_O) \ - | S(S_X) \ - | S(S_Y) \ - | S(S_Z) \ - , \ + .out_state_mask = 0xffffffff, \ } DEF_STATE(A), DEF_STATE(B), DEF_STATE(C), DEF_STATE(D), - + DEF_STATE(E), + DEF_STATE(F), DEF_STATE(G), DEF_STATE(H), DEF_STATE(I), @@ -354,9 +348,9 @@ osmo_fsm_state_name(&test_tdef_fsm, NEXT_STATE), rc); \ } else { \ struct osmo_tdef *t = osmo_tdef_get_entry(tdefs, st->T); \ - printf(" --> %s (configured as T%d%s %lu %s) rc=%d;\t", \ + printf(" --> %s (configured as " OSMO_T_FMT "%s %lu %s) rc=%d;\t", \ osmo_fsm_state_name(&test_tdef_fsm, NEXT_STATE), \ - st->T, st->keep_timer ? "(keep_timer)" : "", \ + OSMO_T_FMT_ARGS(st->T), st->keep_timer ? " (keep_timer)" : "", \ t? t->val : 0, t? osmo_tdef_unit_name(t->unit) : "-", \ rc); \ } \ @@ -383,7 +377,8 @@ test_tdef_fsm_state_chg(tdefs, S_B); test_tdef_fsm_state_chg(tdefs, S_C); test_tdef_fsm_state_chg(tdefs, S_D); - + test_tdef_fsm_state_chg(tdefs, S_E); + test_tdef_fsm_state_chg(tdefs, S_F); test_tdef_fsm_state_chg(tdefs, S_G); test_tdef_fsm_state_chg(tdefs, S_H); test_tdef_fsm_state_chg(tdefs, S_I); @@ -475,9 +470,16 @@ osmo_init_logging2(ctx, NULL); log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_print_level(osmo_stderr_target, 1); log_set_print_category(osmo_stderr_target, 1); + log_set_print_category_hex(osmo_stderr_target, 0); log_set_use_color(osmo_stderr_target, 0); + osmo_fsm_log_addr(false); + osmo_fsm_log_timeouts(true); + + log_set_category_filter(osmo_stderr_target, DLGLOBAL, 1, LOGL_DEBUG); + OSMO_ASSERT(osmo_fsm_register(&test_tdef_fsm) == 0); test_tdef_get(argc > 1);
View file
libosmocore_1.10.0.tar.xz/tests/tdef/tdef_test.err
Added
@@ -0,0 +1,25 @@ +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){A}: Allocated +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){A}: State change to A (T1, 100s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){A}: State change to B (T2, 100ms) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){B}: State change to C (T3, 3000s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){C}: State change to D (T4, 100s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){D}: State change to E (X5, 100ms) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){E}: State change to F (X6, 1ms) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){F}: State change to G (T7, 50s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){G}: State change to H (T8, 300s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){H}: State change to I (T9, 300s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){I}: State change to J (T10, 1200s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){J}: State change to K (keeping T10, 1076.954s remaining) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){K}: State change to A (T1, 100s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){A}: State change to K (keeping T1, 76.954s remaining) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){K}: State change to A (T1, 100s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){A}: State change to L (keeping T1, 76.954s remaining) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){L}: State change to O (no timeout) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){O}: State change to L (T123, 1s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){L}: State change to O (no timeout) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){O}: State change to X (no timeout) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){X}: State change to Y (T666, 999s) +DLGLOBAL DEBUG tdef_test(test_tdef_state_timeout){Y}: State change to Z (no timeout) +DLGLOBAL ERROR tdef_test(test_tdef_state_timeout){Z}: transition to state B not permitted! +DLGLOBAL ERROR tdef_test(test_tdef_state_timeout){Z}: transition to state C not permitted! +DLGLOBAL ERROR tdef_test(test_tdef_state_timeout){Z}: transition to state D not permitted!
View file
libosmocore_1.9.3.tar.xz/tests/tdef/tdef_test.ok -> libosmocore_1.10.0.tar.xz/tests/tdef/tdef_test.ok
Changed
@@ -24,6 +24,18 @@ osmo_tdef_get(4, m) = 100 osmo_tdef_get(4, custom-unit) = 100 osmo_tdef_get(4, us) = 100 +X5=100ms +osmo_tdef_get(-5, s) = 1 +osmo_tdef_get(-5, ms) = 100 +osmo_tdef_get(-5, m) = 1 +osmo_tdef_get(-5, custom-unit) = 100 +osmo_tdef_get(-5, us) = 100000 +X6=100us +osmo_tdef_get(-6, s) = 1 +osmo_tdef_get(-6, ms) = 1 +osmo_tdef_get(-6, m) = 1 +osmo_tdef_get(-6, custom-unit) = 100 +osmo_tdef_get(-6, us) = 100 T7=50s osmo_tdef_get(7, s) = 50 osmo_tdef_get(7, ms) = 50000 @@ -153,9 +165,11 @@ test_tdef_state_timeout() state=A T=0, no timeout --> A (configured as T1 100 s) rc=0; state=A T=1, 100.000000 s remaining - --> B (configured as T2 100 ms) rc=0; state=B T=2, 1.000000 s remaining + --> B (configured as T2 100 ms) rc=0; state=B T=2, 0.100000 s remaining --> C (configured as T3 50 m) rc=0; state=C T=3, 3000.000000 s remaining --> D (configured as T4 100 custom-unit) rc=0; state=D T=4, 100.000000 s remaining + --> E (configured as X5 100 ms) rc=0; state=E T=-5, 0.100000 s remaining + --> F (configured as X6 100 us) rc=0; state=F T=-6, 0.001000 s remaining --> G (configured as T7 50 s) rc=0; state=G T=7, 50.000000 s remaining --> H (configured as T8 300 s) rc=0; state=H T=8, 300.000000 s remaining --> I (configured as T9 5 m) rc=0; state=I T=9, 300.000000 s remaining @@ -163,17 +177,17 @@ - test keep_timer: Time passes: 123.045678 s state=J T=10, 1076.954322 s remaining - --> K (configured as T0(keep_timer) 1 custom-unit) rc=0; state=K T=10, 1076.954322 s remaining + --> K (configured as T0 (keep_timer) 1 custom-unit) rc=0; state=K T=10, 1076.954322 s remaining --> A (configured as T1 100 s) rc=0; state=A T=1, 100.000000 s remaining Time passes: 23.045678 s state=A T=1, 76.954322 s remaining - --> K (configured as T0(keep_timer) 1 custom-unit) rc=0; state=K T=1, 76.954322 s remaining + --> K (configured as T0 (keep_timer) 1 custom-unit) rc=0; state=K T=1, 76.954322 s remaining --> A (configured as T1 100 s) rc=0; state=A T=1, 100.000000 s remaining Time passes: 23.045678 s state=A T=1, 76.954322 s remaining - --> L (configured as T123(keep_timer) 1 s) rc=0; state=L T=1, 76.954322 s remaining + --> L (configured as T123 (keep_timer) 1 s) rc=0; state=L T=1, 76.954322 s remaining --> O (no timer configured for this state) rc=0; state=O T=0, no timeout - --> L (configured as T123(keep_timer) 1 s) rc=0; state=L T=123, 1.000000 s remaining + --> L (configured as T123 (keep_timer) 1 s) rc=0; state=L T=123, 1.000000 s remaining - test T=0: --> O (no timer configured for this state) rc=0; state=O T=0, no timeout - test no timer:
View file
libosmocore_1.9.3.tar.xz/tests/testsuite.at -> libosmocore_1.10.0.tar.xz/tests/testsuite.at
Changed
@@ -84,9 +84,8 @@ if ENABLE_MSGFILE AT_SETUP(msgfile) AT_KEYWORDS(msgfile) -cp $abs_srcdir/msgfile/msgconfig.cfg . cat $abs_srcdir/msgfile/msgfile_test.ok > expout -AT_CHECK($abs_top_builddir/tests/msgfile/msgfile_test, 0, expout) +AT_CHECK($abs_top_builddir/tests/msgfile/msgfile_test $abs_srcdir/msgfile/msgconfig.cfg, 0, expout) AT_CLEANUP endif @@ -201,6 +200,12 @@ AT_CHECK($abs_top_builddir/tests/logging/logging_test wqueue, 0, expout, experr) AT_CLEANUP +AT_SETUP(logging_gsmtap) +AT_KEYWORDS(logging_gsmtap) +cat $abs_srcdir/logging/logging_gsmtap_test.err > experr +AT_CHECK($abs_top_builddir/tests/logging/logging_gsmtap_test 3>&1 1>&2 2>&3 |grep -v "enqueueing message failed" 3>&1 1>&2 2>&3 , , ignore, experr) +AT_CLEANUP + AT_SETUP(codec) AT_KEYWORDS(codec) cat $abs_srcdir/codec/codec_test.ok > expout @@ -237,8 +242,7 @@ AT_KEYWORDS(vty) cat $abs_srcdir/vty/vty_test.ok > expout cat $abs_srcdir/vty/vty_test.err > experr -cp $abs_srcdir/vty/*.cfg . -AT_CHECK($abs_top_builddir/tests/vty/vty_test, 0, expout, experr) +AT_CHECK($abs_top_builddir/tests/vty/vty_test $abs_srcdir/vty, 0, expout, experr) AT_CLEANUP AT_SETUP(gprs-bssgp) @@ -256,13 +260,15 @@ AT_SETUP(gprs-ns) AT_KEYWORDS(gprs-ns) cat $abs_srcdir/gb/gprs_ns_test.ok > expout -AT_CHECK($abs_top_builddir/tests/gb/gprs_ns_test, 0, expout, ignore) +cat $abs_srcdir/gb/gprs_ns_test.err > experr +AT_CHECK($abs_top_builddir/tests/gb/gprs_ns_test, 0, expout, experr) AT_CLEANUP AT_SETUP(gprs-ns2) AT_KEYWORDS(gprs-ns2) cat $abs_srcdir/gb/gprs_ns2_test.ok > expout -AT_CHECK($abs_top_builddir/tests/gb/gprs_ns2_test, 0, expout, ignore) +cat $abs_srcdir/gb/gprs_ns2_test.err > experr +AT_CHECK($abs_top_builddir/tests/gb/gprs_ns2_test, 0, expout, experr) AT_CLEANUP AT_SETUP(utils) @@ -355,7 +361,6 @@ AT_KEYWORDS(socket) cat $abs_srcdir/socket/socket_test.ok > expout cat $abs_srcdir/socket/socket_test.err > experr -touch experr AT_CHECK($abs_top_builddir/tests/socket/socket_test, 0, expout, experr) AT_CLEANUP @@ -364,7 +369,6 @@ AT_SKIP_IF(! test -e $abs_top_builddir/tests/socket/socket_sctp_test) cat $abs_srcdir/socket/socket_sctp_test.ok > expout cat $abs_srcdir/socket/socket_sctp_test.err > experr -touch experr AT_CHECK($abs_top_builddir/tests/socket/socket_sctp_test, 0, expout, experr) AT_CLEANUP @@ -408,7 +412,8 @@ AT_SETUP(tdef) AT_KEYWORDS(tdef) cat $abs_srcdir/tdef/tdef_test.ok > expout -AT_CHECK($abs_top_builddir/tests/tdef/tdef_test, 0, expout, ignore) +cat $abs_srcdir/tdef/tdef_test.err > experr +AT_CHECK($abs_top_builddir/tests/tdef/tdef_test, 0, expout, experr) AT_CLEANUP AT_SETUP(sockaddr_str) @@ -488,7 +493,8 @@ AT_SETUP(iuup) AT_KEYWORDS(iuup) cat $abs_srcdir/iuup/iuup_test.ok > expout -AT_CHECK($abs_top_builddir/tests/iuup/iuup_test, 0, expout, ignore) +cat $abs_srcdir/iuup/iuup_test.err > experr +AT_CHECK($abs_top_builddir/tests/iuup/iuup_test, 0, expout, experr) AT_CLEANUP AT_SETUP(v110_frame_test) @@ -503,6 +509,12 @@ AT_CHECK($abs_top_builddir/tests/v110/ra1_test, , expout,) AT_CLEANUP +AT_SETUP(v110_ta_test) +AT_KEYWORDS(v110_ta_test) +cat $abs_srcdir/v110/ta_test.err > experr +AT_CHECK($abs_top_builddir/tests/v110/ta_test, , , experr) +AT_CLEANUP + AT_SETUP(gsm44021_frame_csd_test) AT_KEYWORDS(gsm44021_frame_csd_test) cat $abs_srcdir/gsm44021/frame_csd_test.ok > expout @@ -513,6 +525,31 @@ AT_KEYWORDS(osmo_io) cat $abs_srcdir/osmo_io/osmo_io_test.ok > expout cat $abs_srcdir/osmo_io/osmo_io_test.err > experr -touch experr AT_CHECK($abs_top_builddir/tests/osmo_io/osmo_io_test, 0, expout, experr) AT_CLEANUP + +AT_SETUP(osmo_io (uring)) +AT_KEYWORDS(osmo_io (uring)) +AT_SKIP_IF( test "$ENABLE_URING" != "yes" || test "$ENABLE_URING_TESTS" != "yes" ) +cat $abs_srcdir/osmo_io/osmo_io_test.ok > expout +cat $abs_srcdir/osmo_io/osmo_io_test.err > experr +AT_CHECK(LIBOSMO_IO_BACKEND=IO_URING $abs_top_builddir/tests/osmo_io/osmo_io_test, 0, expout, experr) +AT_CLEANUP + +AT_SETUP(soft_uart) +AT_KEYWORDS(soft_uart) +cat $abs_srcdir/soft_uart/soft_uart_test.ok > expout +AT_CHECK($abs_top_builddir/tests/soft_uart/soft_uart_test, 0, expout, ignore) +AT_CLEANUP + +AT_SETUP(rlp) +AT_KEYWORDS(rlp) +cat $abs_srcdir/rlp/rlp_test.ok > expout +AT_CHECK($abs_top_builddir/tests/rlp/rlp_test, 0, expout, ignore) +AT_CLEANUP + +AT_SETUP(jhash) +AT_KEYWORDS(jhash) +cat $abs_srcdir/jhash/jhash_test.ok > expout +AT_CHECK($abs_top_builddir/tests/jhash/jhash_test, 0, expout, ignore) +AT_CLEANUP
View file
libosmocore_1.9.3.tar.xz/tests/utils/utils_test.c -> libosmocore_1.10.0.tar.xz/tests/utils/utils_test.c
Changed
@@ -31,6 +31,7 @@ #include <errno.h> #include <limits.h> #include <inttypes.h> +#include <string.h> static void hexdump_test(void) { @@ -1279,9 +1280,6 @@ snprintf(buf, sizeof(buf), "0x2b 0x2b 0x2b..."); printf("4: (need %d chars, had size=0) %s\n", rc, buf); - rc = strbuf_example2(NULL, 99); - printf("5: (need %d chars, had NULL buffer)\n", rc); - printf("\ncascade:\n"); rc = strbuf_cascade(buf, sizeof(buf)); printf("(need %d chars)\n%s\n", rc, buf); @@ -1306,6 +1304,67 @@ printf("%zu: %s (need=%zu)\n", sb.len, buf, sb.chars_needed); } +void strbuf_test_tail_for_buflen(size_t buflen) +{ + char bufbuflen; + struct osmo_strbuf sb = { .buf = buf, .len = buflen }; + printf("\n%s(%zu)\n", __func__, buflen); + +#define SHOW(N) \ + printf(#N ": %s sb.chars_needed=%zu sb.pos=&sb.buf%d\n", \ + osmo_quote_str(buf, -1), sb.chars_needed, (int)(sb.pos - sb.buf)) + + /* shorten in steps using OSMO_STRBUF_DROP_TAIL(), removing and re-adding a trailing newline. */ + OSMO_STRBUF_PRINTF(sb, "banananana\n"); + SHOW(1); + OSMO_STRBUF_DROP_TAIL(sb, 3); + SHOW(2); + OSMO_STRBUF_PRINTF(sb, "\n"); + SHOW(3); + OSMO_STRBUF_DROP_TAIL(sb, 3); + SHOW(4); + OSMO_STRBUF_PRINTF(sb, "\n"); + SHOW(5); + + /* drop trailing newline */ + OSMO_STRBUF_DROP_TAIL(sb, 1); + SHOW(6); + + /* test writing something to the end and letting OSMO_STRBUF_ADDED_TAIL() know later */ + int n = OSMO_MIN(6, OSMO_STRBUF_REMAIN(sb)); + if (n) + memcpy(sb.pos, "bread\n", n); + OSMO_STRBUF_ADDED_TAIL(sb, 6); + SHOW(7); +} + +void strbuf_test_tail(void) +{ + strbuf_test_tail_for_buflen(64); + strbuf_test_tail_for_buflen(32); + strbuf_test_tail_for_buflen(16); + strbuf_test_tail_for_buflen(8); + strbuf_test_tail_for_buflen(4); + strbuf_test_tail_for_buflen(1); +} + +void strbuf_test_remain_char_count(void) +{ + char buf20; + struct osmo_strbuf sb = { .buf = buf, .len = sizeof(buf) }; + + printf("\n%s\n", __func__); + + printf("remaining space: %zu\n", OSMO_STRBUF_REMAIN(sb)); + printf("current char count: %zu\n", OSMO_STRBUF_CHAR_COUNT(sb)); + + printf("populating the buffer\n"); + OSMO_STRBUF_PRINTF(sb, "osmocom"); + + printf("remaining space: %zu\n", OSMO_STRBUF_REMAIN(sb)); + printf("current char count: %zu\n", OSMO_STRBUF_CHAR_COUNT(sb)); +} + static void startswith_test_str(const char *str, const char *startswith_str, bool expect_rc) { bool rc = osmo_str_startswith(str, startswith_str); @@ -2152,6 +2211,8 @@ osmo_str_tolowupper_test(); strbuf_test(); strbuf_test_nolen(); + strbuf_test_tail(); + strbuf_test_remain_char_count(); startswith_test(); name_c_impl_test(); osmo_print_n_test();
View file
libosmocore_1.9.3.tar.xz/tests/utils/utils_test.ok -> libosmocore_1.10.0.tar.xz/tests/utils/utils_test.ok
Changed
@@ -458,7 +458,6 @@ 2: (need 42 chars, had size=42) T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off 3: (need 42 chars, had size=42+1) T minus 10 9 8 7 6 5 4 3 2 1 ... Lift off! 4: (need 42 chars, had size=0) 0x2b 0x2b 0x2b... -5: (need 42 chars, had NULL buffer) cascade: (need 134 chars) @@ -470,6 +469,67 @@ more: 0001011100101010000 (need=19) 10: 000101110 (need=9) +strbuf_test_tail_for_buflen(64) +1: "banananana\n" sb.chars_needed=11 sb.pos=&sb.buf11 +2: "bananana" sb.chars_needed=8 sb.pos=&sb.buf8 +3: "bananana\n" sb.chars_needed=9 sb.pos=&sb.buf9 +4: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +5: "banana\n" sb.chars_needed=7 sb.pos=&sb.buf7 +6: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +7: "bananabread\n" sb.chars_needed=12 sb.pos=&sb.buf12 + +strbuf_test_tail_for_buflen(32) +1: "banananana\n" sb.chars_needed=11 sb.pos=&sb.buf11 +2: "bananana" sb.chars_needed=8 sb.pos=&sb.buf8 +3: "bananana\n" sb.chars_needed=9 sb.pos=&sb.buf9 +4: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +5: "banana\n" sb.chars_needed=7 sb.pos=&sb.buf7 +6: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +7: "bananabread\n" sb.chars_needed=12 sb.pos=&sb.buf12 + +strbuf_test_tail_for_buflen(16) +1: "banananana\n" sb.chars_needed=11 sb.pos=&sb.buf11 +2: "bananana" sb.chars_needed=8 sb.pos=&sb.buf8 +3: "bananana\n" sb.chars_needed=9 sb.pos=&sb.buf9 +4: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +5: "banana\n" sb.chars_needed=7 sb.pos=&sb.buf7 +6: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +7: "bananabread\n" sb.chars_needed=12 sb.pos=&sb.buf12 + +strbuf_test_tail_for_buflen(8) +1: "bananan" sb.chars_needed=11 sb.pos=&sb.buf8 +2: "bananan" sb.chars_needed=8 sb.pos=&sb.buf8 +3: "bananan" sb.chars_needed=9 sb.pos=&sb.buf8 +4: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +5: "banana\n" sb.chars_needed=7 sb.pos=&sb.buf7 +6: "banana" sb.chars_needed=6 sb.pos=&sb.buf6 +7: "bananab" sb.chars_needed=12 sb.pos=&sb.buf7 + +strbuf_test_tail_for_buflen(4) +1: "ban" sb.chars_needed=11 sb.pos=&sb.buf4 +2: "ban" sb.chars_needed=8 sb.pos=&sb.buf4 +3: "ban" sb.chars_needed=9 sb.pos=&sb.buf4 +4: "ban" sb.chars_needed=6 sb.pos=&sb.buf4 +5: "ban" sb.chars_needed=7 sb.pos=&sb.buf4 +6: "ban" sb.chars_needed=6 sb.pos=&sb.buf4 +7: "ban" sb.chars_needed=12 sb.pos=&sb.buf4 + +strbuf_test_tail_for_buflen(1) +1: "" sb.chars_needed=11 sb.pos=&sb.buf1 +2: "" sb.chars_needed=8 sb.pos=&sb.buf1 +3: "" sb.chars_needed=9 sb.pos=&sb.buf1 +4: "" sb.chars_needed=6 sb.pos=&sb.buf1 +5: "" sb.chars_needed=7 sb.pos=&sb.buf1 +6: "" sb.chars_needed=6 sb.pos=&sb.buf1 +7: "" sb.chars_needed=12 sb.pos=&sb.buf1 + +strbuf_test_remain_char_count +remaining space: 20 +current char count: 0 +populating the buffer +remaining space: 13 +current char count: 7 + startswith_test() osmo_str_startswith(NULL, NULL) == true osmo_str_startswith("", NULL) == true
View file
libosmocore_1.10.0.tar.xz/tests/v110/ta_test.c
Added
@@ -0,0 +1,459 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> + * + * All Rights Reserved + * + * 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 2 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. + * + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> + +#include <osmocom/core/fsm.h> +#include <osmocom/core/bits.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/application.h> + +#include <osmocom/isdn/v110.h> +#include <osmocom/isdn/v110_ta.h> + +static void *test_ctx = NULL; + +/* inverse logic: ON = binary 0; OFF = binary 1 */ +#define V110_SX_BIT_ON 0 +#define V110_SX_BIT_OFF 1 + +/********************************************************************************* + * V.110 TA configuration and callbacks + *********************************************************************************/ + +static void v110_ta_test_rx_cb(void *priv, const ubit_t *buf, size_t buf_size) +{ + fprintf(stderr, "%s(buf_size=%zu): %s\n", + __func__, buf_size, osmo_ubit_dump(buf, buf_size)); +} + +static void v110_ta_test_tx_cb(void *priv, ubit_t *buf, size_t buf_size) +{ + for (size_t i = 0; i < buf_size; i++) + bufi = (i & 1); + fprintf(stderr, "%s(buf_size=%zu): %s\n", + __func__, buf_size, osmo_ubit_dump(buf, buf_size)); +} + +static void v110_ta_test_status_update_cb(void *priv, unsigned int status) +{ + fprintf(stderr, "%s(status=0x%08x)\n", __func__, status); +} + +static const struct osmo_v110_ta_cfg v110_ta_test_cfg = { + .rate = OSMO_V110_SYNC_RA1_9600, + .rx_cb = &v110_ta_test_rx_cb, + .tx_cb = &v110_ta_test_tx_cb, + .status_update_cb = &v110_ta_test_status_update_cb, +}; + +/********************************************************************************* + * various helper functions + *********************************************************************************/ + +static void v110_ta_test_init_df(struct osmo_v110_decoded_frame *df) +{ + /* quickly set all the bits to binary '1' */ + memset(df, 1, sizeof(*df)); + /* D-bits: 0101... pattern */ + for (unsigned int i = 0; i < MAX_D_BITS; i += 2) + df->d_bitsi = 0; + /* E-bits: E1/E2/E3 indicate 9600 bps */ + df->e_bits0 = 0; +} + +static void v110_ta_test_dump_df(const struct osmo_v110_decoded_frame *df) +{ + fprintf(stderr, " D-bits: %s\n", osmo_ubit_dump(&df->d_bits0, MAX_D_BITS)); + fprintf(stderr, " E-bits: %s\n", osmo_ubit_dump(&df->e_bits0, MAX_E_BITS)); + fprintf(stderr, " S-bits: %s\n", osmo_ubit_dump(&df->s_bits0, MAX_S_BITS)); + fprintf(stderr, " X-bits: %s\n", osmo_ubit_dump(&df->x_bits0, MAX_X_BITS)); +} + +static void v110_ta_test_dump_circuit(const struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit, + bool exp_state) +{ + bool state = osmo_v110_ta_get_circuit(ta, circuit); + + fprintf(stderr, "circuit %s (%s) is %s (expected to be %s)\n", + osmo_v110_ta_circuit_name(circuit), + osmo_v110_ta_circuit_desc(circuit), + state ? "ON" : "OFF", + exp_state ? "ON" : "OFF"); +} + +static void v110_ta_test_set_circuit(struct osmo_v110_ta *ta, + enum osmo_v110_ta_circuit circuit, + bool active) +{ + int rc; + + fprintf(stderr, "setting circuit %s (%s) %s\n", + osmo_v110_ta_circuit_name(circuit), + osmo_v110_ta_circuit_desc(circuit), + active ? "ON" : "OFF"); + + rc = osmo_v110_ta_set_circuit(ta, circuit, active); + fprintf(stderr, "osmo_v110_ta_set_circuit() returns %d\n", rc); +} + +/********************************************************************************* + * the actual tests + *********************************************************************************/ + +static void test_idle_ready(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + fprintf(stderr, "Initial status: 0x%08x\n", osmo_v110_ta_get_status(ta)); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_106, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, false); + + fprintf(stderr, "osmo_v110_ta_frame_in(): all bits set to binary '1'\n"); + memset(&df, 1, sizeof(df)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + fprintf(stderr, "osmo_v110_ta_frame_out(): expecting all bits set to binary '1'\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, true); + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, false); + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, true); + + osmo_v110_ta_free(ta); +} + +static void test_conn_ta_line(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, true); + + /* we expect the TA FSM to be in V110_TA_ST_CON_TA_TO_LINE */ + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-/X-bits are expected to be 1 (OFF)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): D-/E-bits are all expected to be 1\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + /* TODO: test implicit sync by sending V110_TA_EV_RX_FRAME_IND */ + + fprintf(stderr, "osmo_v110_ta_sync_ind(): the lower layer indicates sync event\n"); + osmo_v110_ta_sync_ind(ta); + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-/X-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): D-/E-bits are all expected to be 1\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + fprintf(stderr, "osmo_v110_ta_frame_in(): S-/X-bits are OFF, expect no state change\n"); + v110_ta_test_init_df(&df); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + fprintf(stderr, "osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change\n"); + memset(&df.s_bits0, V110_SX_BIT_ON, sizeof(df.s_bits)); + memset(&df.x_bits0, V110_SX_BIT_ON, sizeof(df.x_bits)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + osmo_v110_ta_free(ta); +} + +static void _test_data_transfer_enter(struct osmo_v110_ta *ta) +{ + struct osmo_v110_decoded_frame df; + int rc; + + OSMO_ASSERT(osmo_v110_ta_get_circuit(ta, OSMO_V110_TA_C_108) == false); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, true); + + /* we expect the TA FSM to be in V110_TA_ST_CON_TA_TO_LINE */ + + fprintf(stderr, "osmo_v110_ta_sync_ind(): the lower layer indicates sync event\n"); + osmo_v110_ta_sync_ind(ta); + + fprintf(stderr, "osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change\n"); + v110_ta_test_init_df(&df); + memset(&df.s_bits0, V110_SX_BIT_ON, sizeof(df.s_bits)); + memset(&df.x_bits0, V110_SX_BIT_ON, sizeof(df.x_bits)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ +} + +static void test_data_transfer(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + _test_data_transfer_enter(ta); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_106, true); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, true); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, true); + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-/X-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): E1..E3-bits are expected to be 011 (9600)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): we also expect the .tx_cb() to be called\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + fprintf(stderr, "osmo_v110_ta_frame_in(): feed that frame that we pulled out back into the TA\n"); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + osmo_v110_ta_free(ta); +} + +static void test_data_transfer_disc_local(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + _test_data_transfer_enter(ta); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + fprintf(stderr, "local TE initiates disconnection\n"); + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, false); + + /* we expect the TA FSM to be in V110_TA_ST_DISCONNECTING */ + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-bits are expected to be 1 (OFF)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): X-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): D-bits are all expected to be 0\n"); + rc = osmo_v110_ta_frame_out(ta, &df); /* TODO: what E-bits do we expect? */ + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_106, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, true); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, true); + + fprintf(stderr, "osmo_v110_ta_frame_in(): S-/X-bits are ON, expect no state change\n"); + v110_ta_test_init_df(&df); + memset(&df.s_bits0, V110_SX_BIT_ON, sizeof(df.s_bits)); + memset(&df.x_bits0, V110_SX_BIT_ON, sizeof(df.x_bits)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + fprintf(stderr, "osmo_v110_ta_frame_in(): S-bits are OFF, expect state change\n"); + v110_ta_test_init_df(&df); + memset(&df.s_bits0, V110_SX_BIT_OFF, sizeof(df.s_bits)); + memset(&df.x_bits0, V110_SX_BIT_ON, sizeof(df.x_bits)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_106, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, false); + + osmo_v110_ta_free(ta); +} + +static void test_data_transfer_disc_remote(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + _test_data_transfer_enter(ta); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + fprintf(stderr, "remote TE initiates disconnection\n"); + fprintf(stderr, "osmo_v110_ta_frame_in(): S-bits are OFF, X-bits are ON\n"); + fprintf(stderr, "osmo_v110_ta_frame_in(): D-bits are all set to 0\n"); + v110_ta_test_init_df(&df); + memset(&df.s_bits0, V110_SX_BIT_OFF, sizeof(df.s_bits)); + memset(&df.x_bits0, V110_SX_BIT_ON, sizeof(df.x_bits)); + memset(&df.d_bits0, 0, sizeof(df.d_bits)); + v110_ta_test_dump_df(&df); + rc = osmo_v110_ta_frame_in(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_in() returns %d\n", rc); + + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, false); + + fprintf(stderr, "local TE confirms disconnection\n"); + v110_ta_test_set_circuit(ta, OSMO_V110_TA_C_108, false); + + /* we expect the TA FSM to be in V110_TA_ST_DISCONNECTING */ + + osmo_v110_ta_desync_ind(ta); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_106, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_107, false); + v110_ta_test_dump_circuit(ta, OSMO_V110_TA_C_109, false); + + osmo_v110_ta_free(ta); +} + +static void test_syncing(void) +{ + struct osmo_v110_decoded_frame df = { 0 }; + struct osmo_v110_ta *ta; + int rc; + + fprintf(stderr, "\n==== Running %s()\n", __func__); + + ta = osmo_v110_ta_alloc(test_ctx, __func__, &v110_ta_test_cfg); + OSMO_ASSERT(ta != NULL); + + /* we expect the TA FSM to be in V110_TA_ST_IDLE_READY */ + + _test_data_transfer_enter(ta); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + fprintf(stderr, "osmo_v110_ta_sync_ind(): the lower layer indicates out-of-sync event\n"); + osmo_v110_ta_desync_ind(ta); + + /* we expect the TA FSM to be in V110_TA_ST_RESYNCING */ + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): X-bits are expected to be 1 (OFF)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): D-bits are to be set by .tx_cb()\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + fprintf(stderr, "osmo_v110_ta_sync_ind(): the lower layer indicates sync event\n"); + osmo_v110_ta_sync_ind(ta); + + /* we expect the TA FSM to be in V110_TA_ST_DATA_TRANSFER */ + + fprintf(stderr, "osmo_v110_ta_frame_out(): S-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): X-bits are expected to be 0 (ON)\n"); + fprintf(stderr, "osmo_v110_ta_frame_out(): D-bits are to be set by .tx_cb()\n"); + rc = osmo_v110_ta_frame_out(ta, &df); + fprintf(stderr, "osmo_v110_ta_frame_out() returns %d\n", rc); + if (rc == 0) + v110_ta_test_dump_df(&df); + + osmo_v110_ta_free(ta); +} + +int main(int argc, char **argv) +{ + test_ctx = talloc_named_const(NULL, 0, __FILE__); + + osmo_init_logging2(test_ctx, NULL); + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_print_level(osmo_stderr_target, 1); + log_set_print_category(osmo_stderr_target, 1); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_use_color(osmo_stderr_target, 0); + + osmo_fsm_log_addr(false); + osmo_fsm_log_timeouts(true); + + log_set_category_filter(osmo_stderr_target, DLGLOBAL, 1, LOGL_DEBUG); + + test_idle_ready(); + test_conn_ta_line(); + /* TODO: test_conn_ta_line_timeout() */ + test_data_transfer(); + test_data_transfer_disc_local(); + test_data_transfer_disc_remote(); + /* TODO: test_disc_timeout() */ + test_syncing(); + /* TODO: test_syncing_timeout() */ + + log_fini(); + OSMO_ASSERT(talloc_total_blocks(test_ctx) == 1); + talloc_free(test_ctx); + + return 0; +}
View file
libosmocore_1.10.0.tar.xz/tests/v110/ta_test.err
Added
@@ -0,0 +1,270 @@ + +==== Running test_idle_ready() +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: State change to IDLE_READY (no timeout) +Initial status: 0x00000000 +circuit 106/CTS (Clear to Send) is OFF (expected to be OFF) +circuit 107/DSR (Data Set Ready) is OFF (expected to be OFF) +circuit 109/DCD (Data Carrier Detect) is OFF (expected to be OFF) +osmo_v110_ta_frame_in(): all bits set to binary '1' + D-bits: 111111111111111111111111111111111111111111111111 + E-bits: 1111111 + S-bits: 111111111 + X-bits: 11 +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: Received Event RX_FRAME_IND +v110_ta_test_rx_cb(buf_size=48): 111111111111111111111111111111111111111111111111 +osmo_v110_ta_frame_in() returns 0 +osmo_v110_ta_frame_out(): expecting all bits set to binary '1' +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: Received Event TX_FRAME_RTS +osmo_v110_ta_frame_out() returns 0 + D-bits: 111111111111111111111111111111111111111111111111 + E-bits: 1111111 + S-bits: 111111111 + X-bits: 11 +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +setting circuit 108/DTR (Data Terminal Ready) OFF +DLGLOBAL DEBUG V110-TA(test_idle_ready){CONNECT_TA_TO_LINE}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_idle_ready){CONNECT_TA_TO_LINE}: State change to IDLE_READY (no timeout) +osmo_v110_ta_set_circuit() returns 0 +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_idle_ready){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +DLGLOBAL DEBUG V110-TA(test_idle_ready){CONNECT_TA_TO_LINE}: Deallocated + +==== Running test_conn_ta_line() +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){IDLE_READY}: State change to IDLE_READY (no timeout) +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_frame_out(): S-/X-bits are expected to be 1 (OFF) +osmo_v110_ta_frame_out(): D-/E-bits are all expected to be 1 +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: Received Event TX_FRAME_RTS +osmo_v110_ta_frame_out() returns 0 + D-bits: 111111111111111111111111111111111111111111111111 + E-bits: 1111111 + S-bits: 111111111 + X-bits: 11 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: Received Event SYNC_IND +osmo_v110_ta_frame_out(): S-/X-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): D-/E-bits are all expected to be 1 +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: Received Event TX_FRAME_RTS +osmo_v110_ta_frame_out() returns 0 + D-bits: 111111111111111111111111111111111111111111111111 + E-bits: 1111111 + S-bits: 000000000 + X-bits: 00 +osmo_v110_ta_frame_in(): S-/X-bits are OFF, expect no state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 111111111 + X-bits: 11 +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_rx_cb(buf_size=48): 111111111111111111111111111111111111111111111111 +osmo_v110_ta_frame_in() returns 0 +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000001e) +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){CONNECT_TA_TO_LINE}: State change to DATA_TRANSFER (no timeout) +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +DLGLOBAL DEBUG V110-TA(test_conn_ta_line){DATA_TRANSFER}: Deallocated + +==== Running test_data_transfer() +DLGLOBAL DEBUG V110-TA(test_data_transfer){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_data_transfer){IDLE_READY}: State change to IDLE_READY (no timeout) +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_data_transfer){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_data_transfer){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_data_transfer){CONNECT_TA_TO_LINE}: Received Event SYNC_IND +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000001e) +DLGLOBAL DEBUG V110-TA(test_data_transfer){CONNECT_TA_TO_LINE}: State change to DATA_TRANSFER (no timeout) +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +circuit 106/CTS (Clear to Send) is ON (expected to be ON) +circuit 107/DSR (Data Set Ready) is ON (expected to be ON) +circuit 109/DCD (Data Carrier Detect) is ON (expected to be ON) +osmo_v110_ta_frame_out(): S-/X-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): E1..E3-bits are expected to be 011 (9600) +osmo_v110_ta_frame_out(): we also expect the .tx_cb() to be called +DLGLOBAL DEBUG V110-TA(test_data_transfer){DATA_TRANSFER}: Received Event TX_FRAME_RTS +v110_ta_test_tx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_out() returns 0 + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +osmo_v110_ta_frame_in(): feed that frame that we pulled out back into the TA +DLGLOBAL DEBUG V110-TA(test_data_transfer){DATA_TRANSFER}: Received Event RX_FRAME_IND +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +DLGLOBAL DEBUG V110-TA(test_data_transfer){DATA_TRANSFER}: Deallocated + +==== Running test_data_transfer_disc_local() +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){IDLE_READY}: State change to IDLE_READY (no timeout) +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){CONNECT_TA_TO_LINE}: Received Event SYNC_IND +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000001e) +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){CONNECT_TA_TO_LINE}: State change to DATA_TRANSFER (no timeout) +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +local TE initiates disconnection +setting circuit 108/DTR (Data Terminal Ready) OFF +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DATA_TRANSFER}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DATA_TRANSFER}: State change to DISCONNECTING (T2, 5s) +v110_ta_test_status_update_cb(status=0x00000014) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_frame_out(): S-bits are expected to be 1 (OFF) +osmo_v110_ta_frame_out(): X-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): D-bits are all expected to be 0 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DISCONNECTING}: Received Event TX_FRAME_RTS +osmo_v110_ta_frame_out() returns 0 + D-bits: 000000000000000000000000000000000000000000000000 + E-bits: 1111111 + S-bits: 111111111 + X-bits: 00 +circuit 106/CTS (Clear to Send) is OFF (expected to be OFF) +circuit 107/DSR (Data Set Ready) is ON (expected to be ON) +circuit 109/DCD (Data Carrier Detect) is ON (expected to be ON) +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect no state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DISCONNECTING}: Received Event RX_FRAME_IND +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +osmo_v110_ta_frame_in(): S-bits are OFF, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 111111111 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DISCONNECTING}: Received Event RX_FRAME_IND +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){DISCONNECTING}: State change to IDLE_READY (no timeout) +v110_ta_test_status_update_cb(status=0x00000000) +v110_ta_test_rx_cb(buf_size=48): 111111111111111111111111111111111111111111111111 +osmo_v110_ta_frame_in() returns 0 +circuit 106/CTS (Clear to Send) is OFF (expected to be OFF) +circuit 107/DSR (Data Set Ready) is OFF (expected to be OFF) +circuit 109/DCD (Data Carrier Detect) is OFF (expected to be OFF) +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_local){IDLE_READY}: Deallocated + +==== Running test_data_transfer_disc_remote() +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){IDLE_READY}: State change to IDLE_READY (no timeout) +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){CONNECT_TA_TO_LINE}: Received Event SYNC_IND +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000001e) +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){CONNECT_TA_TO_LINE}: State change to DATA_TRANSFER (no timeout) +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +remote TE initiates disconnection +osmo_v110_ta_frame_in(): S-bits are OFF, X-bits are ON +osmo_v110_ta_frame_in(): D-bits are all set to 0 + D-bits: 000000000000000000000000000000000000000000000000 + E-bits: 0111111 + S-bits: 111111111 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){DATA_TRANSFER}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000000a) +osmo_v110_ta_frame_in() returns 0 +circuit 107/DSR (Data Set Ready) is OFF (expected to be OFF) +circuit 109/DCD (Data Carrier Detect) is OFF (expected to be OFF) +local TE confirms disconnection +setting circuit 108/DTR (Data Terminal Ready) OFF +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){DATA_TRANSFER}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){DATA_TRANSFER}: State change to DISCONNECTING (T2, 5s) +v110_ta_test_status_update_cb(status=0x00000000) +osmo_v110_ta_set_circuit() returns 0 +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){DISCONNECTING}: Received Event DESYNC_IND +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){DISCONNECTING}: State change to IDLE_READY (no timeout) +circuit 106/CTS (Clear to Send) is OFF (expected to be OFF) +circuit 107/DSR (Data Set Ready) is OFF (expected to be OFF) +circuit 109/DCD (Data Carrier Detect) is OFF (expected to be OFF) +DLGLOBAL DEBUG V110-TA(test_data_transfer_disc_remote){IDLE_READY}: Deallocated + +==== Running test_syncing() +DLGLOBAL DEBUG V110-TA(test_syncing){IDLE_READY}: Allocated +DLGLOBAL DEBUG V110-TA(test_syncing){IDLE_READY}: State change to IDLE_READY (no timeout) +setting circuit 108/DTR (Data Terminal Ready) ON +DLGLOBAL DEBUG V110-TA(test_syncing){IDLE_READY}: Received Event V24_STATUS_CHG +DLGLOBAL DEBUG V110-TA(test_syncing){IDLE_READY}: State change to CONNECT_TA_TO_LINE (T1, 10s) +osmo_v110_ta_set_circuit() returns 0 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_syncing){CONNECT_TA_TO_LINE}: Received Event SYNC_IND +osmo_v110_ta_frame_in(): S-/X-bits are ON, expect state change + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_syncing){CONNECT_TA_TO_LINE}: Received Event RX_FRAME_IND +v110_ta_test_status_update_cb(status=0x0000001e) +DLGLOBAL DEBUG V110-TA(test_syncing){CONNECT_TA_TO_LINE}: State change to DATA_TRANSFER (no timeout) +v110_ta_test_rx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_in() returns 0 +osmo_v110_ta_sync_ind(): the lower layer indicates out-of-sync event +DLGLOBAL DEBUG V110-TA(test_syncing){DATA_TRANSFER}: Received Event DESYNC_IND +DLGLOBAL DEBUG V110-TA(test_syncing){DATA_TRANSFER}: State change to RESYNCING (X1, 3s) +osmo_v110_ta_frame_out(): S-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): X-bits are expected to be 1 (OFF) +osmo_v110_ta_frame_out(): D-bits are to be set by .tx_cb() +DLGLOBAL DEBUG V110-TA(test_syncing){RESYNCING}: Received Event TX_FRAME_RTS +v110_ta_test_tx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_out() returns 0 + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 11 +osmo_v110_ta_sync_ind(): the lower layer indicates sync event +DLGLOBAL DEBUG V110-TA(test_syncing){RESYNCING}: Received Event SYNC_IND +DLGLOBAL DEBUG V110-TA(test_syncing){RESYNCING}: State change to DATA_TRANSFER (no timeout) +osmo_v110_ta_frame_out(): S-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): X-bits are expected to be 0 (ON) +osmo_v110_ta_frame_out(): D-bits are to be set by .tx_cb() +DLGLOBAL DEBUG V110-TA(test_syncing){DATA_TRANSFER}: Received Event TX_FRAME_RTS +v110_ta_test_tx_cb(buf_size=48): 010101010101010101010101010101010101010101010101 +osmo_v110_ta_frame_out() returns 0 + D-bits: 010101010101010101010101010101010101010101010101 + E-bits: 0111111 + S-bits: 000000000 + X-bits: 00 +DLGLOBAL DEBUG V110-TA(test_syncing){DATA_TRANSFER}: Deallocated
View file
libosmocore_1.9.3.tar.xz/tests/vty/vty_test.c -> libosmocore_1.10.0.tar.xz/tests/vty/vty_test.c
Changed
@@ -39,6 +39,7 @@ #include <osmocom/vty/stats.h> static enum event last_vty_connection_event = -1; +static const char *cfg_path = NULL; void *ctx = NULL; static void test_cmd_string_from_valstr(void) @@ -292,9 +293,12 @@ void test_exit_by_indent(const char *fname, int expect_rc) { + char fpathPATH_MAX; int rc; + printf("reading file %s, expecting rc=%d\n", fname, expect_rc); - rc = vty_read_config_file(fname, NULL); + snprintf(&fpath0, sizeof(fpath), "%s/%s", cfg_path, fname); + rc = vty_read_config_file(fpath, NULL); printf("got rc=%d\n", rc); OSMO_ASSERT(rc == expect_rc); } @@ -618,6 +622,12 @@ }; void *stats_ctx; + if (argc < 2) { + fprintf(stderr, "Usage: %s CFG_PATH\n", argv0); + return 1; + } + cfg_path = argv1; + ctx = talloc_named_const(NULL, 0, "stats test context"); stats_ctx = talloc_named_const(ctx, 1, "stats test context");
View file
libosmocore_1.9.3.tar.xz/tests/write_queue/wqueue_test.c -> libosmocore_1.10.0.tar.xz/tests/write_queue/wqueue_test.c
Changed
@@ -1,3 +1,14 @@ +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH. + * Authors: Holger Hans Peter Freyther + * Alexander Rehbein + * + * 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 2 of the License, or + * (at your option) any later version. + */ + #include <osmocom/core/logging.h> #include <osmocom/core/utils.h> #include <osmocom/core/write_queue.h> @@ -15,6 +26,7 @@ struct msgb *msg; struct osmo_wqueue wqueue; int rc; + size_t dropped_msgs; osmo_wqueue_init(&wqueue, 0); OSMO_ASSERT(wqueue.max_length == 0); @@ -63,6 +75,46 @@ OSMO_ASSERT(wqueue.current_length == 2); msgb_free(msg); osmo_wqueue_clear(&wqueue); + + /* Update limit */ + OSMO_ASSERT(osmo_wqueue_set_maxlen(&wqueue, 5) == 0); + OSMO_ASSERT(osmo_wqueue_set_maxlen(&wqueue, 1) == 0); + OSMO_ASSERT(osmo_wqueue_set_maxlen(&wqueue, 4) == 0); + + /* Add three, update limit to 1 */ + OSMO_ASSERT(wqueue.max_length == 4); + msg = msgb_alloc(4096, "msg6"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(wqueue.current_length == 1); + msg = msgb_alloc(4096, "msg7"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(wqueue.current_length == 2); + msg = msgb_alloc(4096, "msg8"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(wqueue.current_length == 3); + dropped_msgs = osmo_wqueue_set_maxlen(&wqueue, 1); + OSMO_ASSERT(dropped_msgs == 2); + osmo_wqueue_clear(&wqueue); + + /* Add three, reduce limit to 3 from 6 */ + OSMO_ASSERT(osmo_wqueue_set_maxlen(&wqueue, 6) == 0); + OSMO_ASSERT(wqueue.max_length == 6); + msg = msgb_alloc(4096, "msg9"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(wqueue.current_length == 1); + msg = msgb_alloc(4096, "msg10"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(rc == 0); + OSMO_ASSERT(wqueue.current_length == 2); + msg = msgb_alloc(4096, "msg11"); + rc = osmo_wqueue_enqueue(&wqueue, msg); + OSMO_ASSERT(wqueue.current_length == 3); + dropped_msgs = osmo_wqueue_set_maxlen(&wqueue, 3); + OSMO_ASSERT(dropped_msgs == 0); + osmo_wqueue_clear(&wqueue); } int main(int argc, char **argv)
View file
libosmocore_1.9.3.tar.xz/utils/conv_codes_gsm.py -> libosmocore_1.10.0.tar.xz/utils/conv_codes_gsm.py
Changed
@@ -155,11 +155,11 @@ description = "RACH convolutional code" ), - # Extended RACH definition from 3GPP TS 45.003 §5.3.2 + # Extended RACH definition from 3GPP TS 45.003 §5.3.2 ConvolutionalCode( 17, shared_polys"xcch", - puncture = 0, 2, 5, 37, 39, 41, -1 , + puncture = 0, 2, 5, 37, 39, 41, -1 , name = "rach_ext", description = "Extended RACH (11 bit) convolutional code" ),
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.