Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libosmo-netif for openSUSE:Factory 
checked in at 2026-08-26 19:52:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libosmo-netif (Old)
 and      /work/SRC/openSUSE:Factory/.libosmo-netif.new.1258 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libosmo-netif"

Wed Aug 26 19:52:52 2026 rev:18 rq:1373647 version:1.8.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/libosmo-netif/libosmo-netif.changes      
2026-03-15 14:33:20.809808230 +0100
+++ /work/SRC/openSUSE:Factory/.libosmo-netif.new.1258/libosmo-netif.changes    
2026-08-26 19:53:13.186674423 +0200
@@ -1,0 +2,7 @@
+Tue Aug 25 15:26:57 UTC 2026 - Jan Engelhardt <[email protected]>
+
+- Update to release 1.8.0
+  * Introduce ip_checksum API
+  * Introduce API osmo_icmpv6
+
+-------------------------------------------------------------------

Old:
----
  libosmo-netif-1.7.0.tar.bz2

New:
----
  libosmo-netif-1.8.0.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libosmo-netif.spec ++++++
--- /var/tmp/diff_new_pack.yBTWoQ/_old  2026-08-26 19:53:14.842732912 +0200
+++ /var/tmp/diff_new_pack.yBTWoQ/_new  2026-08-26 19:53:14.849733160 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           libosmo-netif
-Version:        1.7.0
+Version:        1.8.0
 Release:        0
 Summary:        Osmocom library for muxed audio
 License:        GPL-2.0-or-later

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.yBTWoQ/_old  2026-08-26 19:53:14.960737080 +0200
+++ /var/tmp/diff_new_pack.yBTWoQ/_new  2026-08-26 19:53:14.971737469 +0200
@@ -1,5 +1,5 @@
-mtime: 1773519991
-commit: d0734224061e26762f55c24a9ec42ff12bd44a1dea981429372eb5e7c3e377f6
+mtime: 1787671649
+commit: 9a1bc5f819f28bbfe8041f031086b70a882895ac9435e2e04c473e9f5fee0dbf
 url: https://src.opensuse.org/jengelh/libosmo-netif
 revision: master
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-08-25 17:27:29.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ libosmo-netif-1.7.0.tar.bz2 -> libosmo-netif-1.8.0.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/.tarball-version 
new/libosmo-netif-1.8.0/.tarball-version
--- old/libosmo-netif-1.7.0/.tarball-version    2025-12-04 06:19:50.000000000 
+0100
+++ new/libosmo-netif-1.8.0/.tarball-version    2026-08-21 07:19:56.000000000 
+0200
@@ -1 +1 @@
-1.7.0
+1.8.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/.version 
new/libosmo-netif-1.8.0/.version
--- old/libosmo-netif-1.7.0/.version    2025-12-04 06:19:49.000000000 +0100
+++ new/libosmo-netif-1.8.0/.version    2026-08-21 07:19:55.000000000 +0200
@@ -1 +1 @@
-1.7.0
+1.8.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/configure 
new/libosmo-netif-1.8.0/configure
--- old/libosmo-netif-1.7.0/configure   2025-12-04 06:19:45.000000000 +0100
+++ new/libosmo-netif-1.8.0/configure   2026-08-21 07:19:49.000000000 +0200
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for libosmo-netif 1.7.0.
+# Generated by GNU Autoconf 2.71 for libosmo-netif 1.8.0.
 #
 # Report bugs to <[email protected]>.
 #
@@ -621,8 +621,8 @@
 # Identity of this package.
 PACKAGE_NAME='libosmo-netif'
 PACKAGE_TARNAME='libosmo-netif'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='libosmo-netif 1.7.0'
+PACKAGE_VERSION='1.8.0'
+PACKAGE_STRING='libosmo-netif 1.8.0'
 PACKAGE_BUGREPORT='[email protected]'
 PACKAGE_URL=''
 
@@ -1388,7 +1388,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libosmo-netif 1.7.0 to adapt to many kinds of systems.
+\`configure' configures libosmo-netif 1.8.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1459,7 +1459,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libosmo-netif 1.7.0:";;
+     short | recursive ) echo "Configuration of libosmo-netif 1.8.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1599,7 +1599,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libosmo-netif configure 1.7.0
+libosmo-netif configure 1.8.0
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1817,7 +1817,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libosmo-netif $as_me 1.7.0, which was
+It was created by libosmo-netif $as_me 1.8.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -3089,7 +3089,7 @@
 
 # Define the identity of the package.
  PACKAGE='libosmo-netif'
- VERSION='1.7.0'
+ VERSION='1.8.0'
 
 
 printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@@ -14215,7 +14215,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libosmo-netif $as_me 1.7.0, which was
+This file was extended by libosmo-netif $as_me 1.8.0, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -14283,7 +14283,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-libosmo-netif config.status 1.7.0
+libosmo-netif config.status 1.8.0
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/debian/changelog 
new/libosmo-netif-1.8.0/debian/changelog
--- old/libosmo-netif-1.7.0/debian/changelog    2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/debian/changelog    2026-08-21 07:19:39.000000000 
+0200
@@ -1,3 +1,36 @@
+libosmo-netif (1.8.0) unstable; urgency=medium
+
+  [ Pau Espin Pedrol ]
+  * cosmetic: stream_cli: Fix typos in API documentation
+  * stream: Log failure to apply NODELAY sockopt
+  * cosmetic: stream_srv: srv_link: Document no need for OSMO_SOCK_F_NONBLOCK
+  * stream_cli: Log state in stream_sctp_recvmsg_wrapper()
+  * stream_srv: keep sockname in iofd name if a stream name is explicitly set
+  * stream_cli: Add stream sockname to iofd name
+  * stream: Improve error handling and logging in write_cb
+  * Introduce ip_checksum API
+  * Introduce API osmo_icmpv6
+  * stream: srv_link: Fix DSCP not set on already created listen socket
+
+  [ Timur Davydov ]
+  * stream: Fix build with --disable-libsctp
+  * gitignore: ignore generated .wasm files
+
+  [ Mychaela N. Falconia ]
+  * twjit: add underrun extension feature
+
+  [ Harald Welte ]
+  * icmpv6: Re-license code under GPL-v2-or-later
+  * ip_checksum: Add SPDX license identifier
+
+  [ Vadim Yanitskiy ]
+  * .gitignore: add missing osmux_{input,output}_test
+
+  [ Andreas Eversberg ]
+  * Also apply DSCP settings on listening socket
+
+ -- Pau Espin Pedrol <[email protected]>  Thu, 20 Aug 2026 10:53:30 +0200
+
 libosmo-netif (1.7.0) unstable; urgency=medium
 
   [ Mychaela N. Falconia ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libosmo-netif-1.7.0/include/osmocom/netif/Makefile.am 
new/libosmo-netif-1.8.0/include/osmocom/netif/Makefile.am
--- old/libosmo-netif-1.7.0/include/osmocom/netif/Makefile.am   2025-12-04 
06:19:35.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/Makefile.am   2026-08-21 
07:19:39.000000000 +0200
@@ -20,6 +20,8 @@
 osmonetif_HEADERS = \
        amr.h \
        datagram.h \
+       icmpv6.h \
+       ip_checksum.h \
        ipa.h \
        ipa_unit.h \
        jibuf.h \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libosmo-netif-1.7.0/include/osmocom/netif/Makefile.in 
new/libosmo-netif-1.8.0/include/osmocom/netif/Makefile.in
--- old/libosmo-netif-1.7.0/include/osmocom/netif/Makefile.in   2025-12-04 
06:19:45.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/Makefile.in   2026-08-21 
07:19:50.000000000 +0200
@@ -122,9 +122,9 @@
     n|no|NO) false;; \
     *) (install-info --version) >/dev/null 2>&1;; \
   esac
-am__osmonetif_HEADERS_DIST = amr.h datagram.h ipa.h ipa_unit.h jibuf.h \
-       osmux.h prim.h rs232.h rtp.h stream.h twjit.h twrtp.h \
-       version.h sctp.h
+am__osmonetif_HEADERS_DIST = amr.h datagram.h icmpv6.h ip_checksum.h \
+       ipa.h ipa_unit.h jibuf.h osmux.h prim.h rs232.h rtp.h stream.h \
+       twjit.h twrtp.h version.h sctp.h
 am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
 am__vpath_adj = case $$p in \
     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@@ -319,9 +319,9 @@
        version.h.tpl \
        $(NULL)
 
-osmonetif_HEADERS = amr.h datagram.h ipa.h ipa_unit.h jibuf.h osmux.h \
-       prim.h rs232.h rtp.h stream.h twjit.h twrtp.h version.h \
-       $(NULL) $(am__append_1)
+osmonetif_HEADERS = amr.h datagram.h icmpv6.h ip_checksum.h ipa.h \
+       ipa_unit.h jibuf.h osmux.h prim.h rs232.h rtp.h stream.h \
+       twjit.h twrtp.h version.h $(NULL) $(am__append_1)
 osmonetifdir = $(includedir)/osmocom/netif
 all: all-am
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/include/osmocom/netif/icmpv6.h 
new/libosmo-netif-1.8.0/include/osmocom/netif/icmpv6.h
--- old/libosmo-netif-1.7.0/include/osmocom/netif/icmpv6.h      1970-01-01 
01:00:00.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/icmpv6.h      2026-08-21 
07:19:39.000000000 +0200
@@ -0,0 +1,105 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <netinet/in.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/endian.h>
+
+#define ICMPv6_OPT_TYPE_PREFIX_INFO 0x03
+
+struct osmo_icmpv6_hdr {
+       uint8_t type;
+       uint8_t code;
+       uint16_t csum;
+} __attribute__ ((packed));
+
+struct osmo_icmpv6_echo_hdr {
+       struct osmo_icmpv6_hdr hdr;
+       uint16_t ident;         /* Identifier */
+       uint16_t seq;           /* Sequence number */
+       uint8_t data[0];        /* Data */
+} __attribute__ ((packed));
+
+/* RFC4861 Section 4.1 */
+struct osmo_icmpv6_rsol_hdr {
+       struct osmo_icmpv6_hdr hdr;
+       uint32_t reserved;
+       uint8_t options[0];
+} __attribute__ ((packed));
+
+/* RFC4861 Section 4.2 */
+struct osmo_icmpv6_radv_hdr {
+       struct osmo_icmpv6_hdr hdr;
+       uint8_t cur_ho_limit;
+#if OSMO_IS_LITTLE_ENDIAN
+       uint8_t res:6,
+               m:1,
+               o:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above 
(libosmocore/contrib/struct_endianness.py) */
+       uint8_t o:1, m:1, res:6;
+#endif
+       uint16_t router_lifetime;
+       uint32_t reachable_time;
+       uint32_t retrans_timer;
+       uint8_t options[0];
+} __attribute__ ((packed));
+
+
+/* RFC4861 Section 4.6 */
+struct osmo_icmpv6_opt_hdr {
+       uint8_t type;
+       /* length in units of 8 octets, including type+len! */
+       uint8_t len;
+       uint8_t data[0];
+} __attribute__ ((packed));
+
+/* RFC4861 Section 4.6.2 */
+struct osmo_icmpv6_opt_prefix {
+       struct osmo_icmpv6_opt_hdr hdr;
+       uint8_t prefix_len;
+#if OSMO_IS_LITTLE_ENDIAN
+       uint8_t res:6,
+               a:1,
+               l:1;
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above 
(libosmocore/contrib/struct_endianness.py) */
+       uint8_t l:1, a:1, res:6;
+#endif
+       uint32_t valid_lifetime;
+       uint32_t preferred_lifetime;
+       uint32_t res2;
+       uint8_t prefix[16];
+} __attribute__ ((packed));
+
+/* RFC4861 Section 4.6.4 */
+struct osmo_icmpv6_opt_mtu {
+       struct osmo_icmpv6_opt_hdr hdr;
+       uint16_t reserved;
+       uint32_t mtu;
+} __attribute__ ((packed));
+
+uint16_t osmo_icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr 
*saddr,
+                                   const struct in6_addr *daddr);
+
+struct msgb *osmo_icmpv6_construct_rs(const struct in6_addr *saddr);
+struct msgb *osmo_icmpv6_construct_ra(const struct in6_addr *saddr,
+                                     const struct in6_addr *daddr,
+                                     const struct in6_addr *prefix,
+                                     uint32_t mtu);
+
+bool osmo_icmpv6_validate_router_solicit(const uint8_t *pack, unsigned len);
+struct osmo_icmpv6_radv_hdr *osmo_icmpv6_validate_router_adv(const uint8_t 
*pack, unsigned len);
+
+#define foreach_icmpv6_opt(icmpv6_pkt, icmpv6_len, opt_hdr) \
+       for (opt_hdr = (struct osmo_icmpv6_opt_hdr *)(icmpv6_pkt)->options; \
+            (uint8_t *)(opt_hdr) + sizeof(struct osmo_icmpv6_opt_hdr) <= 
(((uint8_t *)(icmpv6_pkt)) + (icmpv6_len)); \
+            opt_hdr = (struct osmo_icmpv6_opt_hdr *)((uint8_t *)(opt_hdr) + 
(opt_hdr)->len) \
+           )
+
+/* RFC3307 link-local scope multicast address */
+extern const struct in6_addr osmo_icmpv6_all_router_mcast_addr;
+
+extern const uint8_t osmo_icmpv6_solicited_node_mcast_addr_prefix[13];
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libosmo-netif-1.7.0/include/osmocom/netif/ip_checksum.h 
new/libosmo-netif-1.8.0/include/osmocom/netif/ip_checksum.h
--- old/libosmo-netif-1.7.0/include/osmocom/netif/ip_checksum.h 1970-01-01 
01:00:00.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/ip_checksum.h 2026-08-21 
07:19:39.000000000 +0200
@@ -0,0 +1,11 @@
+#pragma once
+#include <stdint.h>
+#include <netinet/in.h>
+
+uint16_t osmo_ip_checksum_fast_csum(const void *iph, unsigned int ihl);
+uint32_t osmo_ip_checksum_csum_partial(const void *buff, int len, uint32_t 
wsum);
+uint16_t osmo_ip_checksum_compute_csum(const void *buff, int len);
+
+uint16_t osmo_ip_checksum_csum_ipv6_magic(const struct in6_addr *saddr,
+                                         const struct in6_addr *daddr,
+                                         uint32_t len, uint8_t proto, uint32_t 
csum);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/include/osmocom/netif/twjit.h 
new/libosmo-netif-1.8.0/include/osmocom/netif/twjit.h
--- old/libosmo-netif-1.7.0/include/osmocom/netif/twjit.h       2025-12-04 
06:19:35.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/twjit.h       2026-08-21 
07:19:39.000000000 +0200
@@ -83,6 +83,9 @@
        uint32_t intentional_gaps;
        uint32_t ts_resets;
        uint32_t jitter_max;
+       /* new counters added after first osmo_twjit ABI freeze */
+       uint32_t soft_underruns;
+
        /* New fields may be added here at the end; once added, they become
         * permanent like the initially defined ones. */
 };
@@ -134,6 +137,8 @@
                                          uint16_t delta_ms);
 int osmo_twjit_config_set_start_max_delta(struct osmo_twjit_config *conf,
                                          uint16_t delta_ms);
+int osmo_twjit_config_set_underrun_ext(struct osmo_twjit_config *conf,
+                                       uint16_t underrun_ext);
 int osmo_twjit_config_set_handover_on_marker(struct osmo_twjit_config *conf,
                                             bool hom);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/libosmo-netif-1.7.0/include/osmocom/netif/twjit_private.h 
new/libosmo-netif-1.8.0/include/osmocom/netif/twjit_private.h
--- old/libosmo-netif-1.7.0/include/osmocom/netif/twjit_private.h       
2025-12-04 06:19:35.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/twjit_private.h       
2026-08-21 07:19:39.000000000 +0200
@@ -49,6 +49,12 @@
        /*! max time delta in starting state, 1 ms units, 0 means not set;
         *  document section: 2.3.3.2. */
        uint16_t start_max_delta;
+       /*! Optional extended underrun tolerance: maximum gap in RTP stream
+        *  that does not result in full reset and reacquisition, minimum of 1.
+        *  If this field is set to 0, the feature is disabled and the original
+        *  twjit algorithm (no intentional gaps allowed) applies.
+        *  Document section: 2.3.5.1. */
+       uint16_t underrun_ext;
        /*! Osmocom addition, not in ThemWi original: should RTP packets
         *  with M bit set cause a handover or HUNT state reset just like
         *  an SSRC change?  With this option enabled, M bit is treated
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/include/osmocom/netif/version.h 
new/libosmo-netif-1.8.0/include/osmocom/netif/version.h
--- old/libosmo-netif-1.7.0/include/osmocom/netif/version.h     2025-12-04 
06:19:49.000000000 +0100
+++ new/libosmo-netif-1.8.0/include/osmocom/netif/version.h     2026-08-21 
07:19:55.000000000 +0200
@@ -1,10 +1,10 @@
 #pragma once
 
-#define LIBOSMO_NETIF_VERSION 1.7.0
-#define LIBOSMO_NETIF_VERSION_STR "1.7.0"
+#define LIBOSMO_NETIF_VERSION 1.8.0
+#define LIBOSMO_NETIF_VERSION_STR "1.8.0"
 
 #define LIBOSMO_NETIF_VERSION_MAJOR 1
-#define LIBOSMO_NETIF_VERSION_MINOR 7
+#define LIBOSMO_NETIF_VERSION_MINOR 8
 #define LIBOSMO_NETIF_VERSION_PATCH 0
 
 #define LIBOSMO_NETIF_VERSION_GREATER_EQUAL(major, minor, patch) \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/Makefile.am 
new/libosmo-netif-1.8.0/src/Makefile.am
--- old/libosmo-netif-1.7.0/src/Makefile.am     2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/Makefile.am     2026-08-21 07:19:39.000000000 
+0200
@@ -1,6 +1,6 @@
 # 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=15:0:4
+LIBVERSION=16:0:5
 
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS= -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) \
@@ -15,6 +15,8 @@
 
 libosmonetif_la_SOURCES = amr.c                        \
                          datagram.c            \
+                         icmpv6.c              \
+                         ip_checksum.c         \
                          ipa.c                 \
                          ipa_keepalive.c       \
                          ipa_unit.c            \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/Makefile.in 
new/libosmo-netif-1.8.0/src/Makefile.in
--- old/libosmo-netif-1.7.0/src/Makefile.in     2025-12-04 06:19:45.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/Makefile.in     2026-08-21 07:19:50.000000000 
+0200
@@ -135,16 +135,16 @@
 libosmonetif_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1)
-am__libosmonetif_la_SOURCES_DIST = amr.c datagram.c ipa.c \
-       ipa_keepalive.c ipa_unit.c jibuf.c osmux.c osmux_input.c \
-       osmux_output.c prim.c rs232.c rtp.c stream.c stream_cli.c \
-       stream_srv.c twjit.c twjit_conf.c twrtp.c sctp.c
+am__libosmonetif_la_SOURCES_DIST = amr.c datagram.c icmpv6.c \
+       ip_checksum.c ipa.c ipa_keepalive.c ipa_unit.c jibuf.c osmux.c \
+       osmux_input.c osmux_output.c prim.c rs232.c rtp.c stream.c \
+       stream_cli.c stream_srv.c twjit.c twjit_conf.c twrtp.c sctp.c
 @ENABLE_LIBSCTP_TRUE@am__objects_1 = sctp.lo
-am_libosmonetif_la_OBJECTS = amr.lo datagram.lo ipa.lo \
-       ipa_keepalive.lo ipa_unit.lo jibuf.lo osmux.lo osmux_input.lo \
-       osmux_output.lo prim.lo rs232.lo rtp.lo stream.lo \
-       stream_cli.lo stream_srv.lo twjit.lo twjit_conf.lo twrtp.lo \
-       $(am__objects_1)
+am_libosmonetif_la_OBJECTS = amr.lo datagram.lo icmpv6.lo \
+       ip_checksum.lo ipa.lo ipa_keepalive.lo ipa_unit.lo jibuf.lo \
+       osmux.lo osmux_input.lo osmux_output.lo prim.lo rs232.lo \
+       rtp.lo stream.lo stream_cli.lo stream_srv.lo twjit.lo \
+       twjit_conf.lo twrtp.lo $(am__objects_1)
 libosmonetif_la_OBJECTS = $(am_libosmonetif_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -170,6 +170,7 @@
 depcomp = $(SHELL) $(top_srcdir)/depcomp
 am__maybe_remake_depfiles = depfiles
 am__depfiles_remade = ./$(DEPDIR)/amr.Plo ./$(DEPDIR)/datagram.Plo \
+       ./$(DEPDIR)/icmpv6.Plo ./$(DEPDIR)/ip_checksum.Plo \
        ./$(DEPDIR)/ipa.Plo ./$(DEPDIR)/ipa_keepalive.Plo \
        ./$(DEPDIR)/ipa_unit.Plo ./$(DEPDIR)/jibuf.Plo \
        ./$(DEPDIR)/osmux.Plo ./$(DEPDIR)/osmux_input.Plo \
@@ -362,7 +363,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 = 15:0:4
+LIBVERSION = 16:0:5
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)
 AM_CFLAGS = -fPIC -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) \
        $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) $(LIBSCTP_CFLAGS)
@@ -373,10 +374,11 @@
        $(LIBOSMOVTY_LIBS) $(LIBSCTP_LIBS)
 
 libosmonetif_la_LDFLAGS = $(AM_LDFLAGS) -version-info $(LIBVERSION) 
-no-undefined
-libosmonetif_la_SOURCES = amr.c datagram.c ipa.c ipa_keepalive.c \
-       ipa_unit.c jibuf.c osmux.c osmux_input.c osmux_output.c prim.c \
-       rs232.c rtp.c stream.c stream_cli.c stream_srv.c twjit.c \
-       twjit_conf.c twrtp.c $(NULL) $(am__append_1)
+libosmonetif_la_SOURCES = amr.c datagram.c icmpv6.c ip_checksum.c \
+       ipa.c ipa_keepalive.c ipa_unit.c jibuf.c osmux.c osmux_input.c \
+       osmux_output.c prim.c rs232.c rtp.c stream.c stream_cli.c \
+       stream_srv.c twjit.c twjit_conf.c twrtp.c $(NULL) \
+       $(am__append_1)
 all: all-am
 
 .SUFFIXES:
@@ -457,6 +459,8 @@
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/amr.Plo@am__quote@ # 
am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/datagram.Plo@am__quote@ # 
am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icmpv6.Plo@am__quote@ # 
am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ip_checksum.Plo@am__quote@ # 
am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa.Plo@am__quote@ # 
am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_keepalive.Plo@am__quote@ 
# am--include-marker
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_unit.Plo@am__quote@ # 
am--include-marker
@@ -640,6 +644,8 @@
 distclean: distclean-am
                -rm -f ./$(DEPDIR)/amr.Plo
        -rm -f ./$(DEPDIR)/datagram.Plo
+       -rm -f ./$(DEPDIR)/icmpv6.Plo
+       -rm -f ./$(DEPDIR)/ip_checksum.Plo
        -rm -f ./$(DEPDIR)/ipa.Plo
        -rm -f ./$(DEPDIR)/ipa_keepalive.Plo
        -rm -f ./$(DEPDIR)/ipa_unit.Plo
@@ -704,6 +710,8 @@
 maintainer-clean: maintainer-clean-am
                -rm -f ./$(DEPDIR)/amr.Plo
        -rm -f ./$(DEPDIR)/datagram.Plo
+       -rm -f ./$(DEPDIR)/icmpv6.Plo
+       -rm -f ./$(DEPDIR)/ip_checksum.Plo
        -rm -f ./$(DEPDIR)/ipa.Plo
        -rm -f ./$(DEPDIR)/ipa_keepalive.Plo
        -rm -f ./$(DEPDIR)/ipa_unit.Plo
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/icmpv6.c 
new/libosmo-netif-1.8.0/src/icmpv6.c
--- old/libosmo-netif-1.7.0/src/icmpv6.c        1970-01-01 01:00:00.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/icmpv6.c        2026-08-21 07:19:39.000000000 
+0200
@@ -0,0 +1,226 @@
+/* Minimal ICMPv6 code for generating router advertisements as required by
+ * relevant 3GPP specs for a GGSN with IPv6 PDP contexts */
+
+/* (C) 2017 by Harald Welte <[email protected]>
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <netinet/in.h>
+#if defined(__FreeBSD__)
+#include <sys/types.h> /* FreeBSD 10.x needs this before ip6.h */
+#include <sys/endian.h>
+#endif
+#include <netinet/ip6.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
+
+#include <osmocom/netif/ip_checksum.h>
+#include <osmocom/netif/icmpv6.h>
+
+/* 29.061 11.2.1.3.4 IPv6 Router Configuration Variables in GGSN */
+#define GGSN_MaxRtrAdvInterval 21600           /* 6 hours */
+#define GGSN_MinRtrAdvInterval 16200           /* 4.5 hours */
+#define GGSN_AdvValidLifetime  0xffffffff      /* infinite */
+#define GGSN_AdvPreferredLifetime 0xffffffff   /* infinite */
+
+/* RFC3307 link-local scope multicast address */
+const struct in6_addr osmo_icmpv6_all_router_mcast_addr = {
+       .s6_addr = { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }
+};
+
+
+/* RFC4291  link-local solicited-node multicast address, FF02:0:0:0:0:1:FF, 
104 bits = 13 bytes */
+const uint8_t osmo_icmpv6_solicited_node_mcast_addr_prefix[13] = {
+       0xff, 0x02, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x01,
+       0xFF
+};
+
+/* Prepends the ipv6 header and returns checksum content */
+uint16_t osmo_icmpv6_prepend_ip6hdr(struct msgb *msg, const struct in6_addr 
*saddr,
+                                   const struct in6_addr *daddr)
+{
+       uint32_t len;
+       uint16_t skb_csum;
+       struct ip6_hdr *i6h;
+
+       /* checksum */
+       skb_csum = osmo_ip_checksum_csum_partial(msgb_data(msg), 
msgb_length(msg), 0);
+       len = msgb_length(msg);
+       skb_csum = osmo_ip_checksum_csum_ipv6_magic(saddr, daddr, len, 
IPPROTO_ICMPV6, skb_csum);
+
+       /* Push IPv6 header in front of ICMPv6 packet */
+       i6h = (struct ip6_hdr *) msgb_push(msg, sizeof(*i6h));
+       /* 4 bits version, 8 bits TC, 20 bits flow-ID */
+       i6h->ip6_ctlun.ip6_un1.ip6_un1_flow = htonl(0x60000000);
+       i6h->ip6_ctlun.ip6_un1.ip6_un1_plen = htons(len);
+       i6h->ip6_ctlun.ip6_un1.ip6_un1_nxt = IPPROTO_ICMPV6;
+       i6h->ip6_ctlun.ip6_un1.ip6_un1_hlim = 255;
+       i6h->ip6_src = *saddr;
+       i6h->ip6_dst = *daddr;
+       return skb_csum;
+}
+
+/*! construct a RFC4861 compliant ICMPv6 router soliciation
+ *  \param[in] saddr Source IPv6 address for router advertisement
+ *  \param[in] daddr Destination IPv6 address for router advertisement IPv6 
header
+ *  \param[in] prefix The single prefix to be advertised (/64 implied!)
+ *  \returns callee-allocated message buffer containing router advertisement */
+struct msgb *osmo_icmpv6_construct_rs(const struct in6_addr *saddr)
+{
+       struct msgb *msg = msgb_alloc_headroom(512, 128, "IPv6 RS");
+       struct osmo_icmpv6_rsol_hdr *rs;
+       OSMO_ASSERT(msg);
+       rs = (struct osmo_icmpv6_rsol_hdr *) msgb_put(msg, sizeof(*rs));
+       rs->hdr.type = 133;     /* see RFC4861 4.1 */
+       rs->hdr.code = 0;       /* see RFC4861 4.1 */
+       rs->hdr.csum = 0;       /* updated below */
+       rs->reserved = 0;       /* see RFC4861 4.1 */
+
+       rs->hdr.csum = osmo_icmpv6_prepend_ip6hdr(msg, saddr, 
&osmo_icmpv6_all_router_mcast_addr);
+
+       return msg;
+}
+/*! construct a 3GPP 29.061 compliant router advertisement for a given prefix
+ *  \param[in] saddr Source IPv6 address for router advertisement
+ *  \param[in] daddr Destination IPv6 address for router advertisement IPv6 
header
+ *  \param[in] prefix The single prefix to be advertised (/64 implied!)
+ *  \returns callee-allocated message buffer containing router advertisement */
+struct msgb *osmo_icmpv6_construct_ra(const struct in6_addr *saddr,
+                                     const struct in6_addr *daddr,
+                                     const struct in6_addr *prefix,
+                                     uint32_t mtu)
+{
+       struct msgb *msg = msgb_alloc_headroom(512, 128, "IPv6 RA");
+       struct osmo_icmpv6_radv_hdr *ra;
+       struct osmo_icmpv6_opt_prefix *ra_opt_pref;
+       struct osmo_icmpv6_opt_mtu *ra_opt_mtu;
+
+       OSMO_ASSERT(msg);
+
+       ra = (struct osmo_icmpv6_radv_hdr *) msgb_put(msg, sizeof(*ra));
+       ra->hdr.type = 134;     /* see RFC4861 4.2 */
+       ra->hdr.code = 0;       /* see RFC4861 4.2 */
+       ra->hdr.csum = 0;       /* updated below */
+       ra->cur_ho_limit = 64;  /* seems reasonable? */
+       /* the GGSN shall leave the M-flag cleared in the Router
+        * Advertisement messages */
+       ra->m = 0;
+       /* The GGSN may set the O-flag if there are additional
+        * configuration parameters that need to be fetched by the MS */
+       ra->o = 0;              /* no DHCPv6 */
+       ra->res = 0;
+       /* RFC4861 Default: 3 * MaxRtrAdvInterval */
+       ra->router_lifetime = htons(3*GGSN_MaxRtrAdvInterval);
+       ra->reachable_time = 0; /* Unspecified */
+
+       /* RFC4861 Section 4.6.2 */
+       ra_opt_pref = (struct osmo_icmpv6_opt_prefix *) msgb_put(msg, 
sizeof(*ra_opt_pref));
+       ra_opt_pref->hdr.type = 3;      /* RFC4861 4.6.2 */
+       ra_opt_pref->hdr.len = 4;       /* RFC4861 4.6.2 */
+       ra_opt_pref->prefix_len = 64;   /* only prefix length as per 3GPP */
+       /* The Prefix is contained in the Prefix Information Option of
+        * the Router Advertisements and shall have the A-flag set
+        * and the L-flag cleared */
+       ra_opt_pref->a = 1;
+       ra_opt_pref->l = 0;
+       ra_opt_pref->res = 0;
+       /*  The lifetime of the prefix shall be set to infinity */
+       ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime);
+       ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime);
+       ra_opt_pref->res2 = 0;
+       memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
+
+       /* RFC4861 Section 4.6.4, MTU */
+       ra_opt_mtu = (struct osmo_icmpv6_opt_mtu *) msgb_put(msg, 
sizeof(*ra_opt_mtu));
+       ra_opt_mtu->hdr.type = 5;       /* RFC4861 4.6.4 */
+       ra_opt_mtu->hdr.len = 1;        /* RFC4861 4.6.4 */
+       ra_opt_mtu->reserved = 0;
+       ra_opt_mtu->mtu = htonl(mtu);
+
+       /* The Prefix is contained in the Prefix Information Option of
+        * the Router Advertisements and shall have the A-flag set
+        * and the L-flag cleared */
+       ra_opt_pref->a = 1;
+       ra_opt_pref->l = 0;
+       ra_opt_pref->res = 0;
+       /*  The lifetime of the prefix shall be set to infinity */
+       ra_opt_pref->valid_lifetime = htonl(GGSN_AdvValidLifetime);
+       ra_opt_pref->preferred_lifetime = htonl(GGSN_AdvPreferredLifetime);
+       ra_opt_pref->res2 = 0;
+       memcpy(ra_opt_pref->prefix, prefix, sizeof(ra_opt_pref->prefix));
+
+       /* checksum */
+       ra->hdr.csum = osmo_icmpv6_prepend_ip6hdr(msg, saddr, daddr);
+
+       return msg;
+}
+
+/* Validate an ICMPv6 router solicitation according to RFC4861 6.1.1 */
+bool osmo_icmpv6_validate_router_solicit(const uint8_t *pack, unsigned len)
+{
+       const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+       //const struct icmpv6_hdr *ic6h = (struct icmpv6_hdr *) (pack + 
sizeof(*ip6h));
+
+       /* Hop limit field must have 255 */
+       if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
+               return false;
+       /* FIXME: ICMP checksum is valid */
+       /* ICMP length (derived from IP length) is 8 or more octets */
+       if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 8)
+               return false;
+       /* FIXME: All included options have a length > 0 */
+       /* FIXME: If IP source is unspecified, no source link-layer addr option 
*/
+       return true;
+}
+
+/* Validate an ICMPv6 router advertisement according to RFC4861 6.1.2.
+   Returns pointer packet header on success, NULL otherwise. */
+struct osmo_icmpv6_radv_hdr *osmo_icmpv6_validate_router_adv(const uint8_t 
*pack, unsigned len)
+{
+       const struct ip6_hdr *ip6h = (struct ip6_hdr *)pack;
+       const struct osmo_icmpv6_hdr *ic6h = (struct osmo_icmpv6_hdr *) (pack + 
sizeof(*ip6h));
+
+       /* ICMP length (derived from IP length) is 16 or more octets */
+       if (len < sizeof(*ip6h) + 16)
+               return NULL;
+
+       if (ic6h->type != 134) /* router advertismenet type */
+               return NULL;
+
+       /*Routers must use their link-local address */
+       if (!IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))
+               return NULL;
+       /* Hop limit field must have 255 */
+       if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_hlim != 255)
+               return NULL;
+       /* ICMP Code is 0 */
+       if (ic6h->code != 0)
+               return NULL;
+       /* ICMP length (derived from IP length) is 16 or more octets */
+       if (ip6h->ip6_ctlun.ip6_un1.ip6_un1_plen < 16)
+               return NULL;
+       /* FIXME: All included options have a length > 0 */
+       /* FIXME: If IP source is unspecified, no source link-layer addr option 
*/
+       return (struct osmo_icmpv6_radv_hdr *)ic6h;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/ip_checksum.c 
new/libosmo-netif-1.8.0/src/ip_checksum.c
--- old/libosmo-netif-1.7.0/src/ip_checksum.c   1970-01-01 01:00:00.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/ip_checksum.c   2026-08-21 07:19:39.000000000 
+0200
@@ -0,0 +1,214 @@
+/*
+ *
+ * INET                An implementation of the TCP/IP protocol suite for the 
LINUX
+ *             operating system.  INET is implemented using the  BSD Socket
+ *             interface as the means of communication with the user level.
+ *
+ *             IP/TCP/UDP checksumming routines
+ *
+ * Authors:    Jorge Cwik, <[email protected]>
+ *             Arnt Gulbrandsen, <[email protected]>
+ *             Tom May, <[email protected]>
+ *             Andreas Schwab, <[email protected]>
+ *             Lots of code moved from tcp.c and ip.c; see those files
+ *             for more names.
+ *
+ * 03/02/96    Jes Sorensen, Andreas Schwab, Roman Hodek:
+ *             Fixed some nasty bugs, causing some horrible crashes.
+ *             A: At some points, the sum (%0) was used as
+ *             length-counter instead of the length counter
+ *             (%1). Thanks to Roman Hodek for pointing this out.
+ *             B: GCC seems to mess up if one uses too many
+ *             data-registers to hold input values and one tries to
+ *             specify d0 and d1 as scratch registers. Letting gcc
+ *             choose these registers itself solves the problem.
+ *
+ *             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.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
+ kills, so most of the assembly has to go. */
+
+#if defined(__FreeBSD__)
+#define _KERNEL        /* needed on FreeBSD 10.x for s6_addr32 */
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/endian.h>
+#endif
+
+#include <arpa/inet.h>
+
+#include <osmocom/netif/ip_checksum.h>
+
+static inline unsigned short from32to16(unsigned int x)
+{
+       /* add up 16-bit and 16-bit for 16+c bit */
+       x = (x & 0xffff) + (x >> 16);
+       /* add up carry.. */
+       x = (x & 0xffff) + (x >> 16);
+       return x;
+}
+
+static unsigned int do_csum(const unsigned char *buff, int len)
+{
+       int odd;
+       unsigned int result = 0;
+
+       if (len <= 0)
+               goto out;
+       odd = 1 & (unsigned long) buff;
+       if (odd) {
+#if BYTE_ORDER == LITTLE_ENDIAN
+               result += (*buff << 8);
+#else
+               result = *buff;
+#endif
+               len--;
+               buff++;
+       }
+       if (len >= 2) {
+               if (2 & (unsigned long) buff) {
+                       result += *(unsigned short *) buff;
+                       len -= 2;
+                       buff += 2;
+               }
+               if (len >= 4) {
+                       const unsigned char *end = buff + ((unsigned)len & ~3);
+                       unsigned int carry = 0;
+                       do {
+                               unsigned int w = *(unsigned int *) buff;
+                               buff += 4;
+                               result += carry;
+                               result += w;
+                               carry = (w > result);
+                       } while (buff < end);
+                       result += carry;
+                       result = (result & 0xffff) + (result >> 16);
+               }
+               if (len & 2) {
+                       result += *(unsigned short *) buff;
+                       buff += 2;
+               }
+       }
+       if (len & 1)
+#if BYTE_ORDER == LITTLE_ENDIAN
+               result += *buff;
+#else
+               result += (*buff << 8);
+#endif
+       result = from32to16(result);
+       if (odd)
+               result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
+out:
+       return result;
+}
+
+/* fold a partial checksum */
+static uint16_t csum_fold(uint32_t csum)
+{
+       uint32_t sum = (uint32_t)csum;
+       sum = (sum & 0xffff) + (sum >> 16);
+       sum = (sum & 0xffff) + (sum >> 16);
+       return (uint16_t)~sum;
+}
+
+/*
+ *     This is a version of ip_compute_csum() optimized for IP headers,
+ *     which always checksum on 4 octet boundaries.
+ */
+uint16_t osmo_ip_checksum_fast_csum(const void *iph, unsigned int ihl)
+{
+       return (uint16_t)~do_csum(iph, ihl*4);
+}
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+uint32_t osmo_ip_checksum_csum_partial(const void *buff, int len, uint32_t 
wsum)
+{
+       unsigned int sum = (unsigned int)wsum;
+       unsigned int result = do_csum(buff, len);
+
+       /* add in old sum, and carry.. */
+       result += sum;
+       if (sum > result)
+               result += 1;
+       return (uint32_t)result;
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+uint16_t osmo_ip_checksum_compute_csum(const void *buff, int len)
+{
+       return (uint16_t)~do_csum(buff, len);
+}
+
+uint16_t osmo_ip_checksum_csum_ipv6_magic(const struct in6_addr *saddr,
+                                         const struct in6_addr *daddr,
+                                         uint32_t len, uint8_t proto, uint32_t 
csum)
+{
+       int carry;
+       uint32_t ulen;
+       uint32_t uproto;
+       uint32_t sum = (uint32_t)csum;
+
+       sum += (uint32_t)saddr->s6_addr32[0];
+       carry = (sum < (uint32_t)saddr->s6_addr32[0]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[1];
+       carry = (sum < (uint32_t)saddr->s6_addr32[1]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[2];
+       carry = (sum < (uint32_t)saddr->s6_addr32[2]);
+       sum += carry;
+
+       sum += (uint32_t)saddr->s6_addr32[3];
+       carry = (sum < (uint32_t)saddr->s6_addr32[3]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[0];
+       carry = (sum < (uint32_t)daddr->s6_addr32[0]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[1];
+       carry = (sum < (uint32_t)daddr->s6_addr32[1]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[2];
+       carry = (sum < (uint32_t)daddr->s6_addr32[2]);
+       sum += carry;
+
+       sum += (uint32_t)daddr->s6_addr32[3];
+       carry = (sum < (uint32_t)daddr->s6_addr32[3]);
+       sum += carry;
+
+       ulen = (uint32_t)htonl((uint32_t) len);
+       sum += ulen;
+       carry = (sum < ulen);
+       sum += carry;
+
+       uproto = (uint32_t)htonl(proto);
+       sum += uproto;
+       carry = (sum < uproto);
+       sum += carry;
+
+       return csum_fold((uint32_t)sum);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/stream.c 
new/libosmo-netif-1.8.0/src/stream.c
--- old/libosmo-netif-1.7.0/src/stream.c        2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/stream.c        2026-08-21 07:19:39.000000000 
+0200
@@ -49,12 +49,12 @@
 
 #include "config.h"
 
-#include <osmocom/netif/sctp.h>
-
 /*! \cond private */
 
 #ifdef HAVE_LIBSCTP
 
+#include <osmocom/netif/sctp.h>
+
 /* is any of the bytes from offset .. u8_size in 'u8' non-zero? return offset 
or -1 if all zero */
 static int byte_nonzero(const uint8_t *u8, unsigned int offset, unsigned int 
u8_size)
 {
@@ -182,10 +182,22 @@
 #ifdef HAVE_LIBSCTP
        case IPPROTO_SCTP:
                rc = setsockopt(fd, IPPROTO_SCTP, SCTP_NODELAY, &on, 
sizeof(on));
+               if (rc < 0) {
+                       char errbuf[256];
+                       strerror_r(errno, errbuf, sizeof(errbuf));
+                       LOGP(DLINP, LOGL_ERROR, "setsockopt(IPPROTO_SCTP, 
SCTP_NODELAY, %u) failed: %d (%s)\n",
+                            on, errno, errbuf);
+               }
                break;
 #endif
        case IPPROTO_TCP:
                rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+               if (rc < 0) {
+                       char errbuf[256];
+                       strerror_r(errno, errbuf, sizeof(errbuf));
+                       LOGP(DLINP, LOGL_ERROR, "setsockopt(IPPROTO_TCP, 
TCP_NODELAY, %u) failed: %d (%s)\n",
+                            on, errno, errbuf);
+               }
                break;
        default:
                rc = -1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/stream_cli.c 
new/libosmo-netif-1.8.0/src/stream_cli.c
--- old/libosmo-netif-1.7.0/src/stream_cli.c    2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/stream_cli.c    2026-08-21 07:19:39.000000000 
+0200
@@ -49,7 +49,9 @@
 
 #include "config.h"
 
+#ifdef HAVE_LIBSCTP
 #include <osmocom/netif/sctp.h>
+#endif
 
 /*! \file stream_cli.c */
 
@@ -411,6 +413,26 @@
 #endif
 }
 
+/* Update cli->sockname based on socket info: */
+static void stream_cli_update_iofd_name(struct osmo_stream_cli *cli)
+{
+       if (!(cli->mode == OSMO_STREAM_MODE_OSMO_IO && cli->iofd))
+               return;
+
+       char *tmp = talloc_asprintf(cli, "%s,%s", cli->name, cli->sockname);
+       osmo_iofd_set_name(cli->iofd, tmp);
+       talloc_free(tmp);
+}
+
+/* Update cli->sockname based on socket info: */
+static void stream_cli_update_sockname(struct osmo_stream_cli *cli)
+{
+       osmo_sock_get_name_buf(cli->sockname, sizeof(cli->sockname), 
osmo_stream_cli_get_fd(cli));
+       /* Update stream iofd with the new cli->sockname too: */
+       stream_cli_update_iofd_name(cli);
+
+}
+
 /* returns true if cli is freed */
 static bool stream_cli_handle_connecting(struct osmo_stream_cli *cli, int res)
 {
@@ -435,8 +457,7 @@
        if (cli->mode == OSMO_STREAM_MODE_OSMO_FD && 
llist_empty(&cli->tx_queue))
                osmo_fd_write_disable(&cli->ofd);
 
-       /* Update sockname based on socket info: */
-       osmo_sock_get_name_buf(cli->sockname, sizeof(cli->sockname), 
osmo_stream_cli_get_fd(cli));
+       stream_cli_update_sockname(cli);
 
        LOGSCLI(cli, LOGL_INFO, "connection established\n");
        cli->state = STREAM_CLI_STATE_CONNECTED;
@@ -583,8 +604,10 @@
                (void)stream_cli_handle_connecting(cli, res);
                break;
        case STREAM_CLI_STATE_CONNECTED:
-               if (msg && res <= 0) {
-                       LOGSCLI(cli, LOGL_ERROR, "received error %d in response 
to send\n", res);
+               if (msg && res < 0) {
+                       char errbuf[64];
+                       strerror_r(-res, errbuf, sizeof(errbuf));
+                       LOGSCLI(cli, LOGL_ERROR, "error to send: %d (%s)\n", 
res, errbuf);
                        (void)stream_cli_reconnect(cli);
                }
                /* res=0 && msgb=NULL: "connected notify", but we already 
received before a read_cb
@@ -691,8 +714,8 @@
                talloc_free((void *)cli->name);
        cli->name = name;
 
-       if (cli->mode == OSMO_STREAM_MODE_OSMO_IO && cli->iofd)
-               osmo_iofd_set_name(cli->iofd, cli->name);
+       /* Update stream iofd with the new cli->name too: */
+       stream_cli_update_iofd_name(cli);
 }
 
 /*! Retrieve name previously set on the cli object (see 
osmo_stream_cli_set_name()).
@@ -876,7 +899,7 @@
                configure_cli_segmentation_cb(cli);
 }
 
-/*! Set the socket type for the stream server link.
+/*! Set the socket type for the stream client.
  *  Any changes to this setting will only become active upon next (re)connect.
  *  \param[in] cli Stream Client to modify
  *  \param[in] type Socket Type (like SOCK_STREAM (default), SOCK_SEQPACKET, 
...)
@@ -896,7 +919,7 @@
        return 0;
 }
 
-/*! Set the socket domain for the stream client link.
+/*! Set the socket domain for the stream client.
  *  Any changes to this setting will only become active upon next (re)connect.
  *  \param[in] cli Stream Client to modify
  *  \param[in] domain Socket Domain (like AF_UNSPEC (default for IP), AF_UNIX, 
AF_INET, ...)
@@ -1224,9 +1247,8 @@
  *  \return negative on error, 0 on success */
 int osmo_stream_cli_open(struct osmo_stream_cli *cli)
 {
-       int ret, flags;
+       int ret;
        int fd = -1;
-       unsigned int local_addrcnt;
 
        /* we are reconfiguring this socket, close existing first. */
        if ((cli->flags & OSMO_STREAM_CLI_F_RECONF) && 
osmo_stream_cli_get_fd(cli) >= 0) {
@@ -1246,8 +1268,9 @@
                switch (cli->proto) {
 #ifdef HAVE_LIBSCTP
                case IPPROTO_SCTP:
-                       local_addrcnt = cli->local_addrcnt;
-                       flags = OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK |
+               {
+                       unsigned int local_addrcnt = cli->local_addrcnt;
+                       int flags = OSMO_SOCK_F_CONNECT | OSMO_SOCK_F_NONBLOCK |
                                OSMO_SOCK_F_DSCP(cli->ip_dscp) | 
OSMO_SOCK_F_PRIO(cli->sk_prio);
                        if (cli->local_addrcnt > 0 || cli->local_port > 0) { /* 
explicit bind required? */
                                flags |= OSMO_SOCK_F_BIND;
@@ -1260,6 +1283,7 @@
                                                        (const char 
**)cli->addr, cli->addrcnt, cli->port,
                                                        flags, &cli->ma_pars);
                        break;
+               }
 #endif
                default:
                        ret = osmo_sock_init2(cli->sk_domain, cli->sk_type, 
cli->proto,
@@ -1383,9 +1407,11 @@
        case OSMO_STREAM_MODE_OSMO_IO:
                /* whenever osmo_stream_cli_is_connected() [see above check], 
we should have an iofd */
                OSMO_ASSERT(cli->iofd);
+#ifdef HAVE_LIBSCTP
                if (cli->proto == IPPROTO_SCTP)
                        rc = stream_iofd_sctp_send_msgb(cli->iofd, msg, 
MSG_NOSIGNAL);
                else
+#endif
                        rc = osmo_iofd_write_msgb(cli->iofd, msg);
                if (rc < 0)
                        msgb_free(msg);
@@ -1433,7 +1459,9 @@
                case IPPROTO_SCTP:
                {
                        char log_pfx[128];
-                       snprintf(log_pfx, sizeof(log_pfx), "CLICONN(%s,%s)", 
cli->name ? : "", cli->sockname);
+                       snprintf(log_pfx, sizeof(log_pfx), "CLICONN(%s,%s){%s}",
+                                cli->name ? : "", cli->sockname,
+                                get_value_string(stream_cli_state_names, 
cli->state));
                        ret = stream_sctp_recvmsg_wrapper(cli->ofd.fd, msg, 
log_pfx);
                        break;
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/stream_srv.c 
new/libosmo-netif-1.8.0/src/stream_srv.c
--- old/libosmo-netif-1.7.0/src/stream_srv.c    2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/stream_srv.c    2026-08-21 07:19:39.000000000 
+0200
@@ -50,7 +50,9 @@
 
 #include "config.h"
 
+#ifdef HAVE_LIBSCTP
 #include <osmocom/netif/sctp.h>
+#endif
 
 /*! \file stream_srv.c */
 
@@ -172,8 +174,11 @@
 
        if (link->flags & OSMO_STREAM_SRV_F_NODELAY) {
                ret = stream_setsockopt_nodelay(sock_fd, link->proto, 1);
-               if (ret < 0)
+               if (ret < 0) {
+                       LOGSLNK(link, LOGL_ERROR, "stream_setsockopt_nodelay: 
failed setsockopt err=%d\n",
+                               errno);
                        goto error_close_socket;
+               }
        }
 
        if (link->ip_dscp > 0) {
@@ -294,7 +299,19 @@
  */
 int osmo_stream_srv_link_set_ip_dscp(struct osmo_stream_srv_link *link, 
uint8_t ip_dscp)
 {
+       int rc;
+
        link->ip_dscp = ip_dscp;
+
+       if (!osmo_stream_srv_link_is_opened(link))
+               return 0;
+
+       rc = osmo_sock_set_dscp(link->ofd.fd, link->ip_dscp);
+       if (rc < 0) {
+               LOGSLNK(link, LOGL_ERROR, "set_ip_dscp(%u): failed setsockopt 
err=%d\n",
+                       link->ip_dscp, errno);
+               return -EIO;
+       }
        return 0;
 }
 
@@ -568,6 +585,10 @@
 int osmo_stream_srv_link_open(struct osmo_stream_srv_link *link)
 {
        int ret;
+       /* No need to set OSMO_SOCK_F_NONBLOCK since non-blocking behavior is 
only
+        * required later on, during accept() call, and and osmo_fd_register()
+        * below already takes care of setting the socket as non-blocking. */
+       const int sk_flags = OSMO_SOCK_F_BIND;
 
        if (link->ofd.fd >= 0) {
                /* No reconfigure needed for existing socket, we are fine */
@@ -581,7 +602,7 @@
 
        switch (link->sk_domain) {
        case AF_UNIX:
-               ret = osmo_sock_unix_init(link->sk_type, 0, link->addr[0], 
OSMO_SOCK_F_BIND);
+               ret = osmo_sock_unix_init(link->sk_type, 0, link->addr[0], 
sk_flags);
                break;
        case AF_UNSPEC:
        case AF_INET:
@@ -591,12 +612,12 @@
                case IPPROTO_SCTP:
                        ret = osmo_sock_init2_multiaddr2(link->sk_domain, 
link->sk_type, link->proto,
                                                         (const char 
**)link->addr, link->addrcnt, link->port,
-                                                        NULL, 0, 0, 
OSMO_SOCK_F_BIND, &link->ma_pars);
+                                                        NULL, 0, 0, sk_flags, 
&link->ma_pars);
                        break;
 #endif
                default:
                        ret = osmo_sock_init(link->sk_domain, link->sk_type, 
link->proto,
-                                            link->addr[0], link->port, 
OSMO_SOCK_F_BIND);
+                                            link->addr[0], link->port, 
sk_flags);
                }
                break;
        default:
@@ -605,6 +626,18 @@
        if (ret < 0)
                return ret;
 
+       if (link->ip_dscp > 0) {
+               int rc;
+               rc = osmo_sock_set_dscp(ret, link->ip_dscp);
+               if (rc < 0) {
+                       LOGSLNK(link, LOGL_ERROR, "set_ip_dscp(%u): failed 
setsockopt err=%d\n",
+                               link->ip_dscp, errno);
+                       close(ret);
+                       link->ofd.fd = -1;
+                       return -EIO;
+               }
+       }
+
        link->ofd.fd = ret;
        if (osmo_fd_register(&link->ofd) < 0) {
                close(ret);
@@ -792,8 +825,11 @@
        struct osmo_stream_srv *conn = osmo_iofd_get_data(iofd);
        LOGSSRV(conn, LOGL_DEBUG, "connected write\n");
 
-       if (res < 0)
-               LOGSSRV(conn, LOGL_ERROR, "error to send: %s\n", 
strerror(errno));
+       if (res < 0) {
+               char errbuf[64];
+               strerror_r(-res, errbuf, sizeof(errbuf));
+               LOGSSRV(conn, LOGL_ERROR, "error to send: %d (%s)\n", res, 
errbuf);
+       }
 
        if (osmo_iofd_txqueue_len(iofd) == 0)
                if (conn->flags & OSMO_STREAM_SRV_F_FLUSH_DESTROY)
@@ -1038,12 +1074,15 @@
 
        osmo_sock_get_name_buf(conn->sockname, sizeof(conn->sockname), fd);
 
+#ifdef HAVE_LIBSCTP
        if (link->proto == IPPROTO_SCTP) {
                conn->iofd = osmo_iofd_setup(conn, fd, conn->sockname, 
OSMO_IO_FD_MODE_RECVMSG_SENDMSG,
                                             &srv_ioops_sctp, conn);
                if (conn->iofd)
                        osmo_iofd_set_cmsg_size(conn->iofd, 
CMSG_SPACE(sizeof(struct sctp_sndrcvinfo)));
-       } else {
+       } else
+#endif
+       {
                conn->iofd = osmo_iofd_setup(conn, fd, conn->sockname, 
OSMO_IO_FD_MODE_READ_WRITE,
                                             &srv_ioops, conn);
        }
@@ -1096,8 +1135,11 @@
                talloc_free((void *)conn->name);
        conn->name = name;
 
-       if (conn->mode == OSMO_STREAM_MODE_OSMO_IO && conn->iofd)
-               osmo_iofd_set_name(conn->iofd, conn->name);
+       if (conn->mode == OSMO_STREAM_MODE_OSMO_IO && conn->iofd) {
+               char *tmp = talloc_asprintf(conn, "%s,%s", conn->name, 
conn->sockname);
+               osmo_iofd_set_name(conn->iofd, tmp);
+               talloc_free(tmp);
+       }
 }
 
 /*! Retrieve name previously set on the srv object (see 
osmo_stream_srv_set_name()).
@@ -1369,9 +1411,11 @@
                osmo_fd_write_enable(&conn->ofd);
                break;
        case OSMO_STREAM_MODE_OSMO_IO:
+#ifdef HAVE_LIBSCTP
                if (conn->srv->proto == IPPROTO_SCTP)
                        rc = stream_iofd_sctp_send_msgb(conn->iofd, msg, 
MSG_NOSIGNAL);
                else
+#endif
                        rc = osmo_iofd_write_msgb(conn->iofd, msg);
                if (rc < 0)
                        msgb_free(msg);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/twjit.c 
new/libosmo-netif-1.8.0/src/twjit.c
--- old/libosmo-netif-1.7.0/src/twjit.c 2025-12-04 06:19:35.000000000 +0100
+++ new/libosmo-netif-1.8.0/src/twjit.c 2026-08-21 07:19:39.000000000 +0200
@@ -51,7 +51,7 @@
        uint16_t drop_int_count;
 };
 
-/*! Each twjit instance is in one of 4 fundamental states at any moment,
+/*! Each twjit instance is in one of 5 fundamental states at any moment,
  *  as enumerated here.  See document section 2.3.1 for state transition
  *  diagram.
  */
@@ -62,6 +62,8 @@
        TWJIT_STATE_HUNT,
        /*! one subbuf is both flowing out and accepting new packets */
        TWJIT_STATE_FLOWING,
+       /*! limited continuation of FLOWING state past underrun */
+       TWJIT_STATE_UNDERRUN,
        /*! one subbuf is flowing out while another receives new packets */
        TWJIT_STATE_HANDOVER,
 };
@@ -89,6 +91,8 @@
        uint8_t read_sb;
        /*! current subbuf being written, 0 or 1 */
        uint8_t write_sb;
+       /*! UNDERRUN state: remaining number of ticks before we give up */
+       uint16_t underrun_countdown;
        /*! RTP timestamp of the most recently received packet */
        uint32_t last_ts;
        /*! RTP sequence number of the most recently received packet */
@@ -533,6 +537,34 @@
                }
                insert_pkt_write_sb(twjit, msg, rx_ts);
                return;
+       case TWJIT_STATE_UNDERRUN:
+               id = check_input_for_subbuf(twjit, false, rx_ssrc, rx_ts,
+                                           rtph->marker);
+               if (id == INPUT_CONTINUE) {
+                       /* Underrun extension mechanism did its intended
+                        * job: continue flow without reset. */
+                       twjit->state = TWJIT_STATE_FLOWING;
+                       insert_pkt_write_sb(twjit, msg, rx_ts);
+                       return;
+               }
+               /* For either INPUT_TOO_OLD or INPUT_RESET, we take the same
+                * path that existed prior to addition of UNDERRUN state:
+                * the original underrun was a "hard" one, and we initiate
+                * HUNT with this newly received packet.
+                *
+                * Please note that we don't increment too_old stats counter
+                * in the case of INPUT_TOO_OLD: that counter counts packets
+                * that were discarded for being too old in FLOWING state.
+                * In the present case, however, the packet is not discarded:
+                * instead it is fed into HUNT state to begin acquisition of
+                * a new flow.  This behavior is necessary in order to
+                * reacquire flow if the original underrun was caused by a
+                * sudden increase in IP path latency.
+                */
+               twjit->stats.underruns++;
+               twjit->state = TWJIT_STATE_HUNT;
+               init_subbuf_first_packet(twjit, msg, rx_ssrc, rx_ts);
+               return;
        default:
                OSMO_ASSERT(0);
        }
@@ -598,6 +630,30 @@
        sb->drop_int_count = twjit->config.thinning_int - 2;
 }
 
+static void underrun_advance_ts(struct osmo_twjit *twjit)
+{
+       struct twjit_subbuf *sb = &twjit->sb[twjit->read_sb];
+
+       sb->head_ts += twjit->ts_quantum;
+}
+
+/* This static function is called only from osmo_twjit_output() in the
+ * case of underrun in FLOWING state.  It has been factored out in order
+ * to reduce the level of indentation and thus make it easier to keep
+ * line length below the 80 character limit which the author regards as
+ * an unviolable Universal constant. */
+static void handle_flowing_underrun(struct osmo_twjit *twjit)
+{
+       if (twjit->config.underrun_ext) {
+               twjit->state = TWJIT_STATE_UNDERRUN;
+               twjit->underrun_countdown = twjit->config.underrun_ext - 1;
+               underrun_advance_ts(twjit);
+               twjit->stats.soft_underruns++;
+       } else {
+               twjit->state = TWJIT_STATE_EMPTY;
+       }
+}
+
 static void toss_read_queue(struct osmo_twjit *twjit)
 {
        struct twjit_subbuf *sb = &twjit->sb[twjit->read_sb];
@@ -628,11 +684,19 @@
                return pull_from_read_sb(twjit);
        case TWJIT_STATE_FLOWING:
                if (read_sb_is_empty(twjit)) {
-                       twjit->state = TWJIT_STATE_EMPTY;
+                       handle_flowing_underrun(twjit);
                        return NULL;
                }
                read_sb_thinning(twjit);
                return pull_from_read_sb(twjit);
+       case TWJIT_STATE_UNDERRUN:
+               if (twjit->underrun_countdown) {
+                       twjit->underrun_countdown--;
+                       underrun_advance_ts(twjit);
+               } else {
+                       twjit->state = TWJIT_STATE_EMPTY;
+               }
+               return NULL;
        case TWJIT_STATE_HANDOVER:
                if (starting_sb_is_ready(twjit)) {
                        toss_read_queue(twjit);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/src/twjit_conf.c 
new/libosmo-netif-1.8.0/src/twjit_conf.c
--- old/libosmo-netif-1.7.0/src/twjit_conf.c    2025-12-04 06:19:35.000000000 
+0100
+++ new/libosmo-netif-1.8.0/src/twjit_conf.c    2026-08-21 07:19:39.000000000 
+0200
@@ -136,6 +136,10 @@
                        conf->start_max_delta, VTY_NEWLINE);
        }
 
+       if (conf->underrun_ext) {
+               vty_out(vty, "%s underrun-extension %u%s", prefix,
+                       conf->underrun_ext, VTY_NEWLINE);
+       }
        vty_out(vty, "%s marker-handling %s%s", prefix,
                conf->handover_on_marker ? "handover" : "ignore", VTY_NEWLINE);
 
@@ -222,6 +226,25 @@
        return CMD_SUCCESS;
 }
 
+DEFUN(cfg_underrun_ext, cfg_underrun_ext_cmd,
+      "underrun-extension <1-65535>",
+      "Underrun extension for intentional gaps (DTX)\n"
+      "Maximum number of consecutive omitted packets\n")
+{
+       struct osmo_twjit_config *conf = vty->index;
+       conf->underrun_ext = atoi(argv[0]);
+       return CMD_SUCCESS;
+}
+
+DEFUN(cfg_no_underrun_ext, cfg_no_underrun_ext_cmd,
+      "no underrun-extension",
+      NO_STR "Underrun extension for intentional gaps\n")
+{
+       struct osmo_twjit_config *conf = vty->index;
+       conf->underrun_ext = 0;
+       return CMD_SUCCESS;
+}
+
 DEFUN(cfg_marker_handling, cfg_marker_handling_cmd,
       "marker-handling (handover|ignore)",
       "How to handle RTP packets with marker bit set\n"
@@ -246,6 +269,8 @@
        install_lib_element(twjit_node, &cfg_no_start_min_delta_cmd);
        install_lib_element(twjit_node, &cfg_start_max_delta_cmd);
        install_lib_element(twjit_node, &cfg_no_start_max_delta_cmd);
+       install_lib_element(twjit_node, &cfg_underrun_ext_cmd);
+       install_lib_element(twjit_node, &cfg_no_underrun_ext_cmd);
        install_lib_element(twjit_node, &cfg_marker_handling_cmd);
 }
 
@@ -329,6 +354,20 @@
        return 0;
 }
 
+/*! Non-vty function for underrun-extension setting
+ *
+ * \param[in] conf twjit config instance to operate on.
+ * \param[in] underrun_ext Maximum permissible intentional gap, in packets,
+ * or 0 to disable this mechanism.
+ * \returns 0 if successful, negative on errors.
+ */
+int osmo_twjit_config_set_underrun_ext(struct osmo_twjit_config *conf,
+                                       uint16_t underrun_ext)
+{
+       conf->underrun_ext = underrun_ext;
+       return 0;
+}
+
 /*! Non-vty function for marker-handling setting
  *
  * \param[in] conf twjit config instance to operate on.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/tests/package.m4 
new/libosmo-netif-1.8.0/tests/package.m4
--- old/libosmo-netif-1.7.0/tests/package.m4    2025-12-04 06:19:50.000000000 
+0100
+++ new/libosmo-netif-1.8.0/tests/package.m4    2026-08-21 07:19:56.000000000 
+0200
@@ -4,9 +4,9 @@
 m4_define([AT_PACKAGE_TARNAME],
   [libosmo-netif])
 m4_define([AT_PACKAGE_VERSION],
-  [1.7.0])
+  [1.8.0])
 m4_define([AT_PACKAGE_STRING],
-  [libosmo-netif 1.7.0])
+  [libosmo-netif 1.8.0])
 m4_define([AT_PACKAGE_BUGREPORT],
   [[email protected]])
 m4_define([AT_PACKAGE_URL],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libosmo-netif-1.7.0/tests/testsuite 
new/libosmo-netif-1.8.0/tests/testsuite
--- old/libosmo-netif-1.7.0/tests/testsuite     2025-12-04 06:19:50.000000000 
+0100
+++ new/libosmo-netif-1.8.0/tests/testsuite     2026-08-21 07:19:56.000000000 
+0200
@@ -926,7 +926,7 @@
 # List of tests.
 if $at_list_p; then
   cat <<_ATEOF || at_write_fail=1
-libosmo-netif 1.7.0 test suite test groups:
+libosmo-netif 1.8.0 test suite test groups:
 
  NUM: FILE-NAME:LINE     TEST-GROUP-NAME
       KEYWORDS
@@ -967,7 +967,7 @@
   exit $at_write_fail
 fi
 if $at_version_p; then
-  printf "%s\n" "$as_me (libosmo-netif 1.7.0)" &&
+  printf "%s\n" "$as_me (libosmo-netif 1.8.0)" &&
   cat <<\_ATEOF || at_write_fail=1
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1155,11 +1155,11 @@
 
 # Banners and logs.
 printf "%s\n" "## ------------------------------- ##
-## libosmo-netif 1.7.0 test suite. ##
+## libosmo-netif 1.8.0 test suite. ##
 ## ------------------------------- ##"
 {
   printf "%s\n" "## ------------------------------- ##
-## libosmo-netif 1.7.0 test suite. ##
+## libosmo-netif 1.8.0 test suite. ##
 ## ------------------------------- ##"
   echo
 
@@ -1976,7 +1976,7 @@
   printf "%s\n" "Please send $at_msg and all information you think might help:
 
    To: <[email protected]>
-   Subject: [libosmo-netif 1.7.0] $as_me: $at_msg1$at_msg2
+   Subject: [libosmo-netif 1.8.0] $as_me: $at_msg1$at_msg2
 
 You may investigate any problem if you feel able to do so, in which
 case the test suite provides a good starting point.  Its output may

Reply via email to