Upgrade libnl to libnl3_9_0

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update external/libnl
For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md

Test: TreeHugger
Change-Id: I66c6cb5c1f93f0caef2b74fa4c73e7e70f407ed2
diff --git a/.clang-format b/.clang-format
index bed344c..ad32417 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 #
-# clang-format configuration file. Intended for clang-format >= 4.
+# clang-format configuration file. Intended for clang-format >= 11.
 #
 # For more information, see:
 #
@@ -13,7 +13,7 @@
 AlignAfterOpenBracket: Align
 AlignConsecutiveAssignments: false
 AlignConsecutiveDeclarations: false
-#AlignEscapedNewlines: Left # Unknown to clang-format-4.0
+AlignEscapedNewlines: Left
 AlignOperands: true
 AlignTrailingComments: false
 AllowAllParametersOfDeclarationOnNextLine: false
@@ -37,24 +37,24 @@
   AfterObjCDeclaration: false
   AfterStruct: false
   AfterUnion: false
-  #AfterExternBlock: false # Unknown to clang-format-5.0
+  AfterExternBlock: false
   BeforeCatch: false
   BeforeElse: false
   IndentBraces: false
-  #SplitEmptyFunction: true # Unknown to clang-format-4.0
-  #SplitEmptyRecord: true # Unknown to clang-format-4.0
-  #SplitEmptyNamespace: true # Unknown to clang-format-4.0
+  SplitEmptyFunction: true
+  SplitEmptyRecord: true
+  SplitEmptyNamespace: true
 BreakBeforeBinaryOperators: None
 BreakBeforeBraces: Custom
-#BreakBeforeInheritanceComma: false # Unknown to clang-format-4.0
+BreakBeforeInheritanceComma: false
 BreakBeforeTernaryOperators: false
 BreakConstructorInitializersBeforeComma: false
-#BreakConstructorInitializers: BeforeComma # Unknown to clang-format-4.0
+BreakConstructorInitializers: BeforeComma
 BreakAfterJavaFieldAnnotations: false
 BreakStringLiterals: false
 ColumnLimit: 80
 CommentPragmas: '^ IWYU pragma:'
-#CompactNamespaces: false # Unknown to clang-format-4.0
+CompactNamespaces: false
 ConstructorInitializerAllOnOneLineOrOnePerLine: false
 ConstructorInitializerIndentWidth: 8
 ContinuationIndentWidth: 8
@@ -62,28 +62,30 @@
 DerivePointerAlignment: false
 DisableFormat: false
 ExperimentalAutoDetectBinPacking: false
-#FixNamespaceComments: false # Unknown to clang-format-4.0
+FixNamespaceComments: false
 
 # Taken from:
-#   git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \
+#   git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ tools/ \
 #   | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$,  - '\1'," \
-#   | sort | uniq
+#   | LC_ALL=C sort -u
 ForEachMacros:
   - 'list_for_each_safe'
   - 'nl_list_for_each_entry'
+  - 'nl_list_for_each_entry_safe'
   - 'nla_for_each_attr'
   - 'nla_for_each_nested'
   - 'nlmsg_for_each'
   - 'nlmsg_for_each_attr'
   - 'nlmsg_for_each_msg'
 
-#IncludeBlocks: Preserve # Unknown to clang-format-5.0
+IncludeBlocks: Preserve
 IncludeCategories:
   - Regex: '.*'
     Priority: 1
 IncludeIsMainRegex: '(Test)?$'
 IndentCaseLabels: false
-#IndentPPDirectives: None # Unknown to clang-format-5.0
+IndentGotoLabels: false
+IndentPPDirectives: None
 IndentWidth: 8
 IndentWrappedFunctionNames: false
 JavaScriptQuotes: Leave
@@ -93,13 +95,13 @@
 MacroBlockEnd: ''
 MaxEmptyLinesToKeep: 1
 NamespaceIndentation: None
-#ObjCBinPackProtocolList: Auto # Unknown to clang-format-5.0
+ObjCBinPackProtocolList: Auto
 ObjCBlockIndentWidth: 8
 ObjCSpaceAfterProperty: true
 ObjCSpaceBeforeProtocolList: true
 
 # Taken from git's rules
-#PenaltyBreakAssignment: 10 # Unknown to clang-format-4.0
+PenaltyBreakAssignment: 10
 PenaltyBreakBeforeFirstCallParameter: 30
 PenaltyBreakComment: 10
 PenaltyBreakFirstLessLess: 0
@@ -110,14 +112,14 @@
 PointerAlignment: Right
 ReflowComments: false
 SortIncludes: false
-#SortUsingDeclarations: false # Unknown to clang-format-4.0
+SortUsingDeclarations: false
 SpaceAfterCStyleCast: false
 SpaceAfterTemplateKeyword: true
 SpaceBeforeAssignmentOperators: true
-#SpaceBeforeCtorInitializerColon: true # Unknown to clang-format-5.0
-#SpaceBeforeInheritanceColon: true # Unknown to clang-format-5.0
-SpaceBeforeParens: ControlStatements
-#SpaceBeforeRangeBasedForLoopColon: true # Unknown to clang-format-5.0
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatementsExceptForEachMacros
+SpaceBeforeRangeBasedForLoopColon: true
 SpaceInEmptyParentheses: false
 SpacesBeforeTrailingComments: 1
 SpacesInAngles: false
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..afddf49
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,7 @@
+[flake8]
+extend-ignore =
+    E203
+    E501
+filename =
+    *.py
+    *.py.in
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
new file mode 100644
index 0000000..a5b6f4c
--- /dev/null
+++ b/.git-blame-ignore-revs
@@ -0,0 +1,7 @@
+# List of commits that did automated reformatting. You can ignore them
+# during git-blame with `--ignore-rev` or `--ignore-revs-file`.
+#
+#   $ git config --add 'blame.ignoreRevsFile' '.git-blame-ignore-revs'
+#
+3c753e3c94b01c63bf99b2709f4780e2df4608eb
+53da4712439dfd1ccdfeb8d4ca3027082a826e29
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ef0afad..708928e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,29 @@
   pull_request:
 
 jobs:
+  clang-format:
+    runs-on: ubuntu-latest
+    container:
+      image: fedora:39
+    steps:
+      - name: Install packages
+        run: |
+          sudo dnf install -y \
+            clang-tools-extra \
+            git
+
+      - name: Check out repository code
+        uses: actions/checkout@v3
+
+      - name: Setup git
+        run: |
+          git config --global --add safe.directory "$PWD"
+
+      - name: Formatting with clang-format
+        run: |
+          clang-format --version
+          ./tools/clang-format.sh -n
+
   ci:
     strategy:
       matrix:
@@ -31,24 +54,35 @@
           python-version: 3.x
 
       - name: Lint Python
+        if: ${{ matrix.cc == 'gcc' }}
         run: |
           python3 -m pip install flake8
-          flake8 . --count --select=E703,E9,F63,F7,F82,Y --show-source --statistics
+          flake8 . --count --show-source --statistics
+
+      - name: Code formatting with Python black
+        if: ${{ matrix.cc == 'gcc' }}
+        run: |
+          python3 -m pip install black==22.12.0
+          black --check .
 
       - name: Build
         run: |
           set -x
 
           export CC="${{ matrix.cc }}"
-          export CFLAGS="-DNL_MORE_ASSERTS=1000 -O2 -Werror -Wall -Wdeclaration-after-statement -Wvla -std=gnu11"
+          export CFLAGS="-DNL_MORE_ASSERTS=1000 -O2 -Werror -Wall -Wdeclaration-after-statement -Wvla -std=gnu11 -fexceptions"
           if [ "$CC" = "clang" ]; then
                   CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument -Wno-error=unused-function"
+                  export LDFLAGS="-Wl,--no-undefined-version,--fatal-warnings"
+          else
+                  export LDFLAGS="-Wl,--no-undefined-version"
           fi
 
           ./autogen.sh
           ./configure
           make -j 5
         shell: bash
+
       - name: Build Unit Tests
         run: make -j 5 check-progs
 
@@ -57,8 +91,8 @@
           set -x
           export NLTST_SEED_RAND=
           for i in `seq 1 5`; do
-            tests/check-all
             tests/check-direct
+            tests/check-all
             make -j check
           done
 
@@ -66,36 +100,35 @@
         run: |
           set -x
           export NLTST_SEED_RAND=
-          CK_FORK=no libtool --mode=execute valgrind --error-exitcode=66 --leak-check=full -s --show-leak-kinds=all ./tests/check-all
           CK_FORK=no libtool --mode=execute valgrind --error-exitcode=66 --leak-check=full -s --show-leak-kinds=all ./tests/check-direct
+          CK_FORK=no libtool --mode=execute valgrind --error-exitcode=66 --leak-check=full -s --show-leak-kinds=all ./tests/check-all
         shell: bash
 
       - name: Install packages for Release
         run: |
-          test "${{ matrix.cc }}" == gcc || exit 0
-          sudo apt-get -y --no-install-recommends install \
+          python3 -m pip install \
             asciidoc \
+            graphviz \
+            pygments
+          sudo apt-get -y --no-install-recommends install \
             doxygen \
             graphviz \
             mscgen \
-            source-highlight \
-            python3-pygments
+            source-highlight
 
       - name: Build Release
         run: |
-          test "${{ matrix.cc }}" == gcc || exit 0
           set -x
           git clean -fdx
+          export CC="${{ matrix.cc }}"
           NO_GPG_SIGN=1 ./tools/build_release.sh BuildAll
 
       - name: Build out-of-tree and disable-static
         run: |
           set -x
-
           git clean -fdx
-
           export CC="${{ matrix.cc }}"
-          export CFLAGS="-Werror -Wall -Wdeclaration-after-statement -Wvla -std=gnu11"
+          export CFLAGS="-Werror -Wall -Wdeclaration-after-statement -Wvla -std=gnu11 -fexceptions"
           if [ "$CC" = "clang" ]; then
                   CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument -Wno-error=unused-function"
           fi
@@ -109,4 +142,73 @@
           export NLTST_SEED_RAND=
           make -j 5 check
 
+      - name: Link with mold
+        run: |
+          sudo apt-get -y --no-install-recommends install \
+            mold
+          git clean -fdx
+          export LDFLAGS="-fuse-ld=mold -Wl,--fatal-warnings"
+          ./autogen.sh
+          ./configure
+          make -j 5 V=1
+
       - run: echo "🍏 This job's status is ${{ job.status }}."
+
+  ci-alpine:
+    runs-on: ubuntu-latest
+    container:
+      image: alpine:latest
+    steps:
+      - name: Install packages
+        run: |
+          apk add \
+            autoconf \
+            automake \
+            bash \
+            bison \
+            check-dev \
+            flex \
+            gcc \
+            git \
+            libtool \
+            linux-headers \
+            make \
+            musl-dev \
+            pkgconfig
+
+      - name: Check out repository code
+        uses: actions/checkout@v3
+
+      - name: Setup git
+        run: |
+          git config --global --add safe.directory "$PWD"
+
+      - name: Build
+        run: |
+          set -x
+
+          export CC="${{ matrix.cc }}"
+          export CFLAGS="-DNL_MORE_ASSERTS=1000 -O2 -Werror -Wall -Wdeclaration-after-statement -Wvla -std=gnu11 -fexceptions"
+          if [ "$CC" = "clang" ]; then
+                  CFLAGS="$CFLAGS -Wno-error=unused-command-line-argument -Wno-error=unused-function"
+                  export LDFLAGS="-Wl,--no-undefined-version,--fatal-warnings"
+          else
+                  export LDFLAGS="-Wl,--no-undefined-version"
+          fi
+
+          ./autogen.sh
+          ./configure
+          make -j 5
+          make -j 5 check-progs
+
+      - name: Run Unit Tests
+        run: |
+          set -x
+          export NLTST_SEED_RAND=
+          for i in `seq 1 5`; do
+            tests/check-direct
+            # unshare() does not work (EPERM). This test currently cannot pass
+            # (odd).
+            # tests/check-all
+            # make -j check
+          done
diff --git a/.gitignore b/.gitignore
index da3eb81..cb825cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+*~
 .deps
 .libs
 .dirstamp
@@ -5,7 +6,6 @@
 *.lo
 *.o
 *.swp
-*.patch
 Makefile
 Makefile.in
 defs.h.in
@@ -23,12 +23,15 @@
 /doc/Doxyfile
 /doc/aclocal.m4
 /doc/api/*.css
+/doc/api/*.dot
 /doc/api/*.html
 /doc/api/*.js
 /doc/api/*.map
 /doc/api/*.md5
 /doc/api/*.png
 /doc/api/*.tag
+/doc/api/_formula*
+/doc/api/doxygen.svg
 /doc/api/formula.repository
 /doc/api/jquery.js
 /doc/asciidoc.tmp
@@ -40,7 +43,10 @@
 /doc/images/asciidoc__*.png
 /doc/images/core__*
 /doc/libnl.dict
+/include/config.h
+/include/config.h.in
 /include/netlink/version.h
+/include/stamp-h1
 /lib/defs.h
 /lib/lex.yy.c
 /lib/libnl-*.so*
@@ -56,9 +62,8 @@
 /libtool
 /m4/libtool.m4
 /m4/lt*.m4
-/python/build
-/python/capi.py
-/python/capi_wrap.c
+/python/**/capi*
+/python/build/
 /python/setup.py
 /src/genl-ctrl-list
 /src/idiag-socket-details
@@ -96,6 +101,7 @@
 /src/nl-neigh-delete
 /src/nl-neigh-list
 /src/nl-neightbl-list
+/src/nl-nh-list
 /src/nl-pktloc-lookup
 /src/nl-qdisc-add
 /src/nl-qdisc-delete
diff --git a/METADATA b/METADATA
index cb610c1..5e52a66 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update libnl
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/libnl
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "libnl"
 description: "Netlink Library Suite"
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://github.com/thom311/libnl"
-  }
-  url {
-    type: GIT
-    value: "https://github.com/thom311/libnl.git"
-  }
-  version: "libnl3_7_0"
   license_type: RESTRICTED
   last_upgrade_date {
-    year: 2023
-    month: 1
-    day: 9
+    year: 2024
+    month: 4
+    day: 4
+  }
+  homepage: "https://github.com/thom311/libnl"
+  identifier {
+    type: "Git"
+    value: "https://github.com/thom311/libnl.git"
+    version: "libnl3_9_0"
   }
 }
diff --git a/Makefile.am b/Makefile.am
index ef0f82d..1e76649 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -8,6 +8,7 @@
 
 check_PROGRAMS =
 check_programs =
+check_local =
 
 bin_PROGRAMS =
 sbin_PROGRAMS =
@@ -110,6 +111,7 @@
 	include/netlink/route/neightbl.h \
 	include/netlink/route/netconf.h \
 	include/netlink/route/nexthop.h \
+	include/netlink/route/nh.h \
 	include/netlink/route/pktloc.h \
 	include/netlink/route/qdisc.h \
 	include/netlink/route/route.h \
@@ -148,6 +150,7 @@
 libnlinclude_netlink_route_link_HEADERS = \
 	include/netlink/route/link/api.h \
 	include/netlink/route/link/bonding.h \
+	include/netlink/route/link/bridge_info.h \
 	include/netlink/route/link/bridge.h \
 	include/netlink/route/link/can.h \
 	include/netlink/route/link/geneve.h \
@@ -211,6 +214,7 @@
 	include/netlink/cli/link.h \
 	include/netlink/cli/mdb.h \
 	include/netlink/cli/neigh.h \
+	include/netlink/cli/nh.h \
 	include/netlink/cli/qdisc.h \
 	include/netlink/cli/route.h \
 	include/netlink/cli/rule.h \
@@ -219,11 +223,38 @@
 	$(NULL)
 endif
 
+public_headers = \
+	$(libnlinclude_netlink_HEADERS) \
+	$(libnlinclude_netlink_fib_lookup_HEADERS) \
+	$(libnlinclude_netlink_genl_HEADERS) \
+	$(libnlinclude_netlink_idiag_HEADERS) \
+	$(libnlinclude_netlink_netfilter_HEADERS) \
+	$(libnlinclude_netlink_route_HEADERS) \
+	$(libnlinclude_netlink_route_act_HEADERS) \
+	$(libnlinclude_netlink_route_cls_HEADERS) \
+	$(libnlinclude_netlink_route_cls_ematch_HEADERS) \
+	$(libnlinclude_netlink_route_link_HEADERS) \
+	$(libnlinclude_netlink_route_qdisc_HEADERS) \
+	$(libnlinclude_netlink_xfrm_HEADERS) \
+	$(libnlinclude_netlink_cli_HEADERS) \
+	$(NULL)
+
 noinst_HEADERS = \
+	include/base/nl-base-utils.h \
+	include/linux-private/linux/atm.h \
+	include/linux-private/linux/atmapi.h \
+	include/linux-private/linux/atmioc.h \
+	include/linux-private/linux/atmsap.h \
+	include/linux-private/linux/byteorder/little_endian.h \
 	include/linux-private/linux/can/netlink.h \
+	include/linux-private/linux/const.h \
+	include/linux-private/linux/errno.h \
+	include/linux-private/linux/ethtool.h \
+	include/linux-private/linux/falloc.h \
 	include/linux-private/linux/fib_rules.h \
 	include/linux-private/linux/gen_stats.h \
 	include/linux-private/linux/genetlink.h \
+	include/linux-private/linux/hdlc/ioctl.h \
 	include/linux-private/linux/if.h \
 	include/linux-private/linux/if_addr.h \
 	include/linux-private/linux/if_arp.h \
@@ -231,56 +262,70 @@
 	include/linux-private/linux/if_ether.h \
 	include/linux-private/linux/if_link.h \
 	include/linux-private/linux/if_macsec.h \
+	include/linux-private/linux/if_packet.h \
 	include/linux-private/linux/if_tunnel.h \
 	include/linux-private/linux/if_vlan.h \
 	include/linux-private/linux/in.h \
 	include/linux-private/linux/in6.h \
+	include/linux-private/linux/in_route.h \
 	include/linux-private/linux/inet_diag.h \
+	include/linux-private/linux/ioctl.h \
 	include/linux-private/linux/ip.h \
 	include/linux-private/linux/ipv6.h \
 	include/linux-private/linux/libc-compat.h \
+	include/linux-private/linux/limits.h \
 	include/linux-private/linux/lwtunnel.h \
 	include/linux-private/linux/mpls.h \
 	include/linux-private/linux/mpls_iptunnel.h \
 	include/linux-private/linux/neighbour.h \
 	include/linux-private/linux/netconf.h \
+	include/linux-private/linux/netdevice.h \
 	include/linux-private/linux/netfilter.h \
 	include/linux-private/linux/netfilter/nf_conntrack_common.h \
+	include/linux-private/linux/netfilter/nf_conntrack_tcp.h \
 	include/linux-private/linux/netfilter/nfnetlink.h \
 	include/linux-private/linux/netfilter/nfnetlink_compat.h \
 	include/linux-private/linux/netfilter/nfnetlink_conntrack.h \
 	include/linux-private/linux/netfilter/nfnetlink_log.h \
 	include/linux-private/linux/netfilter/nfnetlink_queue.h \
 	include/linux-private/linux/netlink.h \
+	include/linux-private/linux/nexthop.h \
 	include/linux-private/linux/pkt_cls.h \
 	include/linux-private/linux/pkt_sched.h \
+	include/linux-private/linux/posix_types.h \
 	include/linux-private/linux/rtnetlink.h \
+	include/linux-private/linux/seg6.h \
+	include/linux-private/linux/seg6_hmac.h \
+	include/linux-private/linux/seg6_iptunnel.h \
+	include/linux-private/linux/seg6_local.h \
 	include/linux-private/linux/snmp.h \
 	include/linux-private/linux/sock_diag.h \
 	include/linux-private/linux/socket.h \
+	include/linux-private/linux/stddef.h \
+	include/linux-private/linux/swab.h \
+	include/linux-private/linux/taskstats.h \
 	include/linux-private/linux/tc_act/tc_gact.h \
 	include/linux-private/linux/tc_act/tc_mirred.h \
 	include/linux-private/linux/tc_act/tc_nat.h \
 	include/linux-private/linux/tc_act/tc_skbedit.h \
 	include/linux-private/linux/tc_act/tc_vlan.h \
+	include/linux-private/linux/tc_ematch/tc_em_cmp.h \
 	include/linux-private/linux/tc_ematch/tc_em_meta.h \
+	include/linux-private/linux/tc_ematch/tc_em_nbyte.h \
+	include/linux-private/linux/tc_ematch/tc_em_text.h \
+	include/linux-private/linux/types.h \
+	include/linux-private/linux/version.h \
 	include/linux-private/linux/veth.h \
 	include/linux-private/linux/xfrm.h \
-	include/netlink-private/cache-api.h \
-	include/netlink-private/genl.h \
-	include/netlink-private/netlink.h \
-	include/netlink-private/nl-auto.h \
-	include/netlink-private/object-api.h \
-	include/netlink-private/route/link/api.h \
-	include/netlink-private/route/link/sriov.h \
-	include/netlink-private/route/mpls.h \
-	include/netlink-private/route/nexthop-encap.h \
-	include/netlink-private/route/tc-api.h \
-	include/netlink-private/route/utils.h \
-	include/netlink-private/socket.h \
-	include/netlink-private/tc.h \
-	include/netlink-private/types.h \
-	include/netlink-private/utils.h \
+	include/nl-aux-core/nl-core.h \
+	include/nl-aux-route/nl-route.h \
+	include/nl-aux-xfrm/nl-xfrm.h \
+	include/nl-default.h \
+	include/nl-priv-dynamic-core/cache-api.h \
+	include/nl-priv-dynamic-core/nl-core.h \
+	include/nl-priv-dynamic-core/object-api.h \
+	include/nl-priv-dynamic-route/nl-priv-dynamic-route.h \
+	include/nl-priv-static-route/nl-priv-static-route.h \
 	$(NULL)
 
 ###############################################################################
@@ -334,15 +379,18 @@
 
 ###############################################################################
 
+default_includes = \
+	-I$(srcdir)/include/linux-private \
+	-I$(srcdir)/include \
+	-I$(builddir)/include \
+	$(NULL)
+
 lib_cppflags = \
 	$(warn_cppflags) \
 	-D_GNU_SOURCE \
 	-DSYSCONFDIR=\"$(sysconfdir)/libnl\" \
-	-I$(srcdir)/include/linux-private \
-	-I$(srcdir)/include \
-	-I$(builddir)/include \
-	-I$(builddir)/lib/route \
-	-I$(builddir)/lib/route/cls
+	$(default_includes) \
+	$(NULL)
 
 lib_LTLIBRARIES += lib/libnl-3.la
 
@@ -358,7 +406,9 @@
 	lib/hash.c \
 	lib/hashtable.c \
 	lib/mpls.c \
+	lib/mpls.h \
 	lib/msg.c \
+	lib/nl-core.h \
 	lib/nl.c \
 	lib/object.c \
 	lib/socket.c \
@@ -401,10 +451,12 @@
 	lib/route/cls/mall.c \
 	lib/route/cls/police.c \
 	lib/route/cls/u32.c \
+	lib/route/link-sriov.h \
 	lib/route/link.c \
 	lib/route/link/api.c \
 	lib/route/link/bonding.c \
 	lib/route/link/bridge.c \
+	lib/route/link/bridge_info.c \
 	lib/route/link/can.c \
 	lib/route/link/dummy.c \
 	lib/route/link/geneve.c \
@@ -418,6 +470,7 @@
 	lib/route/link/ipip.c \
 	lib/route/link/ipvlan.c \
 	lib/route/link/ipvti.c \
+	lib/route/link/link-api.h \
 	lib/route/link/macsec.c \
 	lib/route/link/macvlan.c \
 	lib/route/link/ppp.c \
@@ -433,9 +486,12 @@
 	lib/route/neigh.c \
 	lib/route/neightbl.c \
 	lib/route/netconf.c \
+	lib/route/nexthop-encap.h \
 	lib/route/nexthop.c \
 	lib/route/nexthop_encap.c \
+	lib/route/nh.c \
 	lib/route/nh_encap_mpls.c \
+	lib/route/nl-route.h \
 	lib/route/pktloc.c \
 	lib/route/qdisc.c \
 	lib/route/qdisc/blackhole.c \
@@ -458,6 +514,7 @@
 	lib/route/route_utils.c \
 	lib/route/rtnl.c \
 	lib/route/rule.c \
+	lib/route/tc-api.h \
 	lib/route/tc.c \
 	$(NULL)
 nodist_lib_libnl_route_3_la_SOURCES = \
@@ -465,7 +522,11 @@
 EXTRA_lib_libnl_route_3_la_DEPENDENCIES = \
 	libnl-route-3.sym
 lib_libnl_route_3_la_CPPFLAGS = \
-	$(lib_cppflags)
+	$(lib_cppflags) \
+	-I$(srcdir)/lib/route \
+	-I$(builddir)/lib/route \
+	-I$(builddir)/lib/route/cls \
+	$(NULL)
 lib_libnl_route_3_la_LDFLAGS = \
 	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
 	-Wl,--version-script=$(srcdir)/libnl-route-3.sym
@@ -482,6 +543,7 @@
 	lib/idiag/idiag_msg_obj.c \
 	lib/idiag/idiag_req_obj.c \
 	lib/idiag/idiag_vegasinfo_obj.c \
+	lib/idiag/nl-idiag.h \
 	$(NULL)
 EXTRA_lib_libnl_idiag_3_la_DEPENDENCIES = \
 	libnl-idiag-3.sym
@@ -500,6 +562,7 @@
 	lib/genl/family.c \
 	lib/genl/genl.c \
 	lib/genl/mngt.c \
+	lib/genl/nl-genl.h \
 	$(NULL)
 EXTRA_lib_libnl_genl_3_la_DEPENDENCIES = \
 	libnl-genl-3.sym
@@ -524,6 +587,7 @@
 	lib/netfilter/log_obj.c \
 	lib/netfilter/netfilter.c \
 	lib/netfilter/nfnl.c \
+	lib/netfilter/nl-netfilter.h \
 	lib/netfilter/queue.c \
 	lib/netfilter/queue_msg.c \
 	lib/netfilter/queue_msg_obj.c \
@@ -545,6 +609,7 @@
 lib_libnl_xfrm_3_la_SOURCES = \
 	lib/xfrm/ae.c \
 	lib/xfrm/lifetime.c \
+	lib/xfrm/nl-xfrm.h \
 	lib/xfrm/sa.c \
 	lib/xfrm/selector.c \
 	lib/xfrm/sp.c \
@@ -629,6 +694,7 @@
 	src/lib/exp.c \
 	src/lib/link.c \
 	src/lib/neigh.c \
+	src/lib/nh.c \
 	src/lib/qdisc.c \
 	src/lib/route.c \
 	src/lib/rule.c \
@@ -642,9 +708,8 @@
 	-D_GNU_SOURCE \
 	-DPKGLIBDIR=\"$(pkglibdir)\" \
 	-DSYSCONFDIR=\"$(sysconfdir)\" \
-	-I$(srcdir)/include/linux-private \
-	-I$(srcdir)/include \
-	-I$(builddir)/include
+	$(default_includes) \
+	$(NULL)
 src_lib_libnl_cli_3_la_LDFLAGS = \
 	$(src_lib_ldflags) \
 	-Wl,--version-script=$(srcdir)/libnl-cli-3.sym
@@ -662,9 +727,8 @@
 	$(warn_cppflags) \
 	-D_GNU_SOURCE \
 	-DSYSCONFDIR=\"$(sysconfdir)/libnl\" \
-	-I$(srcdir)/include/linux-private \
-	-I$(srcdir)/include \
-	-I$(builddir)/include
+	$(default_includes) \
+	$(NULL)
 
 src_ldadd = \
 	src/lib/libnl-cli-3.la \
@@ -712,6 +776,7 @@
 	src/nl-neigh-delete \
 	src/nl-neigh-list \
 	src/nl-neightbl-list \
+	src/nl-nh-list \
 	src/nl-pktloc-lookup \
 	src/nl-qdisc-add \
 	src/nl-qdisc-delete \
@@ -811,6 +876,8 @@
 src_nl_neigh_list_LDADD =           $(src_ldadd)
 src_nl_neightbl_list_CPPFLAGS =     $(src_cppflags)
 src_nl_neightbl_list_LDADD =        $(src_ldadd)
+src_nl_nh_list_CPPFLAGS =           $(src_cppflags)
+src_nl_nh_list_LDADD =              $(src_ldadd)
 src_nl_pktloc_lookup_CPPFLAGS =     $(src_cppflags)
 src_nl_pktloc_lookup_LDADD =        $(src_ldadd)
 src_nl_qdisc_add_CPPFLAGS =         $(src_cppflags)
@@ -840,9 +907,8 @@
 	$(warn_cppflags) \
 	-D_GNU_SOURCE \
 	-DSYSCONFDIR=\"$(sysconfdir)/libnl\" \
-	-I$(srcdir)/include/linux-private \
-	-I$(srcdir)/include \
-	-I$(builddir)/include
+	$(default_includes) \
+	$(NULL)
 
 tests_ldadd = \
 	lib/libnl-3.la \
@@ -1024,6 +1090,12 @@
 
 ###############################################################################
 
+python-build:
+	cd "$(srcdir)/python"; \
+	python setup.py build
+
+.PHONY: python-build
+
 EXTRA_DIST += \
 	python/README \
 	\
@@ -1038,7 +1110,6 @@
 	python/examples/wiphy.py \
 	\
 	python/netlink/capi.i \
-	python/netlink/fixes.h \
 	python/netlink/__init__.py \
 	python/netlink/core.py \
 	python/netlink/util.py \
@@ -1063,6 +1134,29 @@
 
 ###############################################################################
 
+%.build-headers-test.c: %
+	mkdir -p "$(dir $@)"
+	printf "#include <$$(echo "$<" | sed 's|.*\<include/netlink/|netlink/|')>\nint main(int argc, char **argv) { return 0; }" > $@
+
+%.build-headers-test.o: %.build-headers-test.c
+	$(COMPILE) -Wall -Werror -Wno-error=cpp -I$(srcdir)/include -I$(builddir)/include -c -o $@ $<
+
+BUILD_HEADERS_OBJS = $(patsubst %,%.build-headers-test.o,$(public_headers))
+
+# Test whether the public headers are all self-contained and can be build.
+# This test is not hooked up as `make check`.
+check-local-build-headers: $(BUILD_HEADERS_OBJS)
+
+CLEANFILES += $(BUILD_HEADERS_OBJS)
+
+check_local += check-local-build-headers
+
+###############################################################################
+
+check-local: $(check_local)
+
+.PHONY: $(check_local)
+
 check_PROGRAMS += $(check_programs)
 TESTS += $(check_programs)
 
@@ -1090,6 +1184,6 @@
 
 check-progs: all $(check_PROGRAMS) $(check_LTLIBRARIES)
 
-###############################################################################
+.PHONY: check-progs
 
-.PHONY = check-progs
+###############################################################################
diff --git a/autogen.sh b/autogen.sh
index e498fae..b0e2fde 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,5 +1,7 @@
 #!/bin/bash
 
+set -e
+
 die() {
     echo "$@" >&2
     exit 1
@@ -10,6 +12,6 @@
 cd "$BASEDIR" || die "Could not change into base directory $BASEDIR"
 
 autoreconf -fi || die "Error during autoreconf"
-rm -Rf autom4te.cache;
+rm -rf autom4te.cache
 
 doc/autogen.sh || die "Error during doc/autogen.sh"
diff --git a/configure.ac b/configure.ac
index b6bdcec..bc8b390 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@
 
 # copied from glib
 m4_define([libnl_major_version], [3])
-m4_define([libnl_minor_version], [7])
+m4_define([libnl_minor_version], [9])
 m4_define([libnl_micro_version], [0])
 m4_define([libnl_git_sha], [m4_esyscmd([ ( [ -d ./.git/ ] && [ "$(readlink -f ./.git/)" = "$(readlink -f "$(git rev-parse --git-dir 2>/dev/null)" 2>/dev/null)" ] && git rev-parse --verify -q HEAD 2>/dev/null ) || true ])])
 
@@ -36,11 +36,11 @@
 m4_define([libnl_version],
 	  [libnl_major_version.libnl_minor_version.libnl_micro_version])
 
-AC_INIT(libnl, [libnl_version], [], [], [http://www.infradead.org/~tgr/libnl/])
-AC_CONFIG_HEADERS([lib/defs.h])
+AC_INIT([libnl],[libnl_version],[],[],[http://www.infradead.org/~tgr/libnl/])
+AC_CONFIG_HEADERS([include/config.h])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIR([m4])
-AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
+AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], [])
 m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
 
@@ -64,7 +64,7 @@
 AC_PROG_CC
 AM_PROG_CC_C_O
 AC_PROG_INSTALL
-AM_PROG_LIBTOOL
+LT_INIT
 AC_PROG_MKDIR_P
 AC_CHECK_PROGS(FLEX, 'flex')
 AC_CHECK_PROGS(YACC, 'bison -y')
@@ -120,6 +120,10 @@
 
 AC_CHECK_FUNCS([strerror_l])
 
+AC_CHECK_DECLS([getprotobyname_r, getprotobynumber_r], [], [], [[
+    #include <netdb.h>
+]])
+
 AC_CONFIG_FILES([
 Makefile
 libnl-3.0.pc
@@ -148,26 +152,13 @@
 
 AC_OUTPUT
 
-echo "-------------------------------------------------------------------------------"
-echo "                                  NOTE"
-echo ""
-echo " There have been some changes starting with 3.2 regarding where and how libnl"
-echo " is being installed on the system in order to allow multiple libnl versions"
-echo " to be installed in parallel:"
-echo ""
-echo "    - Headers will be installed in ${includedir}/libnl${MAJ_VERSION}, therefore"
-echo "      you will need to add \"-I/usr/include/libnl${MAJ_VERSION}\" to CFLAGS"
-echo ""
-echo "    - The library basename was renamed to libnl-${MAJ_VERSION}, i.e. the SO names become"
-echo "      libnl-${MAJ_VERSION}.so., libnl-route-${MAJ_VERSION}.so, etc."
-echo ""
-echo "    - libtool versioning was assumed, to ease detection of compatible library"
-echo "      versions."
-echo ""
-echo " If you are using pkg-config for detecting and linking against the library "
-echo " things will continue magically as if nothing every happened. If you are "
-echo " linking manually you need to adapt your Makefiles or switch to using "
-echo " pkg-config files."
-echo ""
-echo "-------------------------------------------------------------------------------"
-
+echo
+echo "libnl $LIBNL_VERSION configuration${LIBNL_GIT_SHA:+ (git:$LIBNL_GIT_SHA)}:"
+echo "    --enable-pthreads=$enable_pthreads"
+echo "    --enable-static=$enable_static"
+echo
+echo "    --enable-debug=$enable_debug"
+echo "    --enable-cli=$enable_cli"
+echo
+echo "    check: $has_check"
+echo
diff --git a/doc/autogen.sh b/doc/autogen.sh
index a569614..a147e93 100755
--- a/doc/autogen.sh
+++ b/doc/autogen.sh
@@ -1,4 +1,10 @@
 #!/bin/bash
 
-autoreconf -fi;
-rm -Rf autom4te.cache;
+set -e
+
+BASEDIR="$(dirname "$0")"
+
+cd "$BASEDIR" || die "Could not change into base directory $BASEDIR"
+
+autoreconf -fi
+rm -rf autom4te.cache
diff --git a/doc/configure.ac b/doc/configure.ac
index 4fb3cc3..c16e20e 100644
--- a/doc/configure.ac
+++ b/doc/configure.ac
@@ -3,8 +3,8 @@
 # Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
 #
 
-AC_INIT(libnl-doc, [3.7.0], [http://www.infradead.org/~tgr/libnl/])
-AC_CONFIG_MACRO_DIR([m4])
+AC_INIT(libnl-doc, [3.9.0], [http://www.infradead.org/~tgr/libnl/])
+AC_CONFIG_MACRO_DIR([../m4])
 AC_CONFIG_AUX_DIR([build-aux])
 AM_INIT_AUTOMAKE([foreign])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)], [])
diff --git a/doc/doxygen-link.py b/doc/doxygen-link.py
index 1f3f67c..2dcd5f0 100755
--- a/doc/doxygen-link.py
+++ b/doc/doxygen-link.py
@@ -1,43 +1,46 @@
 #!/usr/bin/env python
 
 from __future__ import print_function
-import fileinput
 import re
 import sys
 
 
-rc_script = re.compile(r'\s*(.*\S)?\s*')
+rc_script = re.compile(r"\s*(.*\S)?\s*")
+
 
 def parse_dict(filename):
-	links = {}
-	for line in open(filename, 'r'):
-		m = re.match('^([^=]+)=([^\n]+)$', line)
-		if not m:
-			continue
-		name = m.group(1)
-		value = m.group(2)
+    links = {}
+    for line in open(filename, "r"):
+        m = re.match("^([^=]+)=([^\n]+)$", line)
+        if not m:
+            continue
+        name = m.group(1)
+        value = m.group(2)
 
-		# strip leading and trailing whitespace
-		m = rc_script.match(name)
-		if m:
-			name = m.group(1)
+        # strip leading and trailing whitespace
+        m = rc_script.match(name)
+        if m:
+            name = m.group(1)
 
-		# skip special names
-		if name == '':
-			continue
-		if name == '\\':
-			continue
+        # skip special names
+        if name == "":
+            continue
+        if name == "\\":
+            continue
 
-		links[name] = "<a href=\"" + value + "\" class=\"dg\">" + name + "</a>"
-	return links
+        links[name] = '<a href="' + value + '" class="dg">' + name + "</a>"
+    return links
+
 
 links = parse_dict(sys.argv[1])
 
+
 def translate(match):
-	return links[match.group(1)]
+    return links[match.group(1)]
+
 
 # match for all names, with word boundaries \b
-rc = re.compile(r'\b(' + '|'.join(map(re.escape, sorted(links, reverse=True))) + r')\b')
+rc = re.compile(r"\b(" + "|".join(map(re.escape, sorted(links, reverse=True))) + r")\b")
 
-for line in open(sys.argv[2], 'r'):
-	print(rc.sub(translate, line), end='')
+for line in open(sys.argv[2], "r"):
+    print(rc.sub(translate, line), end="")
diff --git a/doc/resolve-asciidoc-refs.py b/doc/resolve-asciidoc-refs.py
index 7999156..d661c56 100755
--- a/doc/resolve-asciidoc-refs.py
+++ b/doc/resolve-asciidoc-refs.py
@@ -2,26 +2,27 @@
 
 from __future__ import print_function
 
-import fileinput
 import re
 import sys
 
 refs = {}
 complete_file = ""
 
-for line in open(sys.argv[1], 'r'):
-	complete_file += line
+for line in open(sys.argv[1], "r"):
+    complete_file += line
 
-for m in re.findall('\[\[(.+)\]\]\n=+ ([^\n]+)', complete_file):
-	ref, title = m
-	refs["<<" + ref + ">>"] = "<<" + ref + ", " + title + ">>"
+for m in re.findall("\\[\\[(.+)\\]\\]\n=+ ([^\n]+)", complete_file):
+    ref, title = m
+    refs["<<" + ref + ">>"] = "<<" + ref + ", " + title + ">>"
+
 
 def translate(match):
-	try:
-		return refs[match.group(0)]
-	except KeyError:
-		return ""
+    try:
+        return refs[match.group(0)]
+    except KeyError:
+        return ""
 
-rc = re.compile('|'.join(map(re.escape, sorted(refs, reverse=True))))
-for line in open(sys.argv[1], 'r'):
-	print(rc.sub(translate, line), end='')
+
+rc = re.compile("|".join(map(re.escape, sorted(refs, reverse=True))))
+for line in open(sys.argv[1], "r"):
+    print(rc.sub(translate, line), end="")
diff --git a/include/base/README.md b/include/base/README.md
new file mode 100644
index 0000000..3da1621
--- /dev/null
+++ b/include/base/README.md
@@ -0,0 +1,13 @@
+include/base
+============
+
+This directory contains libnl-independent helper.
+
+It's an internal "library" of helpers, that purely depend
+on C and external dependencies.
+
+Currently, it's also header-only, so there is no need to link
+with anything special.
+
+This can be used freely by all our internal code, but it's private API,
+so it cannot be used in public headers.
diff --git a/include/base/nl-base-utils.h b/include/base/nl-base-utils.h
new file mode 100644
index 0000000..03d568e
--- /dev/null
+++ b/include/base/nl-base-utils.h
@@ -0,0 +1,842 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef __NETLINK_BASE_NL_BASE_UTILS_H__
+#define __NETLINK_BASE_NL_BASE_UTILS_H__
+
+#include <byteswap.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#ifndef DISABLE_PTHREADS
+#include <pthread.h>
+#endif
+
+/*****************************************************************************/
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define ntohll(x) (x)
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+#define ntohll(x) bswap_64((x))
+#endif
+#define htonll(x) ntohll(x)
+
+/*****************************************************************************/
+
+#define _NL_STRINGIFY_ARG(contents) #contents
+#define _NL_STRINGIFY(macro_or_string) _NL_STRINGIFY_ARG(macro_or_string)
+
+/*****************************************************************************/
+
+#if defined(__GNUC__)
+#define _NL_PRAGMA_WARNING_DO(warning) \
+	_NL_STRINGIFY(GCC diagnostic ignored warning)
+#elif defined(__clang__)
+#define _NL_PRAGMA_WARNING_DO(warning) \
+	_NL_STRINGIFY(clang diagnostic ignored warning)
+#endif
+
+/* you can only suppress a specific warning that the compiler
+ * understands. Otherwise you will get another compiler warning
+ * about invalid pragma option.
+ * It's not that bad however, because gcc and clang often have the
+ * same name for the same warning. */
+
+#if defined(__GNUC__) && \
+	(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define _NL_PRAGMA_WARNING_DISABLE(warning)                 \
+	_Pragma("GCC diagnostic push")                      \
+		_Pragma(_NL_PRAGMA_WARNING_DO("-Wpragmas")) \
+			_Pragma(_NL_PRAGMA_WARNING_DO(warning))
+#elif defined(__clang__)
+#define _NL_PRAGMA_WARNING_DISABLE(warning)                                \
+	_Pragma("clang diagnostic push")                                   \
+		_Pragma(_NL_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \
+			_Pragma(_NL_PRAGMA_WARNING_DO(warning))
+#else
+#define _NL_PRAGMA_WARNING_DISABLE(warning)
+#endif
+
+#if defined(__GNUC__) && \
+	(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
+#define _NL_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop")
+#elif defined(__clang__)
+#define _NL_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop")
+#else
+#define _NL_PRAGMA_WARNING_REENABLE
+#endif
+
+/*****************************************************************************/
+
+#define _nl_packed __attribute__((__packed__))
+#define _nl_unused __attribute__((__unused__))
+#define _nl_always_inline __attribute__((__always_inline__))
+#define _nl_used __attribute__((__used__))
+#define _nl_pure __attribute__((__pure__))
+#define _nl_const __attribute__((__const__))
+#define _nl_noreturn __attribute__((__noreturn__))
+#define _nl_warn_unused_result __attribute__((__warn_unused_result__))
+#define _nl_printf(a, b) __attribute__((__format__(__printf__, a, b)))
+#define _nl_align(s) __attribute__((__aligned__(s)))
+#define _nl_section(s) __attribute__((__section__(s)))
+#define _nl_alignof(type) __alignof(type)
+#define _nl_alignas(type) _nl_align(_nl_alignof(type))
+#define _nl_deprecated(msg) __attribute__((__deprecated__(msg)))
+#define _nl_init __attribute__((constructor))
+#define _nl_exit __attribute__((destructor))
+#define _nl_auto(fcn) __attribute__((__cleanup__(fcn)))
+
+/*****************************************************************************/
+
+#ifdef thread_local
+#define _nl_thread_local thread_local
+/*
+ * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
+ * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
+ */
+#elif __STDC_VERSION__ >= 201112L &&                     \
+	!(defined(__STDC_NO_THREADS__) ||                \
+	  (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 && \
+	   __GLIBC_MINOR__ < 16))
+#define _nl_thread_local _Thread_local
+#else
+#define _nl_thread_local __thread
+#endif
+
+/*****************************************************************************/
+
+#define _NL_STATIC_ASSERT(cond) ((void)sizeof(char[(cond) ? 1 : -1]))
+
+/*****************************************************************************/
+
+#if defined(NL_MORE_ASSERTS) && NL_MORE_ASSERTS > 0
+#define _nl_assert(cond) assert(cond)
+#else
+#define _nl_assert(cond)              \
+	do {                          \
+		if (0) {              \
+			assert(cond); \
+		}                     \
+	} while (0)
+#endif
+
+#define _nl_assert_not_reached() assert(0)
+
+/*****************************************************************************/
+
+#define _NL_BIT(n) (1ull << (n))
+
+/*****************************************************************************/
+
+#define _NL_PASTE_ARGS(identifier1, identifier2) identifier1##identifier2
+#define _NL_PASTE(identifier1, identifier2) \
+	_NL_PASTE_ARGS(identifier1, identifier2)
+
+/* Taken from systemd's UNIQ_T and UNIQ macros. */
+
+#define _NL_UNIQ_T(x, uniq) _NL_PASTE(__unique_prefix_, _NL_PASTE(x, uniq))
+#define _NL_UNIQ __COUNTER__
+
+/*****************************************************************************/
+
+#define _nl_assert_addr_family_or_unspec(addr_family)             \
+	do {                                                      \
+		typeof(addr_family) _addr_family = (addr_family); \
+                                                                  \
+		_nl_assert(_addr_family == AF_UNSPEC ||           \
+			   _addr_family == AF_INET ||             \
+			   _addr_family == AF_INET6);             \
+	} while (0)
+
+#define _nl_assert_addr_family(addr_family)                       \
+	do {                                                      \
+		typeof(addr_family) _addr_family = (addr_family); \
+                                                                  \
+		_nl_assert(_addr_family == AF_INET ||             \
+			   _addr_family == AF_INET6);             \
+	} while (0)
+
+/*****************************************************************************/
+
+#define _NL_SWAP(pa, pb)                   \
+	do {                               \
+		typeof(*(pa)) *_pa = (pa); \
+		typeof(*(pb)) *_pb = (pb); \
+		typeof(*_pa) _tmp;         \
+                                           \
+		_nl_assert(_pa);           \
+		_nl_assert(_pb);           \
+		_tmp = *_pa;               \
+		*_pa = *_pb;               \
+		*_pb = _tmp;               \
+	} while (0)
+
+/*****************************************************************************/
+
+#define _NL_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define ARRAY_SIZE(arr) _NL_N_ELEMENTS(arr)
+
+/*****************************************************************************/
+
+/* This is also defined in stddef.h */
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER)
+#endif
+
+/*****************************************************************************/
+
+static inline uintptr_t _nl_ptr_to_uintptr(const void *p)
+{
+	/* in C, pointers can only be compared (with less-than or greater-than) under certain
+	 * circumstances. Since uintptr_t is supposed to be able to represent the pointer
+	 * as a plain integer and also support to convert the integer back to the pointer,
+	 * it should be safer to compare the pointers directly.
+	 *
+	 * Of course, this function isn't very useful beyond that its use makes it clear
+	 * that we want to compare pointers by value, which otherwise may not be valid. */
+	return (uintptr_t)p;
+}
+
+/*****************************************************************************/
+
+static inline int _nl_strcmp0(const char *s1, const char *s2)
+{
+	int c;
+
+	/* like g_strcmp0(), but this is inlinable.
+	 *
+	 * Also, it is guaranteed to return either -1, 0, or 1. */
+	if (s1 == s2)
+		return 0;
+	if (!s1)
+		return -1;
+	if (!s2)
+		return 1;
+	c = strcmp(s1, s2);
+	if (c < 0)
+		return -1;
+	if (c > 0)
+		return 1;
+	return 0;
+}
+
+static inline bool _nl_streq(const char *a, const char *b)
+{
+	return !strcmp(a, b);
+}
+
+static inline bool _nl_streq0(const char *a, const char *b)
+{
+	return a == b || (a && b && _nl_streq(a, b));
+}
+
+static inline int _nl_memcmp(const void *s1, const void *s2, size_t n)
+{
+	/* Workaround undefined behavior in memcmp() with NULL pointers. */
+	if (n == 0)
+		return 0;
+	_nl_assert(s1);
+	_nl_assert(s2);
+	return memcmp(s1, s2, n);
+}
+
+static inline bool _nl_memeq(const void *s1, const void *s2, size_t len)
+{
+	return _nl_memcmp(s1, s2, len) == 0;
+}
+
+static inline void *_nl_memcpy(void *restrict dest, const void *restrict src,
+			       size_t n)
+{
+	/* Workaround undefined behavior in memcpy() with NULL pointers. */
+	if (n == 0)
+		return dest;
+
+	_nl_assert(src);
+	return memcpy(dest, src, n);
+}
+
+/*****************************************************************************/
+
+#define _NL_INT_IS_SIGNED(arg) (!(((typeof(arg))-1) > 0))
+
+#define _NL_INT_SAME_SIGNEDNESS(arg1, arg2) \
+	(_NL_INT_IS_SIGNED(arg1) == _NL_INT_IS_SIGNED(arg2))
+
+/*****************************************************************************/
+
+/* glib's MIN()/MAX() macros don't have function-like behavior, in that they evaluate
+ * the argument possibly twice.
+ *
+ * Taken from systemd's MIN()/MAX() macros. */
+
+#define _NL_MIN(a, b) __NL_MIN(_NL_UNIQ, a, _NL_UNIQ, b)
+#define __NL_MIN(aq, a, bq, b)                                                 \
+	({                                                                     \
+		typeof(a) _NL_UNIQ_T(A, aq) = (a);                             \
+		typeof(b) _NL_UNIQ_T(B, bq) = (b);                             \
+                                                                               \
+		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq),   \
+							  _NL_UNIQ_T(B, bq))); \
+                                                                               \
+		((_NL_UNIQ_T(A, aq) < _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \
+							   _NL_UNIQ_T(B, bq)); \
+	})
+
+#define _NL_MAX(a, b) __NL_MAX(_NL_UNIQ, a, _NL_UNIQ, b)
+#define __NL_MAX(aq, a, bq, b)                                                 \
+	({                                                                     \
+		typeof(a) _NL_UNIQ_T(A, aq) = (a);                             \
+		typeof(b) _NL_UNIQ_T(B, bq) = (b);                             \
+                                                                               \
+		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_NL_UNIQ_T(A, aq),   \
+							  _NL_UNIQ_T(B, bq))); \
+                                                                               \
+		((_NL_UNIQ_T(A, aq) > _NL_UNIQ_T(B, bq)) ? _NL_UNIQ_T(A, aq) : \
+							   _NL_UNIQ_T(B, bq)); \
+	})
+
+#define _NL_CLAMP(x, low, high) \
+	__NL_CLAMP(_NL_UNIQ, x, _NL_UNIQ, low, _NL_UNIQ, high)
+#define __NL_CLAMP(xq, x, lowq, low, highq, high)                     \
+	({                                                            \
+		typeof(x) _NL_UNIQ_T(X, xq) = (x);                    \
+		typeof(low) _NL_UNIQ_T(LOW, lowq) = (low);            \
+		typeof(high) _NL_UNIQ_T(HIGH, highq) = (high);        \
+                                                                      \
+		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(            \
+			_NL_UNIQ_T(X, xq), _NL_UNIQ_T(LOW, lowq)));   \
+		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(            \
+			_NL_UNIQ_T(X, xq), _NL_UNIQ_T(HIGH, highq))); \
+                                                                      \
+		((_NL_UNIQ_T(X, xq) > _NL_UNIQ_T(HIGH, highq)) ?      \
+			 _NL_UNIQ_T(HIGH, highq) :                    \
+		 (_NL_UNIQ_T(X, xq) < _NL_UNIQ_T(LOW, lowq)) ?        \
+			 _NL_UNIQ_T(LOW, lowq) :                      \
+			 _NL_UNIQ_T(X, xq));                          \
+	})
+
+#define _NL_MAX_WITH_CMP(cmp, a, b)               \
+	({                                        \
+		typeof(a) _a = (a);               \
+		typeof(b) _b = (b);               \
+                                                  \
+		(((cmp(_a, _b)) >= 0) ? _a : _b); \
+	})
+
+/* evaluates to (void) if _A or _B are not constant or of different types */
+#define _NL_CONST_MAX(_A, _B)                                            \
+	(__builtin_choose_expr(                                          \
+		(__builtin_constant_p(_A) && __builtin_constant_p(_B) && \
+		 __builtin_types_compatible_p(typeof(_A), typeof(_B))),  \
+		((_A) > (_B)) ? (_A) : (_B), ((void)0)))
+
+/*****************************************************************************/
+
+#define _NL_CMP_RETURN(c)                        \
+	do {                                     \
+		const int _cc = (c);             \
+                                                 \
+		if (_cc)                         \
+			return _cc < 0 ? -1 : 1; \
+	} while (0)
+
+#define _NL_CMP_RETURN_DIRECT(c)                                  \
+	/* Usually we want that our CMP functions return strictly
+	 * -1, 0, or 1. _NL_CMP_RETURN_DIRECT() is like _NL_CMP_RETURN(),
+	 *  except, it does not clamp the integer value. */ \
+	do {                                                      \
+		const int _cc = (c);                              \
+                                                                  \
+		if (_cc)                                          \
+			return _cc;                               \
+	} while (0)
+
+#define _NL_CMP_SELF(a, b)          \
+	do {                        \
+		typeof(a) _a = (a); \
+		typeof(b) _b = (b); \
+                                    \
+		if (_a == _b)       \
+			return 0;   \
+		if (!_a)            \
+			return -1;  \
+		if (!_b)            \
+			return 1;   \
+	} while (0)
+
+/*****************************************************************************/
+
+#define _NL_CMP_DIRECT(a, b)                                        \
+	do {                                                        \
+		typeof(a) _a = (a);                                 \
+		typeof(b) _b = (b);                                 \
+                                                                    \
+		_NL_STATIC_ASSERT(_NL_INT_SAME_SIGNEDNESS(_a, _b)); \
+                                                                    \
+		if (_a != _b)                                       \
+			return (_a < _b) ? -1 : 1;                  \
+	} while (0)
+
+#define _NL_CMP_DIRECT_UNSAFE(a, b)                                                     \
+	/* This variant is "unsafe", because it evaluates the arguments more then once.
+	 * This is only useful for bitfields, for which typeof() doesn't work.
+	 * Don't use otherwise. */ \
+	do {                                                                            \
+		if ((a) != (b))                                                         \
+			return ((a) < (b)) ? -1 : 1;                                    \
+	} while (0)
+
+/* In the general case, direct pointer comparison is undefined behavior in C.
+ * Avoid that by casting pointers to void* and then to uintptr_t. This comparison
+ * is not really meaningful, except that it provides some kind of stable sort order
+ * between pointers (that can otherwise not be compared). */
+#define _NL_CMP_DIRECT_PTR(a, b) \
+	_NL_CMP_DIRECT(_nl_ptr_to_uintptr(a), _nl_ptr_to_uintptr(b))
+
+#define _NL_CMP_DIRECT_BOOL(a, b) _NL_CMP_DIRECT(!!(a), !!(b))
+
+#define _NL_CMP_DIRECT_MEMCMP(a, b, size) \
+	_NL_CMP_RETURN(_nl_memcmp((a), (b), (size)))
+
+#define _NL_CMP_DIRECT_STRCMP(a, b) _NL_CMP_RETURN_DIRECT(strcmp((a), (b)))
+
+#define _NL_CMP_DIRECT_STRCMP0(a, b) \
+	_NL_CMP_RETURN_DIRECT(_nl_strcmp0((a), (b)))
+
+#define _NL_CMP_DIRECT_STR_INTERNED(a, b)                                                    \
+	/* This is interned strings, which are first checked for equality only using pointer
+     * comparison. Only in case of differences, the sort order is still determined by strcmp(). */ \
+	do {                                                                                 \
+		const char *const _a = (a);                                                  \
+		const char *const _b = (b);                                                  \
+                                                                                             \
+		if (_a != _b)                                                                \
+			_NL_CMP_RETURN_DIRECT(_nl_strcmp0(_a, _b));                          \
+	} while (0)
+
+#define _NL_CMP_DIRECT_IN6ADDR(a, b)                                     \
+	do {                                                             \
+		const struct in6_addr *const _a = (a);                   \
+		const struct in6_addr *const _b = (b);                   \
+                                                                         \
+		_NL_CMP_RETURN(memcmp(_a, _b, sizeof(struct in6_addr))); \
+	} while (0)
+
+/*****************************************************************************/
+
+#define _NL_CMP_FIELD(a, b, field) _NL_CMP_DIRECT(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_UNSAFE(a, b, field)                                               \
+	/* This variant is "unsafe", because it evaluates the arguments more then once.
+	 * This is only useful for bitfields, for which typeof() doesn't work.
+	 * Don't use otherwise. */ \
+	_NL_CMP_DIRECT_UNSAFE(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_BOOL(a, b, field) \
+	_NL_CMP_DIRECT_BOOL(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_STR(a, b, field) \
+	_NL_CMP_DIRECT_STRCMP(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_STR0(a, b, field) \
+	_NL_CMP_DIRECT_STRCMP0(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_STR_INTERNED(a, b, field) \
+	_NL_CMP_DIRECT_STR_INTERNED(((a)->field), ((b)->field))
+
+#define _NL_CMP_FIELD_MEMCMP_LEN(a, b, field, len)          \
+	_NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), \
+			      _NL_MIN(len, sizeof((a)->field)))
+
+#define _NL_CMP_FIELD_MEMCMP(a, b, field) \
+	_NL_CMP_DIRECT_MEMCMP(&((a)->field), &((b)->field), sizeof((a)->field))
+
+#define _NL_CMP_FIELD_IN6ADDR(a, b, field) \
+	_NL_CMP_DIRECT_IN6ADDR(&((a)->field), &((b)->field))
+
+/*****************************************************************************/
+
+/* internal macro to calculate the size of a struct @type up to (and including) @field.
+ * this will be used for .minlen policy fields, so that we require only a field of up
+ * to the given size. */
+#define _nl_offsetofend(type, field) \
+	(offsetof(type, field) + sizeof(((type *)NULL)->field))
+
+/*****************************************************************************/
+
+#define _nl_clear_pointer(pp, destroy)                                         \
+	({                                                                     \
+		__typeof__(*(pp)) *_pp = (pp);                                 \
+		__typeof__(*_pp) _p;                                           \
+		int _changed = 0;                                              \
+                                                                               \
+		if (_pp && (_p = *_pp)) {                                      \
+			_nl_unused const void *const _p_check_is_pointer = _p; \
+                                                                               \
+			*_pp = NULL;                                           \
+                                                                               \
+			(destroy)(_p);                                         \
+                                                                               \
+			_changed = 1;                                          \
+		}                                                              \
+		_changed;                                                      \
+	})
+
+#define _nl_clear_free(pp) _nl_clear_pointer(pp, free)
+
+#define _nl_steal_pointer(pp)                        \
+	({                                           \
+		__typeof__(*(pp)) *const _pp = (pp); \
+		__typeof__(*_pp) _p = NULL;          \
+                                                     \
+		if (_pp && (_p = *_pp)) {            \
+			*_pp = NULL;                 \
+		}                                    \
+                                                     \
+		_p;                                  \
+	})
+
+/*****************************************************************************/
+
+#define _nl_malloc_maybe_a(alloca_maxlen, bytes, to_free)  \
+	({                                                 \
+		const size_t _bytes = (bytes);             \
+		__typeof__(to_free) _to_free = (to_free);  \
+		__typeof__(*_to_free) _ptr;                \
+                                                           \
+		_NL_STATIC_ASSERT((alloca_maxlen) <= 500); \
+		_nl_assert(_to_free && !*_to_free);        \
+                                                           \
+		if (_bytes <= (alloca_maxlen)) {           \
+			_ptr = alloca(_bytes);             \
+		} else {                                   \
+			_ptr = malloc(_bytes);             \
+			*_to_free = _ptr;                  \
+		};                                         \
+                                                           \
+		_ptr;                                      \
+	})
+
+/*****************************************************************************/
+
+static inline char *_nl_strncpy_trunc(char *dst, const char *src, size_t len)
+{
+	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
+	 * behavior of strncpy(). This is just strncpy() with gracefully handling truncation
+	 * (and disabling the "-Wstringop-truncation" warning).
+	 *
+	 * Note that truncation is silently accepted.
+	 */
+
+	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation");
+	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow");
+
+	if (len > 0) {
+		_nl_assert(dst);
+		_nl_assert(src);
+
+		strncpy(dst, src, len);
+
+		dst[len - 1] = '\0';
+	}
+
+	_NL_PRAGMA_WARNING_REENABLE;
+	_NL_PRAGMA_WARNING_REENABLE;
+
+	return dst;
+}
+
+static inline char *_nl_strncpy_assert(char *dst, const char *src, size_t len)
+{
+	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
+	 * behavior of strncpy(). This is just strncpy() with assertion against truncation
+	 * (and disabling the "-Wstringop-truncation" warning).
+	 *
+	 * Note that truncation is still a bug and there is an _nl_assert()
+	 * against that.
+	 */
+
+	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-truncation");
+	_NL_PRAGMA_WARNING_DISABLE("-Wstringop-overflow");
+
+	if (len > 0) {
+		_nl_assert(dst);
+		_nl_assert(src);
+
+		strncpy(dst, src, len);
+
+		_nl_assert(dst[len - 1] == '\0');
+
+		dst[len - 1] = '\0';
+	}
+
+	_NL_PRAGMA_WARNING_REENABLE;
+	_NL_PRAGMA_WARNING_REENABLE;
+
+	return dst;
+}
+
+#define _NL_RETURN_ON_ERR(cmd)       \
+	do {                         \
+		int _err;            \
+                                     \
+		_err = (cmd);        \
+		if (_err < 0)        \
+			return _err; \
+	} while (0)
+
+#define _NL_RETURN_E_ON_ERR(e, cmd)                 \
+	do {                                        \
+		int _err;                           \
+                                                    \
+		_err = (cmd);                       \
+		if (_err < 0) {                     \
+			_NL_STATIC_ASSERT((e) > 0); \
+			return -(e);                \
+		}                                   \
+	} while (0)
+
+/* _NL_RETURN_ON_PUT_ERR() shall only be used with a put command (nla_put or nlmsg_append).
+ * These commands can either fail with a regular error code (which gets propagated)
+ * or with -NLE_NOMEM. However, they don't really try to allocate memory, so we don't
+ * want to propagate -NLE_NOMEM. Instead, we coerce such failure to -NLE_MSGSIZE. */
+#define _NL_RETURN_ON_PUT_ERR(put_cmd)                                                                  \
+	do {                                                                                            \
+		int _err;                                                                               \
+                                                                                                        \
+		_err = (put_cmd);                                                                       \
+		if (_err < 0) {                                                                         \
+			if (_err == -NLE_NOMEM) {                                                       \
+				/* nla_put() returns -NLE_NOMEM in case of out of buffer size. We don't
+				 * want to propagate that error and map it to -NLE_MSGSIZE. */ \
+				return -NLE_MSGSIZE;                                                    \
+			}                                                                               \
+			/* any other error can only be due to invalid parameters. Propagate the
+			 * error, however also assert that it cannot be reached. */         \
+			_nl_assert_not_reached();                                                       \
+			return _err;                                                                    \
+		} else                                                                                  \
+			_nl_assert(_err == 0);                                                          \
+	} while (0)
+
+static inline int _nl_close(int fd)
+{
+	int r;
+
+	r = close(fd);
+	_nl_assert(r == 0 || fd < 0 || errno != EBADF);
+	return r;
+}
+
+static inline void *_nl_memdup(const void *ptr, size_t len)
+{
+	void *p;
+
+	if (len == 0) {
+		/* malloc() leaves it implementation defined whether to return NULL.
+		 * Callers rely on returning NULL if len is zero. */
+		return NULL;
+	}
+
+	p = malloc(len);
+	if (!p)
+		return NULL;
+	memcpy(p, ptr, len);
+	return p;
+}
+
+#define _nl_memdup_ptr(ptr) ((__typeof__(ptr))_nl_memdup((ptr), sizeof(*(ptr))))
+
+/*****************************************************************************/
+
+static inline size_t _nl_addr_family_to_size(int addr_family)
+{
+	if (addr_family == AF_INET)
+		return sizeof(in_addr_t);
+	if (addr_family == AF_INET6)
+		return sizeof(struct in6_addr);
+	return 0;
+}
+
+/*****************************************************************************/
+
+typedef union {
+	in_addr_t addr4;
+	struct in_addr a4;
+	struct in6_addr a6;
+} _NLIPAddr;
+
+static inline char *_nl_inet_ntop(int addr_family, const void *addr, char *buf)
+{
+	char *r;
+
+	_nl_assert_addr_family(addr_family);
+	_nl_assert(addr);
+
+	/* inet_ntop() is documented to fail, but if we pass a known address family
+	 * and a suitably large buffer, it cannot. Assert for that. */
+
+	r = (char *)inet_ntop(addr_family, addr, buf,
+			      (addr_family == AF_INET) ? INET_ADDRSTRLEN :
+							 INET6_ADDRSTRLEN);
+	_nl_assert(r == buf);
+	_nl_assert(strlen(r) < ((addr_family == AF_INET) ? INET_ADDRSTRLEN :
+							   INET6_ADDRSTRLEN));
+
+	return r;
+}
+
+static inline char *_nl_inet_ntop_dup(int addr_family, const void *addr)
+{
+	return (char *)_nl_inet_ntop(addr_family, addr,
+				     malloc((addr_family == AF_INET) ?
+						    INET_ADDRSTRLEN :
+						    INET6_ADDRSTRLEN));
+}
+
+/*****************************************************************************/
+
+#define _NL_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
+	static inline void name(void *v)                \
+	{                                               \
+		if (*((CastType *)v))                   \
+			func(*((CastType *)v));         \
+	}                                               \
+	struct _nl_dummy_for_tailing_semicolon
+
+#define _NL_AUTO_DEFINE_FCN_STRUCT(CastType, name, func) \
+	static inline void name(CastType *v)             \
+	{                                                \
+		if (v)                                   \
+			func(v);                         \
+	}                                                \
+	struct _nl_dummy_for_tailing_semicolon
+
+#define _NL_AUTO_DEFINE_FCN_TYPED0(CastType, name, func) \
+	static inline void name(CastType *v)             \
+	{                                                \
+		if (*v)                                  \
+			func(*v);                        \
+	}                                                \
+	struct _nl_dummy_for_tailing_semicolon
+
+#define _NL_AUTO_DEFINE_FCN_INDIRECT0(CastType, name, func) \
+	static inline void name(CastType *v)                \
+	{                                                   \
+		if (*v)                                     \
+			func(v);                            \
+	}                                                   \
+	struct _nl_dummy_for_tailing_semicolon
+
+#define _nl_auto_free _nl_auto(_nl_auto_free_fcn)
+_NL_AUTO_DEFINE_FCN_VOID0(void *, _nl_auto_free_fcn, free);
+
+/*****************************************************************************/
+
+#define NSEC_PER_SEC 1000000000L
+
+struct trans_tbl {
+	uint64_t i;
+	const char *a;
+};
+
+#define __ADD(id, name)             \
+	{                           \
+		.i = id, .a = #name \
+	}
+
+#define BUG()                                                                \
+	do {                                                                 \
+		fprintf(stderr, "BUG at file position %s:%d:%s\n", __FILE__, \
+			__LINE__, __func__);                                 \
+		assert(0);                                                   \
+	} while (0)
+
+#define BUG_ON(condition)      \
+	do {                   \
+		if (condition) \
+			BUG(); \
+	} while (0)
+
+#define APPBUG(msg)                                                          \
+	do {                                                                 \
+		fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n", __FILE__, \
+			__LINE__, __func__, msg);                            \
+		assert(0);                                                   \
+	} while (0)
+
+/*****************************************************************************/
+
+#ifndef DISABLE_PTHREADS
+#define NL_LOCK(NAME) pthread_mutex_t(NAME) = PTHREAD_MUTEX_INITIALIZER
+#define NL_RW_LOCK(NAME) pthread_rwlock_t(NAME) = PTHREAD_RWLOCK_INITIALIZER
+
+static inline void nl_lock(pthread_mutex_t *lock)
+{
+	pthread_mutex_lock(lock);
+}
+
+static inline void nl_unlock(pthread_mutex_t *lock)
+{
+	pthread_mutex_unlock(lock);
+}
+
+static inline void nl_read_lock(pthread_rwlock_t *lock)
+{
+	pthread_rwlock_rdlock(lock);
+}
+
+static inline void nl_read_unlock(pthread_rwlock_t *lock)
+{
+	pthread_rwlock_unlock(lock);
+}
+
+static inline void nl_write_lock(pthread_rwlock_t *lock)
+{
+	pthread_rwlock_wrlock(lock);
+}
+
+static inline void nl_write_unlock(pthread_rwlock_t *lock)
+{
+	pthread_rwlock_unlock(lock);
+}
+
+#else
+#define NL_LOCK(NAME) int __unused_lock_##NAME __attribute__((unused))
+#define NL_RW_LOCK(NAME) int __unused_lock_##NAME __attribute__((unused))
+
+#define nl_lock(LOCK) \
+	do {          \
+	} while (0)
+#define nl_unlock(LOCK) \
+	do {            \
+	} while (0)
+#define nl_read_lock(LOCK) \
+	do {               \
+	} while (0)
+#define nl_read_unlock(LOCK) \
+	do {                 \
+	} while (0)
+#define nl_write_lock(LOCK) \
+	do {                \
+	} while (0)
+#define nl_write_unlock(LOCK) \
+	do {                  \
+	} while (0)
+#endif
+
+#endif /* __NETLINK_BASE_NL_BASE_UTILS_H__ */
diff --git a/include/linux-private/linux/atm.h b/include/linux-private/linux/atm.h
new file mode 100644
index 0000000..e33ff6b
--- /dev/null
+++ b/include/linux-private/linux/atm.h
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* atm.h - general ATM declarations */
+ 
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
+ 
+
+/*
+ * WARNING: User-space programs should not #include <linux/atm.h> directly.
+ *          Instead, #include <atm.h>
+ */
+
+#ifndef _LINUX_ATM_H
+#define _LINUX_ATM_H
+
+/*
+ * BEGIN_xx and END_xx markers are used for automatic generation of
+ * documentation. Do not change them.
+ */
+
+
+#include <linux/atmapi.h>
+#include <linux/atmsap.h>
+#include <linux/atmioc.h>
+#include <linux/types.h>
+
+
+/* general ATM constants */
+#define ATM_CELL_SIZE		    53	/* ATM cell size incl. header */
+#define ATM_CELL_PAYLOAD	    48	/* ATM payload size */
+#define ATM_AAL0_SDU		    52	/* AAL0 SDU size */
+#define ATM_MAX_AAL34_PDU	 65535	/* maximum AAL3/4 PDU payload */
+#define ATM_AAL5_TRAILER	     8	/* AAL5 trailer size */
+#define ATM_MAX_AAL5_PDU	 65535	/* maximum AAL5 PDU payload */
+#define ATM_MAX_CDV		  9999	/* maximum (default) CDV */
+#define ATM_NOT_RSV_VCI		    32	/* first non-reserved VCI value */
+
+#define ATM_MAX_VPI		   255	/* maximum VPI at the UNI */
+#define ATM_MAX_VPI_NNI		  4096	/* maximum VPI at the NNI */
+#define ATM_MAX_VCI		 65535	/* maximum VCI */
+
+
+/* "protcol" values for the socket system call */
+#define ATM_NO_AAL	0		/* AAL not specified */
+#define ATM_AAL0	13		/* "raw" ATM cells */
+#define ATM_AAL1	1		/* AAL1 (CBR) */
+#define ATM_AAL2	2		/* AAL2 (VBR) */
+#define ATM_AAL34	3		/* AAL3/4 (data) */
+#define ATM_AAL5	5		/* AAL5 (data) */
+
+/*
+ * socket option name coding functions
+ *
+ * Note that __SO_ENCODE and __SO_LEVEL are somewhat a hack since the
+ * << 22 only reserves 9 bits for the level.  On some architectures
+ * SOL_SOCKET is 0xFFFF, so that's a bit of a problem
+ */
+
+#define __SO_ENCODE(l,n,t)	((((l) & 0x1FF) << 22) | ((n) << 16) | \
+				sizeof(t))
+#define __SO_LEVEL_MATCH(c,m)	(((c) >> 22) == ((m) & 0x1FF))
+#define __SO_NUMBER(c)		(((c) >> 16) & 0x3f)
+#define __SO_SIZE(c)		((c) & 0x3fff)
+
+/*
+ * ATM layer
+ */
+
+#define SO_SETCLP	__SO_ENCODE(SOL_ATM,0,int)
+			    /* set CLP bit value - TODO */
+#define SO_CIRANGE	__SO_ENCODE(SOL_ATM,1,struct atm_cirange)
+			    /* connection identifier range; socket must be
+			       bound or connected */
+#define SO_ATMQOS	__SO_ENCODE(SOL_ATM,2,struct atm_qos)
+			    /* Quality of Service setting */
+#define SO_ATMSAP	__SO_ENCODE(SOL_ATM,3,struct atm_sap)
+			    /* Service Access Point */
+#define SO_ATMPVC	__SO_ENCODE(SOL_ATM,4,struct sockaddr_atmpvc)
+			    /* "PVC" address (also for SVCs); get only */
+#define SO_MULTIPOINT	__SO_ENCODE(SOL_ATM, 5, int)
+			    /* make this vc a p2mp */
+
+
+/*
+ * Note @@@: since the socket layers don't really distinguish the control and
+ * the data plane but generally seems to be data plane-centric, any layer is
+ * about equally wrong for the SAP. If you have a better idea about this,
+ * please speak up ...
+ */
+
+
+/* ATM cell header (for AAL0) */
+
+/* BEGIN_CH */
+#define ATM_HDR_GFC_MASK	0xf0000000
+#define ATM_HDR_GFC_SHIFT	28
+#define ATM_HDR_VPI_MASK	0x0ff00000
+#define ATM_HDR_VPI_SHIFT	20
+#define ATM_HDR_VCI_MASK	0x000ffff0
+#define ATM_HDR_VCI_SHIFT	4
+#define ATM_HDR_PTI_MASK	0x0000000e
+#define ATM_HDR_PTI_SHIFT	1
+#define ATM_HDR_CLP		0x00000001
+/* END_CH */
+
+
+/* PTI codings */
+
+/* BEGIN_PTI */
+#define ATM_PTI_US0	0  /* user data cell, congestion not exp, SDU-type 0 */
+#define ATM_PTI_US1	1  /* user data cell, congestion not exp, SDU-type 1 */
+#define ATM_PTI_UCES0	2  /* user data cell, cong. experienced, SDU-type 0 */
+#define ATM_PTI_UCES1	3  /* user data cell, cong. experienced, SDU-type 1 */
+#define ATM_PTI_SEGF5	4  /* segment OAM F5 flow related cell */
+#define ATM_PTI_E2EF5	5  /* end-to-end OAM F5 flow related cell */
+#define ATM_PTI_RSV_RM	6  /* reserved for traffic control/resource mgmt */
+#define ATM_PTI_RSV	7  /* reserved */
+/* END_PTI */
+
+
+/*
+ * The following items should stay in linux/atm.h, which should be linked to
+ * netatm/atm.h
+ */
+
+/* Traffic description */
+
+#define ATM_NONE	0		/* no traffic */
+#define ATM_UBR		1
+#define ATM_CBR		2
+#define ATM_VBR		3
+#define ATM_ABR		4
+#define ATM_ANYCLASS	5		/* compatible with everything */
+
+#define ATM_MAX_PCR	-1		/* maximum available PCR */
+
+struct atm_trafprm {
+	unsigned char	traffic_class;	/* traffic class (ATM_UBR, ...) */
+	int		max_pcr;	/* maximum PCR in cells per second */
+	int		pcr;		/* desired PCR in cells per second */
+	int		min_pcr;	/* minimum PCR in cells per second */
+	int		max_cdv;	/* maximum CDV in microseconds */
+	int		max_sdu;	/* maximum SDU in bytes */
+        /* extra params for ABR */
+        unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
+        unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 
+        unsigned int 	frtt : 24;	/* Fixed Round Trip Time (24-bit) */
+        unsigned int 	rif  : 4;       /* Rate Increment Factor (4-bit) */
+        unsigned int 	rdf  : 4;       /* Rate Decrease Factor (4-bit) */
+        unsigned int nrm_pres  :1;      /* nrm present bit */
+        unsigned int trm_pres  :1;     	/* rm present bit */
+        unsigned int adtf_pres :1;     	/* adtf present bit */
+        unsigned int cdf_pres  :1;    	/* cdf present bit*/
+        unsigned int nrm       :3;     	/* Max # of Cells for each forward RM cell (3-bit) */
+        unsigned int trm       :3;    	/* Time between forward RM cells (3-bit) */    
+	unsigned int adtf      :10;     /* ACR Decrease Time Factor (10-bit) */
+	unsigned int cdf       :3;      /* Cutoff Decrease Factor (3-bit) */
+        unsigned int spare     :9;      /* spare bits */ 
+};
+
+struct atm_qos {
+	struct atm_trafprm txtp;	/* parameters in TX direction */
+	struct atm_trafprm rxtp __ATM_API_ALIGN;
+					/* parameters in RX direction */
+	unsigned char aal __ATM_API_ALIGN;
+};
+
+/* PVC addressing */
+
+#define ATM_ITF_ANY	-1		/* "magic" PVC address values */
+#define ATM_VPI_ANY	-1
+#define ATM_VCI_ANY	-1
+#define ATM_VPI_UNSPEC	-2
+#define ATM_VCI_UNSPEC	-2
+
+
+struct sockaddr_atmpvc {
+	unsigned short 	sap_family;	/* address family, AF_ATMPVC  */
+	struct {			/* PVC address */
+		short	itf;		/* ATM interface */
+		short	vpi;		/* VPI (only 8 bits at UNI) */
+		int	vci;		/* VCI (only 16 bits at UNI) */
+	} sap_addr __ATM_API_ALIGN;	/* PVC address */
+};
+
+/* SVC addressing */
+
+#define	ATM_ESA_LEN	20		/* ATM End System Address length */
+#define ATM_E164_LEN	12		/* maximum E.164 number length */
+
+#define ATM_AFI_DCC	0x39		/* DCC ATM Format */
+#define ATM_AFI_ICD	0x47		/* ICD ATM Format */
+#define ATM_AFI_E164	0x45		/* E.164 ATM Format */
+#define ATM_AFI_LOCAL	0x49		/* Local ATM Format */ 
+
+#define ATM_AFI_DCC_GROUP	0xBD	/* DCC ATM Group Format */
+#define ATM_AFI_ICD_GROUP	0xC5	/* ICD ATM Group Format */
+#define ATM_AFI_E164_GROUP	0xC3	/* E.164 ATM Group Format */
+#define ATM_AFI_LOCAL_GROUP	0xC7	/* Local ATM Group Format */
+
+#define ATM_LIJ_NONE	0		/* no leaf-initiated join */
+#define ATM_LIJ		1		/* request joining */
+#define ATM_LIJ_RPJ	2		/* set to root-prompted join */
+#define ATM_LIJ_NJ	3		/* set to network join */
+
+
+struct sockaddr_atmsvc {
+    unsigned short 	sas_family;	/* address family, AF_ATMSVC */
+    struct {				/* SVC address */
+        unsigned char	prv[ATM_ESA_LEN];/* private ATM address */
+        char		pub[ATM_E164_LEN+1]; /* public address (E.164) */
+    					/* unused addresses must be bzero'ed */
+	char		lij_type;	/* role in LIJ call; one of ATM_LIJ* */
+	__u32	lij_id;		/* LIJ call identifier */
+    } sas_addr __ATM_API_ALIGN;		/* SVC address */
+};
+
+
+static __inline__ int atmsvc_addr_in_use(struct sockaddr_atmsvc addr)
+{
+	return *addr.sas_addr.prv || *addr.sas_addr.pub;
+}
+
+
+static __inline__ int atmpvc_addr_in_use(struct sockaddr_atmpvc addr)
+{
+	return addr.sap_addr.itf || addr.sap_addr.vpi || addr.sap_addr.vci;
+}
+
+
+/*
+ * Some stuff for linux/sockios.h
+ */
+
+struct atmif_sioc {
+	int number;
+	int length;
+	void *arg;
+};
+
+
+typedef unsigned short atm_backend_t;
+#endif /* _LINUX_ATM_H */
diff --git a/include/linux-private/linux/atmapi.h b/include/linux-private/linux/atmapi.h
new file mode 100644
index 0000000..c9bf5c2
--- /dev/null
+++ b/include/linux-private/linux/atmapi.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* atmapi.h - ATM API user space/kernel compatibility */
+ 
+/* Written 1999,2000 by Werner Almesberger, EPFL ICA */
+ 
+
+#ifndef _LINUX_ATMAPI_H
+#define _LINUX_ATMAPI_H
+
+#if defined(__sparc__) || defined(__ia64__)
+/* such alignment is not required on 32 bit sparcs, but we can't
+   figure that we are on a sparc64 while compiling user-space programs. */
+#define __ATM_API_ALIGN	__attribute__((aligned(8)))
+#else
+#define __ATM_API_ALIGN
+#endif
+
+
+/*
+ * Opaque type for kernel pointers. Note that _ is never accessed. We need
+ * the struct in order hide the array, so that we can make simple assignments
+ * instead of being forced to use memcpy. It also improves error reporting for
+ * code that still assumes that we're passing unsigned longs.
+ *
+ * Convention: NULL pointers are passed as a field of all zeroes.
+ */
+ 
+typedef struct { unsigned char _[8]; } __ATM_API_ALIGN atm_kptr_t;
+
+#endif
diff --git a/include/linux-private/linux/atmioc.h b/include/linux-private/linux/atmioc.h
new file mode 100644
index 0000000..a9030bc
--- /dev/null
+++ b/include/linux-private/linux/atmioc.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* atmioc.h - ranges for ATM-related ioctl numbers */
+ 
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+
+
+/*
+ * See https://icawww1.epfl.ch/linux-atm/magic.html for the complete list of
+ * "magic" ioctl numbers.
+ */
+
+
+#ifndef _LINUX_ATMIOC_H
+#define _LINUX_ATMIOC_H
+
+#include <asm/ioctl.h>
+		/* everybody including atmioc.h will also need _IO{,R,W,WR} */
+
+#define ATMIOC_PHYCOM	  0x00 /* PHY device common ioctls, globally unique */
+#define ATMIOC_PHYCOM_END 0x0f
+#define ATMIOC_PHYTYP	  0x10 /* PHY dev type ioctls, unique per PHY type */
+#define ATMIOC_PHYTYP_END 0x2f
+#define ATMIOC_PHYPRV	  0x30 /* PHY dev private ioctls, unique per driver */
+#define ATMIOC_PHYPRV_END 0x4f
+#define ATMIOC_SARCOM	  0x50 /* SAR device common ioctls, globally unique */
+#define ATMIOC_SARCOM_END 0x50
+#define ATMIOC_SARPRV	  0x60 /* SAR dev private ioctls, unique per driver */
+#define ATMIOC_SARPRV_END 0x7f
+#define ATMIOC_ITF	  0x80 /* Interface ioctls, globally unique */
+#define ATMIOC_ITF_END	  0x8f
+#define ATMIOC_BACKEND	  0x90 /* ATM generic backend ioctls, u. per backend */
+#define ATMIOC_BACKEND_END 0xaf
+/* 0xb0-0xbf: Reserved for future use */
+#define ATMIOC_AREQUIPA	  0xc0 /* Application requested IP over ATM, glob. u. */
+#define ATMIOC_LANE	  0xd0 /* LAN Emulation, globally unique */
+#define ATMIOC_MPOA       0xd8 /* MPOA, globally unique */
+#define	ATMIOC_CLIP	  0xe0 /* Classical IP over ATM control, globally u. */
+#define	ATMIOC_CLIP_END	  0xef
+#define	ATMIOC_SPECIAL	  0xf0 /* Special-purpose controls, globally unique */
+#define	ATMIOC_SPECIAL_END 0xff
+
+#endif
diff --git a/include/linux-private/linux/atmsap.h b/include/linux-private/linux/atmsap.h
new file mode 100644
index 0000000..fc05248
--- /dev/null
+++ b/include/linux-private/linux/atmsap.h
@@ -0,0 +1,163 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* atmsap.h - ATM Service Access Point addressing definitions */
+
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
+
+
+#ifndef _LINUX_ATMSAP_H
+#define _LINUX_ATMSAP_H
+
+#include <linux/atmapi.h>
+
+/*
+ * BEGIN_xx and END_xx markers are used for automatic generation of
+ * documentation. Do not change them.
+ */
+
+
+/*
+ * Layer 2 protocol identifiers
+ */
+
+/* BEGIN_L2 */
+#define ATM_L2_NONE	0	/* L2 not specified */
+#define ATM_L2_ISO1745  0x01	/* Basic mode ISO 1745 */
+#define ATM_L2_Q291	0x02	/* ITU-T Q.291 (Rec. I.441) */
+#define ATM_L2_X25_LL	0x06	/* ITU-T X.25, link layer */
+#define ATM_L2_X25_ML	0x07	/* ITU-T X.25, multilink */
+#define ATM_L2_LAPB	0x08	/* Extended LAPB, half-duplex (Rec. T.71) */
+#define ATM_L2_HDLC_ARM	0x09	/* HDLC ARM (ISO/IEC 4335) */
+#define ATM_L2_HDLC_NRM	0x0a	/* HDLC NRM (ISO/IEC 4335) */
+#define ATM_L2_HDLC_ABM	0x0b	/* HDLC ABM (ISO/IEC 4335) */
+#define ATM_L2_ISO8802	0x0c	/* LAN LLC (ISO/IEC 8802/2) */
+#define ATM_L2_X75	0x0d	/* ITU-T X.75, SLP */
+#define ATM_L2_Q922	0x0e	/* ITU-T Q.922 */
+#define ATM_L2_USER	0x10	/* user-specified */
+#define ATM_L2_ISO7776	0x11	/* ISO 7776 DTE-DTE */
+/* END_L2 */
+
+
+/*
+ * Layer 3 protocol identifiers
+ */
+
+/* BEGIN_L3 */
+#define ATM_L3_NONE	0	/* L3 not specified */
+#define ATM_L3_X25	0x06	/* ITU-T X.25, packet layer */
+#define ATM_L3_ISO8208	0x07	/* ISO/IEC 8208 */
+#define ATM_L3_X223	0x08	/* ITU-T X.223 | ISO/IEC 8878 */
+#define ATM_L3_ISO8473	0x09	/* ITU-T X.233 | ISO/IEC 8473 */
+#define ATM_L3_T70	0x0a	/* ITU-T T.70 minimum network layer */
+#define ATM_L3_TR9577	0x0b	/* ISO/IEC TR 9577 */
+#define ATM_L3_H310	0x0c	/* ITU-T Recommendation H.310 */
+#define ATM_L3_H321	0x0d	/* ITU-T Recommendation H.321 */
+#define ATM_L3_USER	0x10	/* user-specified */
+/* END_L3 */
+
+
+/*
+ * High layer identifiers
+ */
+
+/* BEGIN_HL */
+#define ATM_HL_NONE	0	/* HL not specified */
+#define ATM_HL_ISO	0x01	/* ISO */
+#define ATM_HL_USER	0x02	/* user-specific */
+#define ATM_HL_HLP	0x03	/* high layer profile - UNI 3.0 only */
+#define ATM_HL_VENDOR	0x04	/* vendor-specific application identifier */
+/* END_HL */
+
+
+/*
+ * ITU-T coded mode of operation
+ */
+
+/* BEGIN_IMD */
+#define ATM_IMD_NONE	 0	/* mode not specified */
+#define ATM_IMD_NORMAL	 1	/* normal mode of operation */
+#define ATM_IMD_EXTENDED 2	/* extended mode of operation */
+/* END_IMD */
+
+/*
+ * H.310 code points
+ */
+
+#define ATM_TT_NONE	0	/* terminal type not specified */
+#define ATM_TT_RX	1	/* receive only */
+#define ATM_TT_TX	2	/* send only */
+#define ATM_TT_RXTX	3	/* receive and send */
+
+#define ATM_MC_NONE	0	/* no multiplexing */
+#define ATM_MC_TS	1	/* transport stream (TS) */
+#define ATM_MC_TS_FEC	2	/* transport stream with forward error corr. */
+#define ATM_MC_PS	3	/* program stream (PS) */
+#define ATM_MC_PS_FEC	4	/* program stream with forward error corr. */
+#define ATM_MC_H221	5	/* ITU-T Rec. H.221 */
+
+/*
+ * SAP structures
+ */
+
+#define ATM_MAX_HLI	8	/* maximum high-layer information length */
+
+
+struct atm_blli {
+    unsigned char l2_proto;	/* layer 2 protocol */
+    union {
+	struct {
+	    unsigned char mode;	/* mode of operation (ATM_IMD_xxx), 0 if */
+				/* absent */
+	    unsigned char window; /* window size (k), 1-127 (0 to omit) */
+	} itu;			/* ITU-T encoding */
+	unsigned char user;	/* user-specified l2 information */
+    } l2;
+    unsigned char l3_proto;	/* layer 3 protocol */
+    union {
+	struct {
+	    unsigned char mode;	/* mode of operation (ATM_IMD_xxx), 0 if */
+				/* absent */
+	    unsigned char def_size; /* default packet size (log2), 4-12 (0 to */
+				    /* omit) */
+	    unsigned char window;/* packet window size, 1-127 (0 to omit) */
+	} itu;			/* ITU-T encoding */
+	unsigned char user;	/* user specified l3 information */
+	struct {		      /* if l3_proto = ATM_L3_H310 */
+	    unsigned char term_type;  /* terminal type */
+	    unsigned char fw_mpx_cap; /* forward multiplexing capability */
+				      /* only if term_type != ATM_TT_NONE */
+	    unsigned char bw_mpx_cap; /* backward multiplexing capability */
+				      /* only if term_type != ATM_TT_NONE */
+	} h310;
+	struct {		  /* if l3_proto = ATM_L3_TR9577 */
+	    unsigned char ipi;	  /* initial protocol id */
+	    unsigned char snap[5];/* IEEE 802.1 SNAP identifier */
+				  /* (only if ipi == NLPID_IEEE802_1_SNAP) */
+	} tr9577;
+    } l3;
+} __ATM_API_ALIGN;
+
+
+struct atm_bhli {
+    unsigned char hl_type;	/* high layer information type */
+    unsigned char hl_length;	/* length (only if hl_type == ATM_HL_USER || */
+				/* hl_type == ATM_HL_ISO) */
+    unsigned char hl_info[ATM_MAX_HLI];/* high layer information */
+};
+
+
+#define ATM_MAX_BLLI	3		/* maximum number of BLLI elements */
+
+
+struct atm_sap {
+	struct atm_bhli bhli;		/* local SAP, high-layer information */
+	struct atm_blli blli[ATM_MAX_BLLI] __ATM_API_ALIGN;
+					/* local SAP, low-layer info */
+};
+
+
+static __inline__ int blli_in_use(struct atm_blli blli)
+{
+	return blli.l2_proto || blli.l3_proto;
+}
+
+#endif
diff --git a/include/linux-private/linux/byteorder/little_endian.h b/include/linux-private/linux/byteorder/little_endian.h
new file mode 100644
index 0000000..ba6c199
--- /dev/null
+++ b/include/linux-private/linux/byteorder/little_endian.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H
+#define _LINUX_BYTEORDER_LITTLE_ENDIAN_H
+
+#ifndef __LITTLE_ENDIAN
+#define __LITTLE_ENDIAN 1234
+#endif
+#ifndef __LITTLE_ENDIAN_BITFIELD
+#define __LITTLE_ENDIAN_BITFIELD
+#endif
+
+#include <linux/stddef.h>
+#include <linux/types.h>
+#include <linux/swab.h>
+
+#define __constant_htonl(x) ((__be32)___constant_swab32((x)))
+#define __constant_ntohl(x) ___constant_swab32((__be32)(x))
+#define __constant_htons(x) ((__be16)___constant_swab16((x)))
+#define __constant_ntohs(x) ___constant_swab16((__be16)(x))
+#define __constant_cpu_to_le64(x) ((__le64)(__u64)(x))
+#define __constant_le64_to_cpu(x) ((__u64)(__le64)(x))
+#define __constant_cpu_to_le32(x) ((__le32)(__u32)(x))
+#define __constant_le32_to_cpu(x) ((__u32)(__le32)(x))
+#define __constant_cpu_to_le16(x) ((__le16)(__u16)(x))
+#define __constant_le16_to_cpu(x) ((__u16)(__le16)(x))
+#define __constant_cpu_to_be64(x) ((__be64)___constant_swab64((x)))
+#define __constant_be64_to_cpu(x) ___constant_swab64((__u64)(__be64)(x))
+#define __constant_cpu_to_be32(x) ((__be32)___constant_swab32((x)))
+#define __constant_be32_to_cpu(x) ___constant_swab32((__u32)(__be32)(x))
+#define __constant_cpu_to_be16(x) ((__be16)___constant_swab16((x)))
+#define __constant_be16_to_cpu(x) ___constant_swab16((__u16)(__be16)(x))
+#define __cpu_to_le64(x) ((__le64)(__u64)(x))
+#define __le64_to_cpu(x) ((__u64)(__le64)(x))
+#define __cpu_to_le32(x) ((__le32)(__u32)(x))
+#define __le32_to_cpu(x) ((__u32)(__le32)(x))
+#define __cpu_to_le16(x) ((__le16)(__u16)(x))
+#define __le16_to_cpu(x) ((__u16)(__le16)(x))
+#define __cpu_to_be64(x) ((__be64)__swab64((x)))
+#define __be64_to_cpu(x) __swab64((__u64)(__be64)(x))
+#define __cpu_to_be32(x) ((__be32)__swab32((x)))
+#define __be32_to_cpu(x) __swab32((__u32)(__be32)(x))
+#define __cpu_to_be16(x) ((__be16)__swab16((x)))
+#define __be16_to_cpu(x) __swab16((__u16)(__be16)(x))
+
+static __always_inline __le64 __cpu_to_le64p(const __u64 *p)
+{
+	return (__le64)*p;
+}
+static __always_inline __u64 __le64_to_cpup(const __le64 *p)
+{
+	return (__u64)*p;
+}
+static __always_inline __le32 __cpu_to_le32p(const __u32 *p)
+{
+	return (__le32)*p;
+}
+static __always_inline __u32 __le32_to_cpup(const __le32 *p)
+{
+	return (__u32)*p;
+}
+static __always_inline __le16 __cpu_to_le16p(const __u16 *p)
+{
+	return (__le16)*p;
+}
+static __always_inline __u16 __le16_to_cpup(const __le16 *p)
+{
+	return (__u16)*p;
+}
+static __always_inline __be64 __cpu_to_be64p(const __u64 *p)
+{
+	return (__be64)__swab64p(p);
+}
+static __always_inline __u64 __be64_to_cpup(const __be64 *p)
+{
+	return __swab64p((__u64 *)p);
+}
+static __always_inline __be32 __cpu_to_be32p(const __u32 *p)
+{
+	return (__be32)__swab32p(p);
+}
+static __always_inline __u32 __be32_to_cpup(const __be32 *p)
+{
+	return __swab32p((__u32 *)p);
+}
+static __always_inline __be16 __cpu_to_be16p(const __u16 *p)
+{
+	return (__be16)__swab16p(p);
+}
+static __always_inline __u16 __be16_to_cpup(const __be16 *p)
+{
+	return __swab16p((__u16 *)p);
+}
+#define __cpu_to_le64s(x) do { (void)(x); } while (0)
+#define __le64_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le32s(x) do { (void)(x); } while (0)
+#define __le32_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_le16s(x) do { (void)(x); } while (0)
+#define __le16_to_cpus(x) do { (void)(x); } while (0)
+#define __cpu_to_be64s(x) __swab64s((x))
+#define __be64_to_cpus(x) __swab64s((x))
+#define __cpu_to_be32s(x) __swab32s((x))
+#define __be32_to_cpus(x) __swab32s((x))
+#define __cpu_to_be16s(x) __swab16s((x))
+#define __be16_to_cpus(x) __swab16s((x))
+
+
+#endif /* _LINUX_BYTEORDER_LITTLE_ENDIAN_H */
diff --git a/include/linux-private/linux/can/netlink.h b/include/linux-private/linux/can/netlink.h
index f0c5e58..8ec98c2 100644
--- a/include/linux-private/linux/can/netlink.h
+++ b/include/linux-private/linux/can/netlink.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
 /*
  * linux/can/netlink.h
  *
@@ -40,15 +40,15 @@
 };
 
 /*
- * CAN harware-dependent bit-timing constant
+ * CAN hardware-dependent bit-timing constant
  *
  * Used for calculating and checking bit-timing parameters
  */
 struct can_bittiming_const {
 	char name[16];		/* Name of the CAN controller hardware */
-	__u32 tseg1_min;	/* Time segement 1 = prop_seg + phase_seg1 */
+	__u32 tseg1_min;	/* Time segment 1 = prop_seg + phase_seg1 */
 	__u32 tseg1_max;
-	__u32 tseg2_min;	/* Time segement 2 = phase_seg2 */
+	__u32 tseg2_min;	/* Time segment 2 = phase_seg2 */
 	__u32 tseg2_max;
 	__u32 sjw_max;		/* Synchronisation jump width */
 	__u32 brp_min;		/* Bit-rate prescaler */
@@ -100,6 +100,9 @@
 #define CAN_CTRLMODE_FD			0x20	/* CAN FD mode */
 #define CAN_CTRLMODE_PRESUME_ACK	0x40	/* Ignore missing CAN ACKs */
 #define CAN_CTRLMODE_FD_NON_ISO		0x80	/* CAN FD in non-ISO mode */
+#define CAN_CTRLMODE_CC_LEN8_DLC	0x100	/* Classic CAN DLC option */
+#define CAN_CTRLMODE_TDC_AUTO		0x200	/* CAN transiver automatically calculates TDCV */
+#define CAN_CTRLMODE_TDC_MANUAL		0x400	/* TDCV is manually set up by user */
 
 /*
  * CAN device statistics
@@ -133,10 +136,48 @@
 	IFLA_CAN_BITRATE_CONST,
 	IFLA_CAN_DATA_BITRATE_CONST,
 	IFLA_CAN_BITRATE_MAX,
-	__IFLA_CAN_MAX
+	IFLA_CAN_TDC,
+	IFLA_CAN_CTRLMODE_EXT,
+
+	/* add new constants above here */
+	__IFLA_CAN_MAX,
+	IFLA_CAN_MAX = __IFLA_CAN_MAX - 1
 };
 
-#define IFLA_CAN_MAX	(__IFLA_CAN_MAX - 1)
+/*
+ * CAN FD Transmitter Delay Compensation (TDC)
+ *
+ * Please refer to struct can_tdc_const and can_tdc in
+ * include/linux/can/bittiming.h for further details.
+ */
+enum {
+	IFLA_CAN_TDC_UNSPEC,
+	IFLA_CAN_TDC_TDCV_MIN,	/* u32 */
+	IFLA_CAN_TDC_TDCV_MAX,	/* u32 */
+	IFLA_CAN_TDC_TDCO_MIN,	/* u32 */
+	IFLA_CAN_TDC_TDCO_MAX,	/* u32 */
+	IFLA_CAN_TDC_TDCF_MIN,	/* u32 */
+	IFLA_CAN_TDC_TDCF_MAX,	/* u32 */
+	IFLA_CAN_TDC_TDCV,	/* u32 */
+	IFLA_CAN_TDC_TDCO,	/* u32 */
+	IFLA_CAN_TDC_TDCF,	/* u32 */
+
+	/* add new constants above here */
+	__IFLA_CAN_TDC,
+	IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1
+};
+
+/*
+ * IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters
+ */
+enum {
+	IFLA_CAN_CTRLMODE_UNSPEC,
+	IFLA_CAN_CTRLMODE_SUPPORTED,	/* u32 */
+
+	/* add new constants above here */
+	__IFLA_CAN_CTRLMODE,
+	IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1
+};
 
 /* u16 termination range: 1..65535 Ohms */
 #define CAN_TERMINATION_DISABLED 0
diff --git a/include/linux-private/linux/const.h b/include/linux-private/linux/const.h
new file mode 100644
index 0000000..1eb84b5
--- /dev/null
+++ b/include/linux-private/linux/const.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/* const.h: Macros for dealing with constants.  */
+
+#ifndef _LINUX_CONST_H
+#define _LINUX_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code.  Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally.  We
+ * use the following macros to deal with this.
+ *
+ * Similarly, _AT() will cast an expression with a type in C, but
+ * leave it unchanged in asm.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y)	X
+#define _AT(T,X)	X
+#else
+#define __AC(X,Y)	(X##Y)
+#define _AC(X,Y)	__AC(X,Y)
+#define _AT(T,X)	((T)(X))
+#endif
+
+#define _UL(x)		(_AC(x, UL))
+#define _ULL(x)		(_AC(x, ULL))
+
+#define _BITUL(x)	(_UL(1) << (x))
+#define _BITULL(x)	(_ULL(1) << (x))
+
+#define __ALIGN_KERNEL(x, a)		__ALIGN_KERNEL_MASK(x, (__typeof__(x))(a) - 1)
+#define __ALIGN_KERNEL_MASK(x, mask)	(((x) + (mask)) & ~(mask))
+
+#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+
+#endif /* _LINUX_CONST_H */
diff --git a/include/linux-private/linux/errno.h b/include/linux-private/linux/errno.h
new file mode 100644
index 0000000..70f2bd3
--- /dev/null
+++ b/include/linux-private/linux/errno.h
@@ -0,0 +1 @@
+#include <asm/errno.h>
diff --git a/include/linux-private/linux/ethtool.h b/include/linux-private/linux/ethtool.h
new file mode 100644
index 0000000..1d0731b
--- /dev/null
+++ b/include/linux-private/linux/ethtool.h
@@ -0,0 +1,2206 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * ethtool.h: Defines for Linux ethtool.
+ *
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
+ * Copyright 2001 Jeff Garzik <jgarzik@pobox.com>
+ * Portions Copyright 2001 Sun Microsystems (thockin@sun.com)
+ * Portions Copyright 2002 Intel (eli.kupermann@intel.com,
+ *                                christopher.leech@intel.com,
+ *                                scott.feldman@intel.com)
+ * Portions Copyright (C) Sun Microsystems 2008
+ */
+
+#ifndef _LINUX_ETHTOOL_H
+#define _LINUX_ETHTOOL_H
+
+#include <linux/const.h>
+#include <linux/types.h>
+#include <linux/if_ether.h>
+
+#include <limits.h> /* for INT_MAX */
+
+/* All structures exposed to userland should be defined such that they
+ * have the same layout for 32-bit and 64-bit userland.
+ */
+
+/* Note on reserved space.
+ * Reserved fields must not be accessed directly by user space because
+ * they may be replaced by a different field in the future. They must
+ * be initialized to zero before making the request, e.g. via memset
+ * of the entire structure or implicitly by not being set in a structure
+ * initializer.
+ */
+
+/**
+ * struct ethtool_cmd - DEPRECATED, link control and status
+ * This structure is DEPRECATED, please use struct ethtool_link_settings.
+ * @cmd: Command number = %ETHTOOL_GSET or %ETHTOOL_SSET
+ * @supported: Bitmask of %SUPPORTED_* flags for the link modes,
+ *	physical connectors and other link features for which the
+ *	interface supports autonegotiation or auto-detection.
+ *	Read-only.
+ * @advertising: Bitmask of %ADVERTISED_* flags for the link modes,
+ *	physical connectors and other link features that are
+ *	advertised through autonegotiation or enabled for
+ *	auto-detection.
+ * @speed: Low bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN
+ * @duplex: Duplex mode; one of %DUPLEX_*
+ * @port: Physical connector type; one of %PORT_*
+ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not
+ *	applicable.  For clause 45 PHYs this is the PRTAD.
+ * @transceiver: Historically used to distinguish different possible
+ *	PHY types, but not in a consistent way.  Deprecated.
+ * @autoneg: Enable/disable autonegotiation and auto-detection;
+ *	either %AUTONEG_DISABLE or %AUTONEG_ENABLE
+ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO
+ *	protocols supported by the interface; 0 if unknown.
+ *	Read-only.
+ * @maxtxpkt: Historically used to report TX IRQ coalescing; now
+ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
+ * @maxrxpkt: Historically used to report RX IRQ coalescing; now
+ *	obsoleted by &struct ethtool_coalesce.  Read-only; deprecated.
+ * @speed_hi: High bits of the speed, 1Mb units, 0 to INT_MAX or SPEED_UNKNOWN
+ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of
+ *	%ETH_TP_MDI_*.  If the status is unknown or not applicable, the
+ *	value will be %ETH_TP_MDI_INVALID.  Read-only.
+ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of
+ *	%ETH_TP_MDI_*.  If MDI(-X) control is not implemented, reads
+ *	yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected.
+ *	When written successfully, the link should be renegotiated if
+ *	necessary.
+ * @lp_advertising: Bitmask of %ADVERTISED_* flags for the link modes
+ *	and other link features that the link partner advertised
+ *	through autonegotiation; 0 if unknown or not applicable.
+ *	Read-only.
+ * @reserved: Reserved for future use; see the note on reserved space.
+ *
+ * The link speed in Mbps is split between @speed and @speed_hi.  Use
+ * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to
+ * access it.
+ *
+ * If autonegotiation is disabled, the speed and @duplex represent the
+ * fixed link mode and are writable if the driver supports multiple
+ * link modes.  If it is enabled then they are read-only; if the link
+ * is up they represent the negotiated link mode; if the link is down,
+ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and
+ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
+ *
+ * Some hardware interfaces may have multiple PHYs and/or physical
+ * connectors fitted or do not allow the driver to detect which are
+ * fitted.  For these interfaces @port and/or @phy_address may be
+ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE.
+ * Otherwise, attempts to write different values may be ignored or
+ * rejected.
+ *
+ * Users should assume that all fields not marked read-only are
+ * writable and subject to validation by the driver.  They should use
+ * %ETHTOOL_GSET to get the current values before making specific
+ * changes and then applying them with %ETHTOOL_SSET.
+ *
+ * Deprecated fields should be ignored by both users and drivers.
+ */
+struct ethtool_cmd {
+	__u32	cmd;
+	__u32	supported;
+	__u32	advertising;
+	__u16	speed;
+	__u8	duplex;
+	__u8	port;
+	__u8	phy_address;
+	__u8	transceiver;
+	__u8	autoneg;
+	__u8	mdio_support;
+	__u32	maxtxpkt;
+	__u32	maxrxpkt;
+	__u16	speed_hi;
+	__u8	eth_tp_mdix;
+	__u8	eth_tp_mdix_ctrl;
+	__u32	lp_advertising;
+	__u32	reserved[2];
+};
+
+static __inline__ void ethtool_cmd_speed_set(struct ethtool_cmd *ep,
+					 __u32 speed)
+{
+	ep->speed = (__u16)(speed & 0xFFFF);
+	ep->speed_hi = (__u16)(speed >> 16);
+}
+
+static __inline__ __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep)
+{
+	return (ep->speed_hi << 16) | ep->speed;
+}
+
+/* Device supports clause 22 register access to PHY or peripherals
+ * using the interface defined in <linux/mii.h>.  This should not be
+ * set if there are known to be no such peripherals present or if
+ * the driver only emulates clause 22 registers for compatibility.
+ */
+#define ETH_MDIO_SUPPORTS_C22	1
+
+/* Device supports clause 45 register access to PHY or peripherals
+ * using the interface defined in <linux/mii.h> and <linux/mdio.h>.
+ * This should not be set if there are known to be no such peripherals
+ * present.
+ */
+#define ETH_MDIO_SUPPORTS_C45	2
+
+#define ETHTOOL_FWVERS_LEN	32
+#define ETHTOOL_BUSINFO_LEN	32
+#define ETHTOOL_EROMVERS_LEN	32
+
+/**
+ * struct ethtool_drvinfo - general driver and device information
+ * @cmd: Command number = %ETHTOOL_GDRVINFO
+ * @driver: Driver short name.  This should normally match the name
+ *	in its bus driver structure (e.g. pci_driver::name).  Must
+ *	not be an empty string.
+ * @version: Driver version string; may be an empty string
+ * @fw_version: Firmware version string; driver defined; may be an
+ *	empty string
+ * @erom_version: Expansion ROM version string; driver defined; may be
+ *	an empty string
+ * @bus_info: Device bus address.  This should match the dev_name()
+ *	string for the underlying bus device, if there is one.  May be
+ *	an empty string.
+ * @reserved2: Reserved for future use; see the note on reserved space.
+ * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and
+ *	%ETHTOOL_SPFLAGS commands; also the number of strings in the
+ *	%ETH_SS_PRIV_FLAGS set
+ * @n_stats: Number of u64 statistics returned by the %ETHTOOL_GSTATS
+ *	command; also the number of strings in the %ETH_SS_STATS set
+ * @testinfo_len: Number of results returned by the %ETHTOOL_TEST
+ *	command; also the number of strings in the %ETH_SS_TEST set
+ * @eedump_len: Size of EEPROM accessible through the %ETHTOOL_GEEPROM
+ *	and %ETHTOOL_SEEPROM commands, in bytes
+ * @regdump_len: Size of register dump returned by the %ETHTOOL_GREGS
+ *	command, in bytes
+ *
+ * Users can use the %ETHTOOL_GSSET_INFO command to get the number of
+ * strings in any string set (from Linux 2.6.34).
+ */
+struct ethtool_drvinfo {
+	__u32	cmd;
+	char	driver[32];
+	char	version[32];
+	char	fw_version[ETHTOOL_FWVERS_LEN];
+	char	bus_info[ETHTOOL_BUSINFO_LEN];
+	char	erom_version[ETHTOOL_EROMVERS_LEN];
+	char	reserved2[12];
+	__u32	n_priv_flags;
+	__u32	n_stats;
+	__u32	testinfo_len;
+	__u32	eedump_len;
+	__u32	regdump_len;
+};
+
+#define SOPASS_MAX	6
+
+/**
+ * struct ethtool_wolinfo - Wake-On-Lan configuration
+ * @cmd: Command number = %ETHTOOL_GWOL or %ETHTOOL_SWOL
+ * @supported: Bitmask of %WAKE_* flags for supported Wake-On-Lan modes.
+ *	Read-only.
+ * @wolopts: Bitmask of %WAKE_* flags for enabled Wake-On-Lan modes.
+ * @sopass: SecureOn(tm) password; meaningful only if %WAKE_MAGICSECURE
+ *	is set in @wolopts.
+ */
+struct ethtool_wolinfo {
+	__u32	cmd;
+	__u32	supported;
+	__u32	wolopts;
+	__u8	sopass[SOPASS_MAX];
+};
+
+/* for passing single values */
+struct ethtool_value {
+	__u32	cmd;
+	__u32	data;
+};
+
+#define PFC_STORM_PREVENTION_AUTO	0xffff
+#define PFC_STORM_PREVENTION_DISABLE	0
+
+enum tunable_id {
+	ETHTOOL_ID_UNSPEC,
+	ETHTOOL_RX_COPYBREAK,
+	ETHTOOL_TX_COPYBREAK,
+	ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */
+	ETHTOOL_TX_COPYBREAK_BUF_SIZE,
+	/*
+	 * Add your fresh new tunable attribute above and remember to update
+	 * tunable_strings[] in net/ethtool/common.c
+	 */
+	__ETHTOOL_TUNABLE_COUNT,
+};
+
+enum tunable_type_id {
+	ETHTOOL_TUNABLE_UNSPEC,
+	ETHTOOL_TUNABLE_U8,
+	ETHTOOL_TUNABLE_U16,
+	ETHTOOL_TUNABLE_U32,
+	ETHTOOL_TUNABLE_U64,
+	ETHTOOL_TUNABLE_STRING,
+	ETHTOOL_TUNABLE_S8,
+	ETHTOOL_TUNABLE_S16,
+	ETHTOOL_TUNABLE_S32,
+	ETHTOOL_TUNABLE_S64,
+};
+
+struct ethtool_tunable {
+	__u32	cmd;
+	__u32	id;
+	__u32	type_id;
+	__u32	len;
+	void	*data[];
+};
+
+#define DOWNSHIFT_DEV_DEFAULT_COUNT	0xff
+#define DOWNSHIFT_DEV_DISABLE		0
+
+/* Time in msecs after which link is reported as down
+ * 0 = lowest time supported by the PHY
+ * 0xff = off, link down detection according to standard
+ */
+#define ETHTOOL_PHY_FAST_LINK_DOWN_ON	0
+#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF	0xff
+
+/* Energy Detect Power Down (EDPD) is a feature supported by some PHYs, where
+ * the PHY's RX & TX blocks are put into a low-power mode when there is no
+ * link detected (typically cable is un-plugged). For RX, only a minimal
+ * link-detection is available, and for TX the PHY wakes up to send link pulses
+ * to avoid any lock-ups in case the peer PHY may also be running in EDPD mode.
+ *
+ * Some PHYs may support configuration of the wake-up interval for TX pulses,
+ * and some PHYs may support only disabling TX pulses entirely. For the latter
+ * a special value is required (ETHTOOL_PHY_EDPD_NO_TX) so that this can be
+ * configured from userspace (should the user want it).
+ *
+ * The interval units for TX wake-up are in milliseconds, since this should
+ * cover a reasonable range of intervals:
+ *  - from 1 millisecond, which does not sound like much of a power-saver
+ *  - to ~65 seconds which is quite a lot to wait for a link to come up when
+ *    plugging a cable
+ */
+#define ETHTOOL_PHY_EDPD_DFLT_TX_MSECS		0xffff
+#define ETHTOOL_PHY_EDPD_NO_TX			0xfffe
+#define ETHTOOL_PHY_EDPD_DISABLE		0
+
+enum phy_tunable_id {
+	ETHTOOL_PHY_ID_UNSPEC,
+	ETHTOOL_PHY_DOWNSHIFT,
+	ETHTOOL_PHY_FAST_LINK_DOWN,
+	ETHTOOL_PHY_EDPD,
+	/*
+	 * Add your fresh new phy tunable attribute above and remember to update
+	 * phy_tunable_strings[] in net/ethtool/common.c
+	 */
+	__ETHTOOL_PHY_TUNABLE_COUNT,
+};
+
+/**
+ * struct ethtool_regs - hardware register dump
+ * @cmd: Command number = %ETHTOOL_GREGS
+ * @version: Dump format version.  This is driver-specific and may
+ *	distinguish different chips/revisions.  Drivers must use new
+ *	version numbers whenever the dump format changes in an
+ *	incompatible way.
+ * @len: On entry, the real length of @data.  On return, the number of
+ *	bytes used.
+ * @data: Buffer for the register dump
+ *
+ * Users should use %ETHTOOL_GDRVINFO to find the maximum length of
+ * a register dump for the interface.  They must allocate the buffer
+ * immediately following this structure.
+ */
+struct ethtool_regs {
+	__u32	cmd;
+	__u32	version;
+	__u32	len;
+	__u8	data[];
+};
+
+/**
+ * struct ethtool_eeprom - EEPROM dump
+ * @cmd: Command number = %ETHTOOL_GEEPROM, %ETHTOOL_GMODULEEEPROM or
+ *	%ETHTOOL_SEEPROM
+ * @magic: A 'magic cookie' value to guard against accidental changes.
+ *	The value passed in to %ETHTOOL_SEEPROM must match the value
+ *	returned by %ETHTOOL_GEEPROM for the same device.  This is
+ *	unused when @cmd is %ETHTOOL_GMODULEEEPROM.
+ * @offset: Offset within the EEPROM to begin reading/writing, in bytes
+ * @len: On entry, number of bytes to read/write.  On successful
+ *	return, number of bytes actually read/written.  In case of
+ *	error, this may indicate at what point the error occurred.
+ * @data: Buffer to read/write from
+ *
+ * Users may use %ETHTOOL_GDRVINFO or %ETHTOOL_GMODULEINFO to find
+ * the length of an on-board or module EEPROM, respectively.  They
+ * must allocate the buffer immediately following this structure.
+ */
+struct ethtool_eeprom {
+	__u32	cmd;
+	__u32	magic;
+	__u32	offset;
+	__u32	len;
+	__u8	data[];
+};
+
+/**
+ * struct ethtool_eee - Energy Efficient Ethernet information
+ * @cmd: ETHTOOL_{G,S}EEE
+ * @supported: Mask of %SUPPORTED_* flags for the speed/duplex combinations
+ *	for which there is EEE support.
+ * @advertised: Mask of %ADVERTISED_* flags for the speed/duplex combinations
+ *	advertised as eee capable.
+ * @lp_advertised: Mask of %ADVERTISED_* flags for the speed/duplex
+ *	combinations advertised by the link partner as eee capable.
+ * @eee_active: Result of the eee auto negotiation.
+ * @eee_enabled: EEE configured mode (enabled/disabled).
+ * @tx_lpi_enabled: Whether the interface should assert its tx lpi, given
+ *	that eee was negotiated.
+ * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting
+ *	its tx lpi (after reaching 'idle' state). Effective only when eee
+ *	was negotiated and tx_lpi_enabled was set.
+ * @reserved: Reserved for future use; see the note on reserved space.
+ */
+struct ethtool_eee {
+	__u32	cmd;
+	__u32	supported;
+	__u32	advertised;
+	__u32	lp_advertised;
+	__u32	eee_active;
+	__u32	eee_enabled;
+	__u32	tx_lpi_enabled;
+	__u32	tx_lpi_timer;
+	__u32	reserved[2];
+};
+
+/**
+ * struct ethtool_modinfo - plugin module eeprom information
+ * @cmd: %ETHTOOL_GMODULEINFO
+ * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx
+ * @eeprom_len: Length of the eeprom
+ * @reserved: Reserved for future use; see the note on reserved space.
+ *
+ * This structure is used to return the information to
+ * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM.
+ * The type code indicates the eeprom data format
+ */
+struct ethtool_modinfo {
+	__u32   cmd;
+	__u32   type;
+	__u32   eeprom_len;
+	__u32   reserved[8];
+};
+
+/**
+ * struct ethtool_coalesce - coalescing parameters for IRQs and stats updates
+ * @cmd: ETHTOOL_{G,S}COALESCE
+ * @rx_coalesce_usecs: How many usecs to delay an RX interrupt after
+ *	a packet arrives.
+ * @rx_max_coalesced_frames: Maximum number of packets to receive
+ *	before an RX interrupt.
+ * @rx_coalesce_usecs_irq: Same as @rx_coalesce_usecs, except that
+ *	this value applies while an IRQ is being serviced by the host.
+ * @rx_max_coalesced_frames_irq: Same as @rx_max_coalesced_frames,
+ *	except that this value applies while an IRQ is being serviced
+ *	by the host.
+ * @tx_coalesce_usecs: How many usecs to delay a TX interrupt after
+ *	a packet is sent.
+ * @tx_max_coalesced_frames: Maximum number of packets to be sent
+ *	before a TX interrupt.
+ * @tx_coalesce_usecs_irq: Same as @tx_coalesce_usecs, except that
+ *	this value applies while an IRQ is being serviced by the host.
+ * @tx_max_coalesced_frames_irq: Same as @tx_max_coalesced_frames,
+ *	except that this value applies while an IRQ is being serviced
+ *	by the host.
+ * @stats_block_coalesce_usecs: How many usecs to delay in-memory
+ *	statistics block updates.  Some drivers do not have an
+ *	in-memory statistic block, and in such cases this value is
+ *	ignored.  This value must not be zero.
+ * @use_adaptive_rx_coalesce: Enable adaptive RX coalescing.
+ * @use_adaptive_tx_coalesce: Enable adaptive TX coalescing.
+ * @pkt_rate_low: Threshold for low packet rate (packets per second).
+ * @rx_coalesce_usecs_low: How many usecs to delay an RX interrupt after
+ *	a packet arrives, when the packet rate is below @pkt_rate_low.
+ * @rx_max_coalesced_frames_low: Maximum number of packets to be received
+ *	before an RX interrupt, when the packet rate is below @pkt_rate_low.
+ * @tx_coalesce_usecs_low: How many usecs to delay a TX interrupt after
+ *	a packet is sent, when the packet rate is below @pkt_rate_low.
+ * @tx_max_coalesced_frames_low: Maximum nuumber of packets to be sent before
+ *	a TX interrupt, when the packet rate is below @pkt_rate_low.
+ * @pkt_rate_high: Threshold for high packet rate (packets per second).
+ * @rx_coalesce_usecs_high: How many usecs to delay an RX interrupt after
+ *	a packet arrives, when the packet rate is above @pkt_rate_high.
+ * @rx_max_coalesced_frames_high: Maximum number of packets to be received
+ *	before an RX interrupt, when the packet rate is above @pkt_rate_high.
+ * @tx_coalesce_usecs_high: How many usecs to delay a TX interrupt after
+ *	a packet is sent, when the packet rate is above @pkt_rate_high.
+ * @tx_max_coalesced_frames_high: Maximum number of packets to be sent before
+ *	a TX interrupt, when the packet rate is above @pkt_rate_high.
+ * @rate_sample_interval: How often to do adaptive coalescing packet rate
+ *	sampling, measured in seconds.  Must not be zero.
+ *
+ * Each pair of (usecs, max_frames) fields specifies that interrupts
+ * should be coalesced until
+ *	(usecs > 0 && time_since_first_completion >= usecs) ||
+ *	(max_frames > 0 && completed_frames >= max_frames)
+ *
+ * It is illegal to set both usecs and max_frames to zero as this
+ * would cause interrupts to never be generated.  To disable
+ * coalescing, set usecs = 0 and max_frames = 1.
+ *
+ * Some implementations ignore the value of max_frames and use the
+ * condition time_since_first_completion >= usecs
+ *
+ * This is deprecated.  Drivers for hardware that does not support
+ * counting completions should validate that max_frames == !rx_usecs.
+ *
+ * Adaptive RX/TX coalescing is an algorithm implemented by some
+ * drivers to improve latency under low packet rates and improve
+ * throughput under high packet rates.  Some drivers only implement
+ * one of RX or TX adaptive coalescing.  Anything not implemented by
+ * the driver causes these values to be silently ignored.
+ *
+ * When the packet rate is below @pkt_rate_high but above
+ * @pkt_rate_low (both measured in packets per second) the
+ * normal {rx,tx}_* coalescing parameters are used.
+ */
+struct ethtool_coalesce {
+	__u32	cmd;
+	__u32	rx_coalesce_usecs;
+	__u32	rx_max_coalesced_frames;
+	__u32	rx_coalesce_usecs_irq;
+	__u32	rx_max_coalesced_frames_irq;
+	__u32	tx_coalesce_usecs;
+	__u32	tx_max_coalesced_frames;
+	__u32	tx_coalesce_usecs_irq;
+	__u32	tx_max_coalesced_frames_irq;
+	__u32	stats_block_coalesce_usecs;
+	__u32	use_adaptive_rx_coalesce;
+	__u32	use_adaptive_tx_coalesce;
+	__u32	pkt_rate_low;
+	__u32	rx_coalesce_usecs_low;
+	__u32	rx_max_coalesced_frames_low;
+	__u32	tx_coalesce_usecs_low;
+	__u32	tx_max_coalesced_frames_low;
+	__u32	pkt_rate_high;
+	__u32	rx_coalesce_usecs_high;
+	__u32	rx_max_coalesced_frames_high;
+	__u32	tx_coalesce_usecs_high;
+	__u32	tx_max_coalesced_frames_high;
+	__u32	rate_sample_interval;
+};
+
+/**
+ * struct ethtool_ringparam - RX/TX ring parameters
+ * @cmd: Command number = %ETHTOOL_GRINGPARAM or %ETHTOOL_SRINGPARAM
+ * @rx_max_pending: Maximum supported number of pending entries per
+ *	RX ring.  Read-only.
+ * @rx_mini_max_pending: Maximum supported number of pending entries
+ *	per RX mini ring.  Read-only.
+ * @rx_jumbo_max_pending: Maximum supported number of pending entries
+ *	per RX jumbo ring.  Read-only.
+ * @tx_max_pending: Maximum supported number of pending entries per
+ *	TX ring.  Read-only.
+ * @rx_pending: Current maximum number of pending entries per RX ring
+ * @rx_mini_pending: Current maximum number of pending entries per RX
+ *	mini ring
+ * @rx_jumbo_pending: Current maximum number of pending entries per RX
+ *	jumbo ring
+ * @tx_pending: Current maximum supported number of pending entries
+ *	per TX ring
+ *
+ * If the interface does not have separate RX mini and/or jumbo rings,
+ * @rx_mini_max_pending and/or @rx_jumbo_max_pending will be 0.
+ *
+ * There may also be driver-dependent minimum values for the number
+ * of entries per ring.
+ */
+struct ethtool_ringparam {
+	__u32	cmd;
+	__u32	rx_max_pending;
+	__u32	rx_mini_max_pending;
+	__u32	rx_jumbo_max_pending;
+	__u32	tx_max_pending;
+	__u32	rx_pending;
+	__u32	rx_mini_pending;
+	__u32	rx_jumbo_pending;
+	__u32	tx_pending;
+};
+
+/**
+ * struct ethtool_channels - configuring number of network channel
+ * @cmd: ETHTOOL_{G,S}CHANNELS
+ * @max_rx: Read only. Maximum number of receive channel the driver support.
+ * @max_tx: Read only. Maximum number of transmit channel the driver support.
+ * @max_other: Read only. Maximum number of other channel the driver support.
+ * @max_combined: Read only. Maximum number of combined channel the driver
+ *	support. Set of queues RX, TX or other.
+ * @rx_count: Valid values are in the range 1 to the max_rx.
+ * @tx_count: Valid values are in the range 1 to the max_tx.
+ * @other_count: Valid values are in the range 1 to the max_other.
+ * @combined_count: Valid values are in the range 1 to the max_combined.
+ *
+ * This can be used to configure RX, TX and other channels.
+ */
+
+struct ethtool_channels {
+	__u32	cmd;
+	__u32	max_rx;
+	__u32	max_tx;
+	__u32	max_other;
+	__u32	max_combined;
+	__u32	rx_count;
+	__u32	tx_count;
+	__u32	other_count;
+	__u32	combined_count;
+};
+
+/**
+ * struct ethtool_pauseparam - Ethernet pause (flow control) parameters
+ * @cmd: Command number = %ETHTOOL_GPAUSEPARAM or %ETHTOOL_SPAUSEPARAM
+ * @autoneg: Flag to enable autonegotiation of pause frame use
+ * @rx_pause: Flag to enable reception of pause frames
+ * @tx_pause: Flag to enable transmission of pause frames
+ *
+ * Drivers should reject a non-zero setting of @autoneg when
+ * autoneogotiation is disabled (or not supported) for the link.
+ *
+ * If the link is autonegotiated, drivers should use
+ * mii_advertise_flowctrl() or similar code to set the advertised
+ * pause frame capabilities based on the @rx_pause and @tx_pause flags,
+ * even if @autoneg is zero.  They should also allow the advertised
+ * pause frame capabilities to be controlled directly through the
+ * advertising field of &struct ethtool_cmd.
+ *
+ * If @autoneg is non-zero, the MAC is configured to send and/or
+ * receive pause frames according to the result of autonegotiation.
+ * Otherwise, it is configured directly based on the @rx_pause and
+ * @tx_pause flags.
+ */
+struct ethtool_pauseparam {
+	__u32	cmd;
+	__u32	autoneg;
+	__u32	rx_pause;
+	__u32	tx_pause;
+};
+
+/* Link extended state */
+enum ethtool_link_ext_state {
+	ETHTOOL_LINK_EXT_STATE_AUTONEG,
+	ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
+	ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
+	ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
+	ETHTOOL_LINK_EXT_STATE_NO_CABLE,
+	ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
+	ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE,
+	ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE,
+	ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED,
+	ETHTOOL_LINK_EXT_STATE_OVERHEAT,
+	ETHTOOL_LINK_EXT_STATE_MODULE,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */
+enum ethtool_link_ext_substate_autoneg {
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1,
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED,
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED,
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE,
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE,
+	ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE.
+ */
+enum ethtool_link_ext_substate_link_training {
+	ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1,
+	ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT,
+	ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY,
+	ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH.
+ */
+enum ethtool_link_ext_substate_link_logical_mismatch {
+	ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1,
+	ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK,
+	ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS,
+	ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED,
+	ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY.
+ */
+enum ethtool_link_ext_substate_bad_signal_integrity {
+	ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1,
+	ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE,
+	ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_REFERENCE_CLOCK_LOST,
+	ETHTOOL_LINK_EXT_SUBSTATE_BSI_SERDES_ALOS,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */
+enum ethtool_link_ext_substate_cable_issue {
+	ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1,
+	ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE,
+};
+
+/* More information in addition to ETHTOOL_LINK_EXT_STATE_MODULE. */
+enum ethtool_link_ext_substate_module {
+	ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY = 1,
+};
+
+#define ETH_GSTRING_LEN		32
+
+/**
+ * enum ethtool_stringset - string set ID
+ * @ETH_SS_TEST: Self-test result names, for use with %ETHTOOL_TEST
+ * @ETH_SS_STATS: Statistic names, for use with %ETHTOOL_GSTATS
+ * @ETH_SS_PRIV_FLAGS: Driver private flag names, for use with
+ *	%ETHTOOL_GPFLAGS and %ETHTOOL_SPFLAGS
+ * @ETH_SS_NTUPLE_FILTERS: Previously used with %ETHTOOL_GRXNTUPLE;
+ *	now deprecated
+ * @ETH_SS_FEATURES: Device feature names
+ * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names
+ * @ETH_SS_TUNABLES: tunable names
+ * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS
+ * @ETH_SS_PHY_TUNABLES: PHY tunable names
+ * @ETH_SS_LINK_MODES: link mode names
+ * @ETH_SS_MSG_CLASSES: debug message class names
+ * @ETH_SS_WOL_MODES: wake-on-lan modes
+ * @ETH_SS_SOF_TIMESTAMPING: SOF_TIMESTAMPING_* flags
+ * @ETH_SS_TS_TX_TYPES: timestamping Tx types
+ * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters
+ * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types
+ * @ETH_SS_STATS_STD: standardized stats
+ * @ETH_SS_STATS_ETH_PHY: names of IEEE 802.3 PHY statistics
+ * @ETH_SS_STATS_ETH_MAC: names of IEEE 802.3 MAC statistics
+ * @ETH_SS_STATS_ETH_CTRL: names of IEEE 802.3 MAC Control statistics
+ * @ETH_SS_STATS_RMON: names of RMON statistics
+ *
+ * @ETH_SS_COUNT: number of defined string sets
+ */
+enum ethtool_stringset {
+	ETH_SS_TEST		= 0,
+	ETH_SS_STATS,
+	ETH_SS_PRIV_FLAGS,
+	ETH_SS_NTUPLE_FILTERS,
+	ETH_SS_FEATURES,
+	ETH_SS_RSS_HASH_FUNCS,
+	ETH_SS_TUNABLES,
+	ETH_SS_PHY_STATS,
+	ETH_SS_PHY_TUNABLES,
+	ETH_SS_LINK_MODES,
+	ETH_SS_MSG_CLASSES,
+	ETH_SS_WOL_MODES,
+	ETH_SS_SOF_TIMESTAMPING,
+	ETH_SS_TS_TX_TYPES,
+	ETH_SS_TS_RX_FILTERS,
+	ETH_SS_UDP_TUNNEL_TYPES,
+	ETH_SS_STATS_STD,
+	ETH_SS_STATS_ETH_PHY,
+	ETH_SS_STATS_ETH_MAC,
+	ETH_SS_STATS_ETH_CTRL,
+	ETH_SS_STATS_RMON,
+
+	/* add new constants above here */
+	ETH_SS_COUNT
+};
+
+/**
+ * enum ethtool_mac_stats_src - source of ethtool MAC statistics
+ * @ETHTOOL_MAC_STATS_SRC_AGGREGATE:
+ *	if device supports a MAC merge layer, this retrieves the aggregate
+ *	statistics of the eMAC and pMAC. Otherwise, it retrieves just the
+ *	statistics of the single (express) MAC.
+ * @ETHTOOL_MAC_STATS_SRC_EMAC:
+ *	if device supports a MM layer, this retrieves the eMAC statistics.
+ *	Otherwise, it retrieves the statistics of the single (express) MAC.
+ * @ETHTOOL_MAC_STATS_SRC_PMAC:
+ *	if device supports a MM layer, this retrieves the pMAC statistics.
+ */
+enum ethtool_mac_stats_src {
+	ETHTOOL_MAC_STATS_SRC_AGGREGATE,
+	ETHTOOL_MAC_STATS_SRC_EMAC,
+	ETHTOOL_MAC_STATS_SRC_PMAC,
+};
+
+/**
+ * enum ethtool_module_power_mode_policy - plug-in module power mode policy
+ * @ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH: Module is always in high power mode.
+ * @ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO: Module is transitioned by the host
+ *	to high power mode when the first port using it is put administratively
+ *	up and to low power mode when the last port using it is put
+ *	administratively down.
+ */
+enum ethtool_module_power_mode_policy {
+	ETHTOOL_MODULE_POWER_MODE_POLICY_HIGH = 1,
+	ETHTOOL_MODULE_POWER_MODE_POLICY_AUTO,
+};
+
+/**
+ * enum ethtool_module_power_mode - plug-in module power mode
+ * @ETHTOOL_MODULE_POWER_MODE_LOW: Module is in low power mode.
+ * @ETHTOOL_MODULE_POWER_MODE_HIGH: Module is in high power mode.
+ */
+enum ethtool_module_power_mode {
+	ETHTOOL_MODULE_POWER_MODE_LOW = 1,
+	ETHTOOL_MODULE_POWER_MODE_HIGH,
+};
+
+/**
+ * enum ethtool_podl_pse_admin_state - operational state of the PoDL PSE
+ *	functions. IEEE 802.3-2018 30.15.1.1.2 aPoDLPSEAdminState
+ * @ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN: state of PoDL PSE functions are
+ * 	unknown
+ * @ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED: PoDL PSE functions are disabled
+ * @ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED: PoDL PSE functions are enabled
+ */
+enum ethtool_podl_pse_admin_state {
+	ETHTOOL_PODL_PSE_ADMIN_STATE_UNKNOWN = 1,
+	ETHTOOL_PODL_PSE_ADMIN_STATE_DISABLED,
+	ETHTOOL_PODL_PSE_ADMIN_STATE_ENABLED,
+};
+
+/**
+ * enum ethtool_podl_pse_pw_d_status - power detection status of the PoDL PSE.
+ *	IEEE 802.3-2018 30.15.1.1.3 aPoDLPSEPowerDetectionStatus:
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN: PoDL PSE
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED: "The enumeration “disabled” is
+ *	asserted true when the PoDL PSE state diagram variable mr_pse_enable is
+ *	false"
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING: "The enumeration “searching” is
+ *	asserted true when either of the PSE state diagram variables
+ *	pi_detecting or pi_classifying is true."
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING: "The enumeration “deliveringPower”
+ *	is asserted true when the PoDL PSE state diagram variable pi_powered is
+ *	true."
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP: "The enumeration “sleep” is asserted
+ *	true when the PoDL PSE state diagram variable pi_sleeping is true."
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE: "The enumeration “idle” is asserted true
+ *	when the logical combination of the PoDL PSE state diagram variables
+ *	pi_prebiased*!pi_sleeping is true."
+ * @ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR: "The enumeration “error” is asserted
+ *	true when the PoDL PSE state diagram variable overload_held is true."
+ */
+enum ethtool_podl_pse_pw_d_status {
+	ETHTOOL_PODL_PSE_PW_D_STATUS_UNKNOWN = 1,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_DISABLED,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_SEARCHING,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_DELIVERING,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_SLEEP,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_IDLE,
+	ETHTOOL_PODL_PSE_PW_D_STATUS_ERROR,
+};
+
+/**
+ * enum ethtool_mm_verify_status - status of MAC Merge Verify function
+ * @ETHTOOL_MM_VERIFY_STATUS_UNKNOWN:
+ *	verification status is unknown
+ * @ETHTOOL_MM_VERIFY_STATUS_INITIAL:
+ *	the 802.3 Verify State diagram is in the state INIT_VERIFICATION
+ * @ETHTOOL_MM_VERIFY_STATUS_VERIFYING:
+ *	the Verify State diagram is in the state VERIFICATION_IDLE,
+ *	SEND_VERIFY or WAIT_FOR_RESPONSE
+ * @ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED:
+ *	indicates that the Verify State diagram is in the state VERIFIED
+ * @ETHTOOL_MM_VERIFY_STATUS_FAILED:
+ *	the Verify State diagram is in the state VERIFY_FAIL
+ * @ETHTOOL_MM_VERIFY_STATUS_DISABLED:
+ *	verification of preemption operation is disabled
+ */
+enum ethtool_mm_verify_status {
+	ETHTOOL_MM_VERIFY_STATUS_UNKNOWN,
+	ETHTOOL_MM_VERIFY_STATUS_INITIAL,
+	ETHTOOL_MM_VERIFY_STATUS_VERIFYING,
+	ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED,
+	ETHTOOL_MM_VERIFY_STATUS_FAILED,
+	ETHTOOL_MM_VERIFY_STATUS_DISABLED,
+};
+
+/**
+ * struct ethtool_gstrings - string set for data tagging
+ * @cmd: Command number = %ETHTOOL_GSTRINGS
+ * @string_set: String set ID; one of &enum ethtool_stringset
+ * @len: On return, the number of strings in the string set
+ * @data: Buffer for strings.  Each string is null-padded to a size of
+ *	%ETH_GSTRING_LEN.
+ *
+ * Users must use %ETHTOOL_GSSET_INFO to find the number of strings in
+ * the string set.  They must allocate a buffer of the appropriate
+ * size immediately following this structure.
+ */
+struct ethtool_gstrings {
+	__u32	cmd;
+	__u32	string_set;
+	__u32	len;
+	__u8	data[];
+};
+
+/**
+ * struct ethtool_sset_info - string set information
+ * @cmd: Command number = %ETHTOOL_GSSET_INFO
+ * @reserved: Reserved for future use; see the note on reserved space.
+ * @sset_mask: On entry, a bitmask of string sets to query, with bits
+ *	numbered according to &enum ethtool_stringset.  On return, a
+ *	bitmask of those string sets queried that are supported.
+ * @data: Buffer for string set sizes.  On return, this contains the
+ *	size of each string set that was queried and supported, in
+ *	order of ID.
+ *
+ * Example: The user passes in @sset_mask = 0x7 (sets 0, 1, 2) and on
+ * return @sset_mask == 0x6 (sets 1, 2).  Then @data[0] contains the
+ * size of set 1 and @data[1] contains the size of set 2.
+ *
+ * Users must allocate a buffer of the appropriate size (4 * number of
+ * sets queried) immediately following this structure.
+ */
+struct ethtool_sset_info {
+	__u32	cmd;
+	__u32	reserved;
+	__u64	sset_mask;
+	__u32	data[];
+};
+
+/**
+ * enum ethtool_test_flags - flags definition of ethtool_test
+ * @ETH_TEST_FL_OFFLINE: if set perform online and offline tests, otherwise
+ *	only online tests.
+ * @ETH_TEST_FL_FAILED: Driver set this flag if test fails.
+ * @ETH_TEST_FL_EXTERNAL_LB: Application request to perform external loopback
+ *	test.
+ * @ETH_TEST_FL_EXTERNAL_LB_DONE: Driver performed the external loopback test
+ */
+
+enum ethtool_test_flags {
+	ETH_TEST_FL_OFFLINE	= (1 << 0),
+	ETH_TEST_FL_FAILED	= (1 << 1),
+	ETH_TEST_FL_EXTERNAL_LB	= (1 << 2),
+	ETH_TEST_FL_EXTERNAL_LB_DONE	= (1 << 3),
+};
+
+/**
+ * struct ethtool_test - device self-test invocation
+ * @cmd: Command number = %ETHTOOL_TEST
+ * @flags: A bitmask of flags from &enum ethtool_test_flags.  Some
+ *	flags may be set by the user on entry; others may be set by
+ *	the driver on return.
+ * @reserved: Reserved for future use; see the note on reserved space.
+ * @len: On return, the number of test results
+ * @data: Array of test results
+ *
+ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
+ * number of test results that will be returned.  They must allocate a
+ * buffer of the appropriate size (8 * number of results) immediately
+ * following this structure.
+ */
+struct ethtool_test {
+	__u32	cmd;
+	__u32	flags;
+	__u32	reserved;
+	__u32	len;
+	__u64	data[];
+};
+
+/**
+ * struct ethtool_stats - device-specific statistics
+ * @cmd: Command number = %ETHTOOL_GSTATS
+ * @n_stats: On return, the number of statistics
+ * @data: Array of statistics
+ *
+ * Users must use %ETHTOOL_GSSET_INFO or %ETHTOOL_GDRVINFO to find the
+ * number of statistics that will be returned.  They must allocate a
+ * buffer of the appropriate size (8 * number of statistics)
+ * immediately following this structure.
+ */
+struct ethtool_stats {
+	__u32	cmd;
+	__u32	n_stats;
+	__u64	data[];
+};
+
+/**
+ * struct ethtool_perm_addr - permanent hardware address
+ * @cmd: Command number = %ETHTOOL_GPERMADDR
+ * @size: On entry, the size of the buffer.  On return, the size of the
+ *	address.  The command fails if the buffer is too small.
+ * @data: Buffer for the address
+ *
+ * Users must allocate the buffer immediately following this structure.
+ * A buffer size of %MAX_ADDR_LEN should be sufficient for any address
+ * type.
+ */
+struct ethtool_perm_addr {
+	__u32	cmd;
+	__u32	size;
+	__u8	data[];
+};
+
+/* boolean flags controlling per-interface behavior characteristics.
+ * When reading, the flag indicates whether or not a certain behavior
+ * is enabled/present.  When writing, the flag indicates whether
+ * or not the driver should turn on (set) or off (clear) a behavior.
+ *
+ * Some behaviors may read-only (unconditionally absent or present).
+ * If such is the case, return EINVAL in the set-flags operation if the
+ * flag differs from the read-only value.
+ */
+enum ethtool_flags {
+	ETH_FLAG_TXVLAN		= (1 << 7),	/* TX VLAN offload enabled */
+	ETH_FLAG_RXVLAN		= (1 << 8),	/* RX VLAN offload enabled */
+	ETH_FLAG_LRO		= (1 << 15),	/* LRO is enabled */
+	ETH_FLAG_NTUPLE		= (1 << 27),	/* N-tuple filters enabled */
+	ETH_FLAG_RXHASH		= (1 << 28),
+};
+
+/* The following structures are for supporting RX network flow
+ * classification and RX n-tuple configuration. Note, all multibyte
+ * fields, e.g., ip4src, ip4dst, psrc, pdst, spi, etc. are expected to
+ * be in network byte order.
+ */
+
+/**
+ * struct ethtool_tcpip4_spec - flow specification for TCP/IPv4 etc.
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @psrc: Source port
+ * @pdst: Destination port
+ * @tos: Type-of-service
+ *
+ * This can be used to specify a TCP/IPv4, UDP/IPv4 or SCTP/IPv4 flow.
+ */
+struct ethtool_tcpip4_spec {
+	__be32	ip4src;
+	__be32	ip4dst;
+	__be16	psrc;
+	__be16	pdst;
+	__u8    tos;
+};
+
+/**
+ * struct ethtool_ah_espip4_spec - flow specification for IPsec/IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @spi: Security parameters index
+ * @tos: Type-of-service
+ *
+ * This can be used to specify an IPsec transport or tunnel over IPv4.
+ */
+struct ethtool_ah_espip4_spec {
+	__be32	ip4src;
+	__be32	ip4dst;
+	__be32	spi;
+	__u8    tos;
+};
+
+#define	ETH_RX_NFC_IP4	1
+
+/**
+ * struct ethtool_usrip4_spec - general flow specification for IPv4
+ * @ip4src: Source host
+ * @ip4dst: Destination host
+ * @l4_4_bytes: First 4 bytes of transport (layer 4) header
+ * @tos: Type-of-service
+ * @ip_ver: Value must be %ETH_RX_NFC_IP4; mask must be 0
+ * @proto: Transport protocol number; mask must be 0
+ */
+struct ethtool_usrip4_spec {
+	__be32	ip4src;
+	__be32	ip4dst;
+	__be32	l4_4_bytes;
+	__u8    tos;
+	__u8    ip_ver;
+	__u8    proto;
+};
+
+/**
+ * struct ethtool_tcpip6_spec - flow specification for TCP/IPv6 etc.
+ * @ip6src: Source host
+ * @ip6dst: Destination host
+ * @psrc: Source port
+ * @pdst: Destination port
+ * @tclass: Traffic Class
+ *
+ * This can be used to specify a TCP/IPv6, UDP/IPv6 or SCTP/IPv6 flow.
+ */
+struct ethtool_tcpip6_spec {
+	__be32	ip6src[4];
+	__be32	ip6dst[4];
+	__be16	psrc;
+	__be16	pdst;
+	__u8    tclass;
+};
+
+/**
+ * struct ethtool_ah_espip6_spec - flow specification for IPsec/IPv6
+ * @ip6src: Source host
+ * @ip6dst: Destination host
+ * @spi: Security parameters index
+ * @tclass: Traffic Class
+ *
+ * This can be used to specify an IPsec transport or tunnel over IPv6.
+ */
+struct ethtool_ah_espip6_spec {
+	__be32	ip6src[4];
+	__be32	ip6dst[4];
+	__be32	spi;
+	__u8    tclass;
+};
+
+/**
+ * struct ethtool_usrip6_spec - general flow specification for IPv6
+ * @ip6src: Source host
+ * @ip6dst: Destination host
+ * @l4_4_bytes: First 4 bytes of transport (layer 4) header
+ * @tclass: Traffic Class
+ * @l4_proto: Transport protocol number (nexthdr after any Extension Headers)
+ */
+struct ethtool_usrip6_spec {
+	__be32	ip6src[4];
+	__be32	ip6dst[4];
+	__be32	l4_4_bytes;
+	__u8    tclass;
+	__u8    l4_proto;
+};
+
+union ethtool_flow_union {
+	struct ethtool_tcpip4_spec		tcp_ip4_spec;
+	struct ethtool_tcpip4_spec		udp_ip4_spec;
+	struct ethtool_tcpip4_spec		sctp_ip4_spec;
+	struct ethtool_ah_espip4_spec		ah_ip4_spec;
+	struct ethtool_ah_espip4_spec		esp_ip4_spec;
+	struct ethtool_usrip4_spec		usr_ip4_spec;
+	struct ethtool_tcpip6_spec		tcp_ip6_spec;
+	struct ethtool_tcpip6_spec		udp_ip6_spec;
+	struct ethtool_tcpip6_spec		sctp_ip6_spec;
+	struct ethtool_ah_espip6_spec		ah_ip6_spec;
+	struct ethtool_ah_espip6_spec		esp_ip6_spec;
+	struct ethtool_usrip6_spec		usr_ip6_spec;
+	struct ethhdr				ether_spec;
+	__u8					hdata[52];
+};
+
+/**
+ * struct ethtool_flow_ext - additional RX flow fields
+ * @h_dest: destination MAC address
+ * @vlan_etype: VLAN EtherType
+ * @vlan_tci: VLAN tag control information
+ * @data: user defined data
+ * @padding: Reserved for future use; see the note on reserved space.
+ *
+ * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT
+ * is set in &struct ethtool_rx_flow_spec @flow_type.
+ * @h_dest is valid if %FLOW_MAC_EXT is set.
+ */
+struct ethtool_flow_ext {
+	__u8		padding[2];
+	unsigned char	h_dest[ETH_ALEN];
+	__be16		vlan_etype;
+	__be16		vlan_tci;
+	__be32		data[2];
+};
+
+/**
+ * struct ethtool_rx_flow_spec - classification rule for RX flows
+ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
+ * @h_u: Flow fields to match (dependent on @flow_type)
+ * @h_ext: Additional fields to match
+ * @m_u: Masks for flow field bits to be matched
+ * @m_ext: Masks for additional field bits to be matched
+ *	Note, all additional fields must be ignored unless @flow_type
+ *	includes the %FLOW_EXT or %FLOW_MAC_EXT flag
+ *	(see &struct ethtool_flow_ext description).
+ * @ring_cookie: RX ring/queue index to deliver to, or %RX_CLS_FLOW_DISC
+ *	if packets should be discarded, or %RX_CLS_FLOW_WAKE if the
+ *	packets should be used for Wake-on-LAN with %WAKE_FILTER
+ * @location: Location of rule in the table.  Locations must be
+ *	numbered such that a flow matching multiple rules will be
+ *	classified according to the first (lowest numbered) rule.
+ */
+struct ethtool_rx_flow_spec {
+	__u32		flow_type;
+	union ethtool_flow_union h_u;
+	struct ethtool_flow_ext h_ext;
+	union ethtool_flow_union m_u;
+	struct ethtool_flow_ext m_ext;
+	__u64		ring_cookie;
+	__u32		location;
+};
+
+/* How rings are laid out when accessing virtual functions or
+ * offloaded queues is device specific. To allow users to do flow
+ * steering and specify these queues the ring cookie is partitioned
+ * into a 32bit queue index with an 8 bit virtual function id.
+ * This also leaves the 3bytes for further specifiers. It is possible
+ * future devices may support more than 256 virtual functions if
+ * devices start supporting PCIe w/ARI. However at the moment I
+ * do not know of any devices that support this so I do not reserve
+ * space for this at this time. If a future patch consumes the next
+ * byte it should be aware of this possibility.
+ */
+#define ETHTOOL_RX_FLOW_SPEC_RING	0x00000000FFFFFFFFLL
+#define ETHTOOL_RX_FLOW_SPEC_RING_VF	0x000000FF00000000LL
+#define ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF 32
+static __inline__ __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie)
+{
+	return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie;
+}
+
+static __inline__ __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
+{
+	return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >>
+				ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
+}
+
+/**
+ * struct ethtool_rxnfc - command to get or set RX flow classification rules
+ * @cmd: Specific command number - %ETHTOOL_GRXFH, %ETHTOOL_SRXFH,
+ *	%ETHTOOL_GRXRINGS, %ETHTOOL_GRXCLSRLCNT, %ETHTOOL_GRXCLSRULE,
+ *	%ETHTOOL_GRXCLSRLALL, %ETHTOOL_SRXCLSRLDEL or %ETHTOOL_SRXCLSRLINS
+ * @flow_type: Type of flow to be affected, e.g. %TCP_V4_FLOW
+ * @data: Command-dependent value
+ * @fs: Flow classification rule
+ * @rss_context: RSS context to be affected
+ * @rule_cnt: Number of rules to be affected
+ * @rule_locs: Array of used rule locations
+ *
+ * For %ETHTOOL_GRXFH and %ETHTOOL_SRXFH, @data is a bitmask indicating
+ * the fields included in the flow hash, e.g. %RXH_IP_SRC.  The following
+ * structure fields must not be used, except that if @flow_type includes
+ * the %FLOW_RSS flag, then @rss_context determines which RSS context to
+ * act on.
+ *
+ * For %ETHTOOL_GRXRINGS, @data is set to the number of RX rings/queues
+ * on return.
+ *
+ * For %ETHTOOL_GRXCLSRLCNT, @rule_cnt is set to the number of defined
+ * rules on return.  If @data is non-zero on return then it is the
+ * size of the rule table, plus the flag %RX_CLS_LOC_SPECIAL if the
+ * driver supports any special location values.  If that flag is not
+ * set in @data then special location values should not be used.
+ *
+ * For %ETHTOOL_GRXCLSRULE, @fs.@location specifies the location of an
+ * existing rule on entry and @fs contains the rule on return; if
+ * @fs.@flow_type includes the %FLOW_RSS flag, then @rss_context is
+ * filled with the RSS context ID associated with the rule.
+ *
+ * For %ETHTOOL_GRXCLSRLALL, @rule_cnt specifies the array size of the
+ * user buffer for @rule_locs on entry.  On return, @data is the size
+ * of the rule table, @rule_cnt is the number of defined rules, and
+ * @rule_locs contains the locations of the defined rules.  Drivers
+ * must use the second parameter to get_rxnfc() instead of @rule_locs.
+ *
+ * For %ETHTOOL_SRXCLSRLINS, @fs specifies the rule to add or update.
+ * @fs.@location either specifies the location to use or is a special
+ * location value with %RX_CLS_LOC_SPECIAL flag set.  On return,
+ * @fs.@location is the actual rule location.  If @fs.@flow_type
+ * includes the %FLOW_RSS flag, @rss_context is the RSS context ID to
+ * use for flow spreading traffic which matches this rule.  The value
+ * from the rxfh indirection table will be added to @fs.@ring_cookie
+ * to choose which ring to deliver to.
+ *
+ * For %ETHTOOL_SRXCLSRLDEL, @fs.@location specifies the location of an
+ * existing rule on entry.
+ *
+ * A driver supporting the special location values for
+ * %ETHTOOL_SRXCLSRLINS may add the rule at any suitable unused
+ * location, and may remove a rule at a later location (lower
+ * priority) that matches exactly the same set of flows.  The special
+ * values are %RX_CLS_LOC_ANY, selecting any location;
+ * %RX_CLS_LOC_FIRST, selecting the first suitable location (maximum
+ * priority); and %RX_CLS_LOC_LAST, selecting the last suitable
+ * location (minimum priority).  Additional special values may be
+ * defined in future and drivers must return -%EINVAL for any
+ * unrecognised value.
+ */
+struct ethtool_rxnfc {
+	__u32				cmd;
+	__u32				flow_type;
+	__u64				data;
+	struct ethtool_rx_flow_spec	fs;
+	union {
+		__u32			rule_cnt;
+		__u32			rss_context;
+	};
+	__u32				rule_locs[];
+};
+
+
+/**
+ * struct ethtool_rxfh_indir - command to get or set RX flow hash indirection
+ * @cmd: Specific command number - %ETHTOOL_GRXFHINDIR or %ETHTOOL_SRXFHINDIR
+ * @size: On entry, the array size of the user buffer, which may be zero.
+ *	On return from %ETHTOOL_GRXFHINDIR, the array size of the hardware
+ *	indirection table.
+ * @ring_index: RX ring/queue index for each hash value
+ *
+ * For %ETHTOOL_GRXFHINDIR, a @size of zero means that only the size
+ * should be returned.  For %ETHTOOL_SRXFHINDIR, a @size of zero means
+ * the table should be reset to default values.  This last feature
+ * is not supported by the original implementations.
+ */
+struct ethtool_rxfh_indir {
+	__u32	cmd;
+	__u32	size;
+	__u32	ring_index[];
+};
+
+/**
+ * struct ethtool_rxfh - command to get/set RX flow hash indir or/and hash key.
+ * @cmd: Specific command number - %ETHTOOL_GRSSH or %ETHTOOL_SRSSH
+ * @rss_context: RSS context identifier.  Context 0 is the default for normal
+ *	traffic; other contexts can be referenced as the destination for RX flow
+ *	classification rules.  %ETH_RXFH_CONTEXT_ALLOC is used with command
+ *	%ETHTOOL_SRSSH to allocate a new RSS context; on return this field will
+ *	contain the ID of the newly allocated context.
+ * @indir_size: On entry, the array size of the user buffer for the
+ *	indirection table, which may be zero, or (for %ETHTOOL_SRSSH),
+ *	%ETH_RXFH_INDIR_NO_CHANGE.  On return from %ETHTOOL_GRSSH,
+ *	the array size of the hardware indirection table.
+ * @key_size: On entry, the array size of the user buffer for the hash key,
+ *	which may be zero.  On return from %ETHTOOL_GRSSH, the size of the
+ *	hardware hash key.
+ * @hfunc: Defines the current RSS hash function used by HW (or to be set to).
+ *	Valid values are one of the %ETH_RSS_HASH_*.
+ * @rsvd8: Reserved for future use; see the note on reserved space.
+ * @rsvd32: Reserved for future use; see the note on reserved space.
+ * @rss_config: RX ring/queue index for each hash value i.e., indirection table
+ *	of @indir_size __u32 elements, followed by hash key of @key_size
+ *	bytes.
+ *
+ * For %ETHTOOL_GRSSH, a @indir_size and key_size of zero means that only the
+ * size should be returned.  For %ETHTOOL_SRSSH, an @indir_size of
+ * %ETH_RXFH_INDIR_NO_CHANGE means that indir table setting is not requested
+ * and a @indir_size of zero means the indir table should be reset to default
+ * values (if @rss_context == 0) or that the RSS context should be deleted.
+ * An hfunc of zero means that hash function setting is not requested.
+ */
+struct ethtool_rxfh {
+	__u32   cmd;
+	__u32	rss_context;
+	__u32   indir_size;
+	__u32   key_size;
+	__u8	hfunc;
+	__u8	rsvd8[3];
+	__u32	rsvd32;
+	__u32   rss_config[];
+};
+#define ETH_RXFH_CONTEXT_ALLOC		0xffffffff
+#define ETH_RXFH_INDIR_NO_CHANGE	0xffffffff
+
+/**
+ * struct ethtool_rx_ntuple_flow_spec - specification for RX flow filter
+ * @flow_type: Type of match to perform, e.g. %TCP_V4_FLOW
+ * @h_u: Flow field values to match (dependent on @flow_type)
+ * @m_u: Masks for flow field value bits to be ignored
+ * @vlan_tag: VLAN tag to match
+ * @vlan_tag_mask: Mask for VLAN tag bits to be ignored
+ * @data: Driver-dependent data to match
+ * @data_mask: Mask for driver-dependent data bits to be ignored
+ * @action: RX ring/queue index to deliver to (non-negative) or other action
+ *	(negative, e.g. %ETHTOOL_RXNTUPLE_ACTION_DROP)
+ *
+ * For flow types %TCP_V4_FLOW, %UDP_V4_FLOW and %SCTP_V4_FLOW, where
+ * a field value and mask are both zero this is treated as if all mask
+ * bits are set i.e. the field is ignored.
+ */
+struct ethtool_rx_ntuple_flow_spec {
+	__u32		 flow_type;
+	union {
+		struct ethtool_tcpip4_spec		tcp_ip4_spec;
+		struct ethtool_tcpip4_spec		udp_ip4_spec;
+		struct ethtool_tcpip4_spec		sctp_ip4_spec;
+		struct ethtool_ah_espip4_spec		ah_ip4_spec;
+		struct ethtool_ah_espip4_spec		esp_ip4_spec;
+		struct ethtool_usrip4_spec		usr_ip4_spec;
+		struct ethhdr				ether_spec;
+		__u8					hdata[72];
+	} h_u, m_u;
+
+	__u16	        vlan_tag;
+	__u16	        vlan_tag_mask;
+	__u64		data;
+	__u64		data_mask;
+
+	__s32		action;
+#define ETHTOOL_RXNTUPLE_ACTION_DROP	(-1)	/* drop packet */
+#define ETHTOOL_RXNTUPLE_ACTION_CLEAR	(-2)	/* clear filter */
+};
+
+/**
+ * struct ethtool_rx_ntuple - command to set or clear RX flow filter
+ * @cmd: Command number - %ETHTOOL_SRXNTUPLE
+ * @fs: Flow filter specification
+ */
+struct ethtool_rx_ntuple {
+	__u32					cmd;
+	struct ethtool_rx_ntuple_flow_spec	fs;
+};
+
+#define ETHTOOL_FLASH_MAX_FILENAME	128
+enum ethtool_flash_op_type {
+	ETHTOOL_FLASH_ALL_REGIONS	= 0,
+};
+
+/* for passing firmware flashing related parameters */
+struct ethtool_flash {
+	__u32	cmd;
+	__u32	region;
+	char	data[ETHTOOL_FLASH_MAX_FILENAME];
+};
+
+/**
+ * struct ethtool_dump - used for retrieving, setting device dump
+ * @cmd: Command number - %ETHTOOL_GET_DUMP_FLAG, %ETHTOOL_GET_DUMP_DATA, or
+ * 	%ETHTOOL_SET_DUMP
+ * @version: FW version of the dump, filled in by driver
+ * @flag: driver dependent flag for dump setting, filled in by driver during
+ *        get and filled in by ethtool for set operation.
+ *        flag must be initialized by macro ETH_FW_DUMP_DISABLE value when
+ *        firmware dump is disabled.
+ * @len: length of dump data, used as the length of the user buffer on entry to
+ * 	 %ETHTOOL_GET_DUMP_DATA and this is returned as dump length by driver
+ * 	 for %ETHTOOL_GET_DUMP_FLAG command
+ * @data: data collected for get dump data operation
+ */
+struct ethtool_dump {
+	__u32	cmd;
+	__u32	version;
+	__u32	flag;
+	__u32	len;
+	__u8	data[];
+};
+
+#define ETH_FW_DUMP_DISABLE 0
+
+/* for returning and changing feature sets */
+
+/**
+ * struct ethtool_get_features_block - block with state of 32 features
+ * @available: mask of changeable features
+ * @requested: mask of features requested to be enabled if possible
+ * @active: mask of currently enabled features
+ * @never_changed: mask of features not changeable for any device
+ */
+struct ethtool_get_features_block {
+	__u32	available;
+	__u32	requested;
+	__u32	active;
+	__u32	never_changed;
+};
+
+/**
+ * struct ethtool_gfeatures - command to get state of device's features
+ * @cmd: command number = %ETHTOOL_GFEATURES
+ * @size: On entry, the number of elements in the features[] array;
+ *	on return, the number of elements in features[] needed to hold
+ *	all features
+ * @features: state of features
+ */
+struct ethtool_gfeatures {
+	__u32	cmd;
+	__u32	size;
+	struct ethtool_get_features_block features[];
+};
+
+/**
+ * struct ethtool_set_features_block - block with request for 32 features
+ * @valid: mask of features to be changed
+ * @requested: values of features to be changed
+ */
+struct ethtool_set_features_block {
+	__u32	valid;
+	__u32	requested;
+};
+
+/**
+ * struct ethtool_sfeatures - command to request change in device's features
+ * @cmd: command number = %ETHTOOL_SFEATURES
+ * @size: array size of the features[] array
+ * @features: feature change masks
+ */
+struct ethtool_sfeatures {
+	__u32	cmd;
+	__u32	size;
+	struct ethtool_set_features_block features[];
+};
+
+/**
+ * struct ethtool_ts_info - holds a device's timestamping and PHC association
+ * @cmd: command number = %ETHTOOL_GET_TS_INFO
+ * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags
+ * @phc_index: device index of the associated PHC, or -1 if there is none
+ * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
+ * @tx_reserved: Reserved for future use; see the note on reserved space.
+ * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
+ * @rx_reserved: Reserved for future use; see the note on reserved space.
+ *
+ * The bits in the 'tx_types' and 'rx_filters' fields correspond to
+ * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values,
+ * respectively.  For example, if the device supports HWTSTAMP_TX_ON,
+ * then (1 << HWTSTAMP_TX_ON) in 'tx_types' will be set.
+ *
+ * Drivers should only report the filters they actually support without
+ * upscaling in the SIOCSHWTSTAMP ioctl. If the SIOCSHWSTAMP request for
+ * HWTSTAMP_FILTER_V1_SYNC is supported by HWTSTAMP_FILTER_V1_EVENT, then the
+ * driver should only report HWTSTAMP_FILTER_V1_EVENT in this op.
+ */
+struct ethtool_ts_info {
+	__u32	cmd;
+	__u32	so_timestamping;
+	__s32	phc_index;
+	__u32	tx_types;
+	__u32	tx_reserved[3];
+	__u32	rx_filters;
+	__u32	rx_reserved[3];
+};
+
+/*
+ * %ETHTOOL_SFEATURES changes features present in features[].valid to the
+ * values of corresponding bits in features[].requested. Bits in .requested
+ * not set in .valid or not changeable are ignored.
+ *
+ * Returns %EINVAL when .valid contains undefined or never-changeable bits
+ * or size is not equal to required number of features words (32-bit blocks).
+ * Returns >= 0 if request was completed; bits set in the value mean:
+ *   %ETHTOOL_F_UNSUPPORTED - there were bits set in .valid that are not
+ *	changeable (not present in %ETHTOOL_GFEATURES' features[].available)
+ *	those bits were ignored.
+ *   %ETHTOOL_F_WISH - some or all changes requested were recorded but the
+ *      resulting state of bits masked by .valid is not equal to .requested.
+ *      Probably there are other device-specific constraints on some features
+ *      in the set. When %ETHTOOL_F_UNSUPPORTED is set, .valid is considered
+ *      here as though ignored bits were cleared.
+ *   %ETHTOOL_F_COMPAT - some or all changes requested were made by calling
+ *      compatibility functions. Requested offload state cannot be properly
+ *      managed by kernel.
+ *
+ * Meaning of bits in the masks are obtained by %ETHTOOL_GSSET_INFO (number of
+ * bits in the arrays - always multiple of 32) and %ETHTOOL_GSTRINGS commands
+ * for ETH_SS_FEATURES string set. First entry in the table corresponds to least
+ * significant bit in features[0] fields. Empty strings mark undefined features.
+ */
+enum ethtool_sfeatures_retval_bits {
+	ETHTOOL_F_UNSUPPORTED__BIT,
+	ETHTOOL_F_WISH__BIT,
+	ETHTOOL_F_COMPAT__BIT,
+};
+
+#define ETHTOOL_F_UNSUPPORTED   (1 << ETHTOOL_F_UNSUPPORTED__BIT)
+#define ETHTOOL_F_WISH          (1 << ETHTOOL_F_WISH__BIT)
+#define ETHTOOL_F_COMPAT        (1 << ETHTOOL_F_COMPAT__BIT)
+
+#define MAX_NUM_QUEUE		4096
+
+/**
+ * struct ethtool_per_queue_op - apply sub command to the queues in mask.
+ * @cmd: ETHTOOL_PERQUEUE
+ * @sub_command: the sub command which apply to each queues
+ * @queue_mask: Bitmap of the queues which sub command apply to
+ * @data: A complete command structure following for each of the queues addressed
+ */
+struct ethtool_per_queue_op {
+	__u32	cmd;
+	__u32	sub_command;
+	__u32	queue_mask[__KERNEL_DIV_ROUND_UP(MAX_NUM_QUEUE, 32)];
+	char	data[];
+};
+
+/**
+ * struct ethtool_fecparam - Ethernet Forward Error Correction parameters
+ * @cmd: Command number = %ETHTOOL_GFECPARAM or %ETHTOOL_SFECPARAM
+ * @active_fec: FEC mode which is active on the port, single bit set, GET only.
+ * @fec: Bitmask of configured FEC modes.
+ * @reserved: Reserved for future extensions, ignore on GET, write 0 for SET.
+ *
+ * Note that @reserved was never validated on input and ethtool user space
+ * left it uninitialized when calling SET. Hence going forward it can only be
+ * used to return a value to userspace with GET.
+ *
+ * FEC modes supported by the device can be read via %ETHTOOL_GLINKSETTINGS.
+ * FEC settings are configured by link autonegotiation whenever it's enabled.
+ * With autoneg on %ETHTOOL_GFECPARAM can be used to read the current mode.
+ *
+ * When autoneg is disabled %ETHTOOL_SFECPARAM controls the FEC settings.
+ * It is recommended that drivers only accept a single bit set in @fec.
+ * When multiple bits are set in @fec drivers may pick mode in an implementation
+ * dependent way. Drivers should reject mixing %ETHTOOL_FEC_AUTO_BIT with other
+ * FEC modes, because it's unclear whether in this case other modes constrain
+ * AUTO or are independent choices.
+ * Drivers must reject SET requests if they support none of the requested modes.
+ *
+ * If device does not support FEC drivers may use %ETHTOOL_FEC_NONE instead
+ * of returning %EOPNOTSUPP from %ETHTOOL_GFECPARAM.
+ *
+ * See enum ethtool_fec_config_bits for definition of valid bits for both
+ * @fec and @active_fec.
+ */
+struct ethtool_fecparam {
+	__u32   cmd;
+	/* bitmask of FEC modes */
+	__u32   active_fec;
+	__u32   fec;
+	__u32   reserved;
+};
+
+/**
+ * enum ethtool_fec_config_bits - flags definition of ethtool_fec_configuration
+ * @ETHTOOL_FEC_NONE_BIT: FEC mode configuration is not supported. Should not
+ *			be used together with other bits. GET only.
+ * @ETHTOOL_FEC_AUTO_BIT: Select default/best FEC mode automatically, usually
+ *			based link mode and SFP parameters read from module's
+ *			EEPROM. This bit does _not_ mean autonegotiation.
+ * @ETHTOOL_FEC_OFF_BIT: No FEC Mode
+ * @ETHTOOL_FEC_RS_BIT: Reed-Solomon FEC Mode
+ * @ETHTOOL_FEC_BASER_BIT: Base-R/Reed-Solomon FEC Mode
+ * @ETHTOOL_FEC_LLRS_BIT: Low Latency Reed Solomon FEC Mode (25G/50G Ethernet
+ *			Consortium)
+ */
+enum ethtool_fec_config_bits {
+	ETHTOOL_FEC_NONE_BIT,
+	ETHTOOL_FEC_AUTO_BIT,
+	ETHTOOL_FEC_OFF_BIT,
+	ETHTOOL_FEC_RS_BIT,
+	ETHTOOL_FEC_BASER_BIT,
+	ETHTOOL_FEC_LLRS_BIT,
+};
+
+#define ETHTOOL_FEC_NONE		(1 << ETHTOOL_FEC_NONE_BIT)
+#define ETHTOOL_FEC_AUTO		(1 << ETHTOOL_FEC_AUTO_BIT)
+#define ETHTOOL_FEC_OFF			(1 << ETHTOOL_FEC_OFF_BIT)
+#define ETHTOOL_FEC_RS			(1 << ETHTOOL_FEC_RS_BIT)
+#define ETHTOOL_FEC_BASER		(1 << ETHTOOL_FEC_BASER_BIT)
+#define ETHTOOL_FEC_LLRS		(1 << ETHTOOL_FEC_LLRS_BIT)
+
+/* CMDs currently supported */
+#define ETHTOOL_GSET		0x00000001 /* DEPRECATED, Get settings.
+					    * Please use ETHTOOL_GLINKSETTINGS
+					    */
+#define ETHTOOL_SSET		0x00000002 /* DEPRECATED, Set settings.
+					    * Please use ETHTOOL_SLINKSETTINGS
+					    */
+#define ETHTOOL_GDRVINFO	0x00000003 /* Get driver info. */
+#define ETHTOOL_GREGS		0x00000004 /* Get NIC registers. */
+#define ETHTOOL_GWOL		0x00000005 /* Get wake-on-lan options. */
+#define ETHTOOL_SWOL		0x00000006 /* Set wake-on-lan options. */
+#define ETHTOOL_GMSGLVL		0x00000007 /* Get driver message level */
+#define ETHTOOL_SMSGLVL		0x00000008 /* Set driver msg level. */
+#define ETHTOOL_NWAY_RST	0x00000009 /* Restart autonegotiation. */
+/* Get link status for host, i.e. whether the interface *and* the
+ * physical port (if there is one) are up (ethtool_value). */
+#define ETHTOOL_GLINK		0x0000000a
+#define ETHTOOL_GEEPROM		0x0000000b /* Get EEPROM data */
+#define ETHTOOL_SEEPROM		0x0000000c /* Set EEPROM data. */
+#define ETHTOOL_GCOALESCE	0x0000000e /* Get coalesce config */
+#define ETHTOOL_SCOALESCE	0x0000000f /* Set coalesce config. */
+#define ETHTOOL_GRINGPARAM	0x00000010 /* Get ring parameters */
+#define ETHTOOL_SRINGPARAM	0x00000011 /* Set ring parameters. */
+#define ETHTOOL_GPAUSEPARAM	0x00000012 /* Get pause parameters */
+#define ETHTOOL_SPAUSEPARAM	0x00000013 /* Set pause parameters. */
+#define ETHTOOL_GRXCSUM		0x00000014 /* Get RX hw csum enable (ethtool_value) */
+#define ETHTOOL_SRXCSUM		0x00000015 /* Set RX hw csum enable (ethtool_value) */
+#define ETHTOOL_GTXCSUM		0x00000016 /* Get TX hw csum enable (ethtool_value) */
+#define ETHTOOL_STXCSUM		0x00000017 /* Set TX hw csum enable (ethtool_value) */
+#define ETHTOOL_GSG		0x00000018 /* Get scatter-gather enable
+					    * (ethtool_value) */
+#define ETHTOOL_SSG		0x00000019 /* Set scatter-gather enable
+					    * (ethtool_value). */
+#define ETHTOOL_TEST		0x0000001a /* execute NIC self-test. */
+#define ETHTOOL_GSTRINGS	0x0000001b /* get specified string set */
+#define ETHTOOL_PHYS_ID		0x0000001c /* identify the NIC */
+#define ETHTOOL_GSTATS		0x0000001d /* get NIC-specific statistics */
+#define ETHTOOL_GTSO		0x0000001e /* Get TSO enable (ethtool_value) */
+#define ETHTOOL_STSO		0x0000001f /* Set TSO enable (ethtool_value) */
+#define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
+#define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
+#define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
+#define ETHTOOL_GGSO		0x00000023 /* Get GSO enable (ethtool_value) */
+#define ETHTOOL_SGSO		0x00000024 /* Set GSO enable (ethtool_value) */
+#define ETHTOOL_GFLAGS		0x00000025 /* Get flags bitmap(ethtool_value) */
+#define ETHTOOL_SFLAGS		0x00000026 /* Set flags bitmap(ethtool_value) */
+#define ETHTOOL_GPFLAGS		0x00000027 /* Get driver-private flags bitmap */
+#define ETHTOOL_SPFLAGS		0x00000028 /* Set driver-private flags bitmap */
+
+#define ETHTOOL_GRXFH		0x00000029 /* Get RX flow hash configuration */
+#define ETHTOOL_SRXFH		0x0000002a /* Set RX flow hash configuration */
+#define ETHTOOL_GGRO		0x0000002b /* Get GRO enable (ethtool_value) */
+#define ETHTOOL_SGRO		0x0000002c /* Set GRO enable (ethtool_value) */
+#define ETHTOOL_GRXRINGS	0x0000002d /* Get RX rings available for LB */
+#define ETHTOOL_GRXCLSRLCNT	0x0000002e /* Get RX class rule count */
+#define ETHTOOL_GRXCLSRULE	0x0000002f /* Get RX classification rule */
+#define ETHTOOL_GRXCLSRLALL	0x00000030 /* Get all RX classification rule */
+#define ETHTOOL_SRXCLSRLDEL	0x00000031 /* Delete RX classification rule */
+#define ETHTOOL_SRXCLSRLINS	0x00000032 /* Insert RX classification rule */
+#define ETHTOOL_FLASHDEV	0x00000033 /* Flash firmware to device */
+#define ETHTOOL_RESET		0x00000034 /* Reset hardware */
+#define ETHTOOL_SRXNTUPLE	0x00000035 /* Add an n-tuple filter to device */
+#define ETHTOOL_GRXNTUPLE	0x00000036 /* deprecated */
+#define ETHTOOL_GSSET_INFO	0x00000037 /* Get string set info */
+#define ETHTOOL_GRXFHINDIR	0x00000038 /* Get RX flow hash indir'n table */
+#define ETHTOOL_SRXFHINDIR	0x00000039 /* Set RX flow hash indir'n table */
+
+#define ETHTOOL_GFEATURES	0x0000003a /* Get device offload settings */
+#define ETHTOOL_SFEATURES	0x0000003b /* Change device offload settings */
+#define ETHTOOL_GCHANNELS	0x0000003c /* Get no of channels */
+#define ETHTOOL_SCHANNELS	0x0000003d /* Set no of channels */
+#define ETHTOOL_SET_DUMP	0x0000003e /* Set dump settings */
+#define ETHTOOL_GET_DUMP_FLAG	0x0000003f /* Get dump settings */
+#define ETHTOOL_GET_DUMP_DATA	0x00000040 /* Get dump data */
+#define ETHTOOL_GET_TS_INFO	0x00000041 /* Get time stamping and PHC info */
+#define ETHTOOL_GMODULEINFO	0x00000042 /* Get plug-in module information */
+#define ETHTOOL_GMODULEEEPROM	0x00000043 /* Get plug-in module eeprom */
+#define ETHTOOL_GEEE		0x00000044 /* Get EEE settings */
+#define ETHTOOL_SEEE		0x00000045 /* Set EEE settings */
+
+#define ETHTOOL_GRSSH		0x00000046 /* Get RX flow hash configuration */
+#define ETHTOOL_SRSSH		0x00000047 /* Set RX flow hash configuration */
+#define ETHTOOL_GTUNABLE	0x00000048 /* Get tunable configuration */
+#define ETHTOOL_STUNABLE	0x00000049 /* Set tunable configuration */
+#define ETHTOOL_GPHYSTATS	0x0000004a /* get PHY-specific statistics */
+
+#define ETHTOOL_PERQUEUE	0x0000004b /* Set per queue options */
+
+#define ETHTOOL_GLINKSETTINGS	0x0000004c /* Get ethtool_link_settings */
+#define ETHTOOL_SLINKSETTINGS	0x0000004d /* Set ethtool_link_settings */
+#define ETHTOOL_PHY_GTUNABLE	0x0000004e /* Get PHY tunable configuration */
+#define ETHTOOL_PHY_STUNABLE	0x0000004f /* Set PHY tunable configuration */
+#define ETHTOOL_GFECPARAM	0x00000050 /* Get FEC settings */
+#define ETHTOOL_SFECPARAM	0x00000051 /* Set FEC settings */
+
+/* compatibility with older code */
+#define SPARC_ETH_GSET		ETHTOOL_GSET
+#define SPARC_ETH_SSET		ETHTOOL_SSET
+
+/* Link mode bit indices */
+enum ethtool_link_mode_bit_indices {
+	ETHTOOL_LINK_MODE_10baseT_Half_BIT	= 0,
+	ETHTOOL_LINK_MODE_10baseT_Full_BIT	= 1,
+	ETHTOOL_LINK_MODE_100baseT_Half_BIT	= 2,
+	ETHTOOL_LINK_MODE_100baseT_Full_BIT	= 3,
+	ETHTOOL_LINK_MODE_1000baseT_Half_BIT	= 4,
+	ETHTOOL_LINK_MODE_1000baseT_Full_BIT	= 5,
+	ETHTOOL_LINK_MODE_Autoneg_BIT		= 6,
+	ETHTOOL_LINK_MODE_TP_BIT		= 7,
+	ETHTOOL_LINK_MODE_AUI_BIT		= 8,
+	ETHTOOL_LINK_MODE_MII_BIT		= 9,
+	ETHTOOL_LINK_MODE_FIBRE_BIT		= 10,
+	ETHTOOL_LINK_MODE_BNC_BIT		= 11,
+	ETHTOOL_LINK_MODE_10000baseT_Full_BIT	= 12,
+	ETHTOOL_LINK_MODE_Pause_BIT		= 13,
+	ETHTOOL_LINK_MODE_Asym_Pause_BIT	= 14,
+	ETHTOOL_LINK_MODE_2500baseX_Full_BIT	= 15,
+	ETHTOOL_LINK_MODE_Backplane_BIT		= 16,
+	ETHTOOL_LINK_MODE_1000baseKX_Full_BIT	= 17,
+	ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT	= 18,
+	ETHTOOL_LINK_MODE_10000baseKR_Full_BIT	= 19,
+	ETHTOOL_LINK_MODE_10000baseR_FEC_BIT	= 20,
+	ETHTOOL_LINK_MODE_20000baseMLD2_Full_BIT = 21,
+	ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT	= 22,
+	ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT	= 23,
+	ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT	= 24,
+	ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT	= 25,
+	ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT	= 26,
+	ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT	= 27,
+	ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT	= 28,
+	ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT	= 29,
+	ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT	= 30,
+	ETHTOOL_LINK_MODE_25000baseCR_Full_BIT	= 31,
+
+	/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
+	 * 31. Please do NOT define any SUPPORTED_* or ADVERTISED_*
+	 * macro for bits > 31. The only way to use indices > 31 is to
+	 * use the new ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API.
+	 */
+
+	ETHTOOL_LINK_MODE_25000baseKR_Full_BIT	= 32,
+	ETHTOOL_LINK_MODE_25000baseSR_Full_BIT	= 33,
+	ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT	= 34,
+	ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT	= 35,
+	ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT	= 36,
+	ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT	= 37,
+	ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT	= 38,
+	ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT	= 39,
+	ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT		= 40,
+	ETHTOOL_LINK_MODE_1000baseX_Full_BIT	= 41,
+	ETHTOOL_LINK_MODE_10000baseCR_Full_BIT	= 42,
+	ETHTOOL_LINK_MODE_10000baseSR_Full_BIT	= 43,
+	ETHTOOL_LINK_MODE_10000baseLR_Full_BIT	= 44,
+	ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT	= 45,
+	ETHTOOL_LINK_MODE_10000baseER_Full_BIT	= 46,
+	ETHTOOL_LINK_MODE_2500baseT_Full_BIT	= 47,
+	ETHTOOL_LINK_MODE_5000baseT_Full_BIT	= 48,
+
+	ETHTOOL_LINK_MODE_FEC_NONE_BIT	= 49,
+	ETHTOOL_LINK_MODE_FEC_RS_BIT	= 50,
+	ETHTOOL_LINK_MODE_FEC_BASER_BIT	= 51,
+	ETHTOOL_LINK_MODE_50000baseKR_Full_BIT		 = 52,
+	ETHTOOL_LINK_MODE_50000baseSR_Full_BIT		 = 53,
+	ETHTOOL_LINK_MODE_50000baseCR_Full_BIT		 = 54,
+	ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT	 = 55,
+	ETHTOOL_LINK_MODE_50000baseDR_Full_BIT		 = 56,
+	ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT	 = 57,
+	ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT	 = 58,
+	ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT	 = 59,
+	ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT = 60,
+	ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT	 = 61,
+	ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT	 = 62,
+	ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT	 = 63,
+	ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64,
+	ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT	 = 65,
+	ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT	 = 66,
+	ETHTOOL_LINK_MODE_100baseT1_Full_BIT		 = 67,
+	ETHTOOL_LINK_MODE_1000baseT1_Full_BIT		 = 68,
+	ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT	 = 69,
+	ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT	 = 70,
+	ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT = 71,
+	ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT	 = 72,
+	ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT	 = 73,
+	ETHTOOL_LINK_MODE_FEC_LLRS_BIT			 = 74,
+	ETHTOOL_LINK_MODE_100000baseKR_Full_BIT		 = 75,
+	ETHTOOL_LINK_MODE_100000baseSR_Full_BIT		 = 76,
+	ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT	 = 77,
+	ETHTOOL_LINK_MODE_100000baseCR_Full_BIT		 = 78,
+	ETHTOOL_LINK_MODE_100000baseDR_Full_BIT		 = 79,
+	ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT	 = 80,
+	ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT	 = 81,
+	ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT = 82,
+	ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT	 = 83,
+	ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT	 = 84,
+	ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT	 = 85,
+	ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT	 = 86,
+	ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT = 87,
+	ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT	 = 88,
+	ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT	 = 89,
+	ETHTOOL_LINK_MODE_100baseFX_Half_BIT		 = 90,
+	ETHTOOL_LINK_MODE_100baseFX_Full_BIT		 = 91,
+	ETHTOOL_LINK_MODE_10baseT1L_Full_BIT		 = 92,
+	ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT	 = 93,
+	ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT	 = 94,
+	ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT	 = 95,
+	ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT	 = 96,
+	ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT	 = 97,
+	ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT	 = 98,
+	ETHTOOL_LINK_MODE_10baseT1S_Full_BIT		 = 99,
+	ETHTOOL_LINK_MODE_10baseT1S_Half_BIT		 = 100,
+	ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT	 = 101,
+
+	/* must be last entry */
+	__ETHTOOL_LINK_MODE_MASK_NBITS
+};
+
+#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name)	\
+	(1UL << (ETHTOOL_LINK_MODE_ ## base_name ## _BIT))
+
+/* DEPRECATED macros. Please migrate to
+ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT
+ * define any new SUPPORTED_* macro for bits > 31.
+ */
+#define SUPPORTED_10baseT_Half		__ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half)
+#define SUPPORTED_10baseT_Full		__ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full)
+#define SUPPORTED_100baseT_Half		__ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half)
+#define SUPPORTED_100baseT_Full		__ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full)
+#define SUPPORTED_1000baseT_Half	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half)
+#define SUPPORTED_1000baseT_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full)
+#define SUPPORTED_Autoneg		__ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg)
+#define SUPPORTED_TP			__ETHTOOL_LINK_MODE_LEGACY_MASK(TP)
+#define SUPPORTED_AUI			__ETHTOOL_LINK_MODE_LEGACY_MASK(AUI)
+#define SUPPORTED_MII			__ETHTOOL_LINK_MODE_LEGACY_MASK(MII)
+#define SUPPORTED_FIBRE			__ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE)
+#define SUPPORTED_BNC			__ETHTOOL_LINK_MODE_LEGACY_MASK(BNC)
+#define SUPPORTED_10000baseT_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full)
+#define SUPPORTED_Pause			__ETHTOOL_LINK_MODE_LEGACY_MASK(Pause)
+#define SUPPORTED_Asym_Pause		__ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause)
+#define SUPPORTED_2500baseX_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full)
+#define SUPPORTED_Backplane		__ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane)
+#define SUPPORTED_1000baseKX_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full)
+#define SUPPORTED_10000baseKX4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full)
+#define SUPPORTED_10000baseKR_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full)
+#define SUPPORTED_10000baseR_FEC	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC)
+#define SUPPORTED_20000baseMLD2_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full)
+#define SUPPORTED_20000baseKR2_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full)
+#define SUPPORTED_40000baseKR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full)
+#define SUPPORTED_40000baseCR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full)
+#define SUPPORTED_40000baseSR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full)
+#define SUPPORTED_40000baseLR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full)
+#define SUPPORTED_56000baseKR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full)
+#define SUPPORTED_56000baseCR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full)
+#define SUPPORTED_56000baseSR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full)
+#define SUPPORTED_56000baseLR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full)
+/* Please do not define any new SUPPORTED_* macro for bits > 31, see
+ * notice above.
+ */
+
+/*
+ * DEPRECATED macros. Please migrate to
+ * ETHTOOL_GLINKSETTINGS/ETHTOOL_SLINKSETTINGS API. Please do NOT
+ * define any new ADERTISE_* macro for bits > 31.
+ */
+#define ADVERTISED_10baseT_Half		__ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Half)
+#define ADVERTISED_10baseT_Full		__ETHTOOL_LINK_MODE_LEGACY_MASK(10baseT_Full)
+#define ADVERTISED_100baseT_Half	__ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Half)
+#define ADVERTISED_100baseT_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(100baseT_Full)
+#define ADVERTISED_1000baseT_Half	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Half)
+#define ADVERTISED_1000baseT_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseT_Full)
+#define ADVERTISED_Autoneg		__ETHTOOL_LINK_MODE_LEGACY_MASK(Autoneg)
+#define ADVERTISED_TP			__ETHTOOL_LINK_MODE_LEGACY_MASK(TP)
+#define ADVERTISED_AUI			__ETHTOOL_LINK_MODE_LEGACY_MASK(AUI)
+#define ADVERTISED_MII			__ETHTOOL_LINK_MODE_LEGACY_MASK(MII)
+#define ADVERTISED_FIBRE		__ETHTOOL_LINK_MODE_LEGACY_MASK(FIBRE)
+#define ADVERTISED_BNC			__ETHTOOL_LINK_MODE_LEGACY_MASK(BNC)
+#define ADVERTISED_10000baseT_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseT_Full)
+#define ADVERTISED_Pause		__ETHTOOL_LINK_MODE_LEGACY_MASK(Pause)
+#define ADVERTISED_Asym_Pause		__ETHTOOL_LINK_MODE_LEGACY_MASK(Asym_Pause)
+#define ADVERTISED_2500baseX_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(2500baseX_Full)
+#define ADVERTISED_Backplane		__ETHTOOL_LINK_MODE_LEGACY_MASK(Backplane)
+#define ADVERTISED_1000baseKX_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(1000baseKX_Full)
+#define ADVERTISED_10000baseKX4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKX4_Full)
+#define ADVERTISED_10000baseKR_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseKR_Full)
+#define ADVERTISED_10000baseR_FEC	__ETHTOOL_LINK_MODE_LEGACY_MASK(10000baseR_FEC)
+#define ADVERTISED_20000baseMLD2_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseMLD2_Full)
+#define ADVERTISED_20000baseKR2_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(20000baseKR2_Full)
+#define ADVERTISED_40000baseKR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseKR4_Full)
+#define ADVERTISED_40000baseCR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseCR4_Full)
+#define ADVERTISED_40000baseSR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseSR4_Full)
+#define ADVERTISED_40000baseLR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(40000baseLR4_Full)
+#define ADVERTISED_56000baseKR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseKR4_Full)
+#define ADVERTISED_56000baseCR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseCR4_Full)
+#define ADVERTISED_56000baseSR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseSR4_Full)
+#define ADVERTISED_56000baseLR4_Full	__ETHTOOL_LINK_MODE_LEGACY_MASK(56000baseLR4_Full)
+/* Please do not define any new ADVERTISED_* macro for bits > 31, see
+ * notice above.
+ */
+
+/* The following are all involved in forcing a particular link
+ * mode for the device for setting things.  When getting the
+ * devices settings, these indicate the current mode and whether
+ * it was forced up into this mode or autonegotiated.
+ */
+
+/* The forced speed, in units of 1Mb. All values 0 to INT_MAX are legal.
+ * Update drivers/net/phy/phy.c:phy_speed_to_str() and
+ * drivers/net/bonding/bond_3ad.c:__get_link_speed() when adding new values.
+ */
+#define SPEED_10		10
+#define SPEED_100		100
+#define SPEED_1000		1000
+#define SPEED_2500		2500
+#define SPEED_5000		5000
+#define SPEED_10000		10000
+#define SPEED_14000		14000
+#define SPEED_20000		20000
+#define SPEED_25000		25000
+#define SPEED_40000		40000
+#define SPEED_50000		50000
+#define SPEED_56000		56000
+#define SPEED_100000		100000
+#define SPEED_200000		200000
+#define SPEED_400000		400000
+#define SPEED_800000		800000
+
+#define SPEED_UNKNOWN		-1
+
+static __inline__ int ethtool_validate_speed(__u32 speed)
+{
+	return speed <= INT_MAX || speed == (__u32)SPEED_UNKNOWN;
+}
+
+/* Duplex, half or full. */
+#define DUPLEX_HALF		0x00
+#define DUPLEX_FULL		0x01
+#define DUPLEX_UNKNOWN		0xff
+
+static __inline__ int ethtool_validate_duplex(__u8 duplex)
+{
+	switch (duplex) {
+	case DUPLEX_HALF:
+	case DUPLEX_FULL:
+	case DUPLEX_UNKNOWN:
+		return 1;
+	}
+
+	return 0;
+}
+
+#define MASTER_SLAVE_CFG_UNSUPPORTED		0
+#define MASTER_SLAVE_CFG_UNKNOWN		1
+#define MASTER_SLAVE_CFG_MASTER_PREFERRED	2
+#define MASTER_SLAVE_CFG_SLAVE_PREFERRED	3
+#define MASTER_SLAVE_CFG_MASTER_FORCE		4
+#define MASTER_SLAVE_CFG_SLAVE_FORCE		5
+#define MASTER_SLAVE_STATE_UNSUPPORTED		0
+#define MASTER_SLAVE_STATE_UNKNOWN		1
+#define MASTER_SLAVE_STATE_MASTER		2
+#define MASTER_SLAVE_STATE_SLAVE		3
+#define MASTER_SLAVE_STATE_ERR			4
+
+/* These are used to throttle the rate of data on the phy interface when the
+ * native speed of the interface is higher than the link speed. These should
+ * not be used for phy interfaces which natively support multiple speeds (e.g.
+ * MII or SGMII).
+ */
+/* No rate matching performed. */
+#define RATE_MATCH_NONE		0
+/* The phy sends pause frames to throttle the MAC. */
+#define RATE_MATCH_PAUSE	1
+/* The phy asserts CRS to prevent the MAC from transmitting. */
+#define RATE_MATCH_CRS		2
+/* The MAC is programmed with a sufficiently-large IPG. */
+#define RATE_MATCH_OPEN_LOOP	3
+
+/* Which connector port. */
+#define PORT_TP			0x00
+#define PORT_AUI		0x01
+#define PORT_MII		0x02
+#define PORT_FIBRE		0x03
+#define PORT_BNC		0x04
+#define PORT_DA			0x05
+#define PORT_NONE		0xef
+#define PORT_OTHER		0xff
+
+/* Which transceiver to use. */
+#define XCVR_INTERNAL		0x00 /* PHY and MAC are in the same package */
+#define XCVR_EXTERNAL		0x01 /* PHY and MAC are in different packages */
+#define XCVR_DUMMY1		0x02
+#define XCVR_DUMMY2		0x03
+#define XCVR_DUMMY3		0x04
+
+/* Enable or disable autonegotiation. */
+#define AUTONEG_DISABLE		0x00
+#define AUTONEG_ENABLE		0x01
+
+/* MDI or MDI-X status/control - if MDI/MDI_X/AUTO is set then
+ * the driver is required to renegotiate link
+ */
+#define ETH_TP_MDI_INVALID	0x00 /* status: unknown; control: unsupported */
+#define ETH_TP_MDI		0x01 /* status: MDI;     control: force MDI */
+#define ETH_TP_MDI_X		0x02 /* status: MDI-X;   control: force MDI-X */
+#define ETH_TP_MDI_AUTO		0x03 /*                  control: auto-select */
+
+/* Wake-On-Lan options. */
+#define WAKE_PHY		(1 << 0)
+#define WAKE_UCAST		(1 << 1)
+#define WAKE_MCAST		(1 << 2)
+#define WAKE_BCAST		(1 << 3)
+#define WAKE_ARP		(1 << 4)
+#define WAKE_MAGIC		(1 << 5)
+#define WAKE_MAGICSECURE	(1 << 6) /* only meaningful if WAKE_MAGIC */
+#define WAKE_FILTER		(1 << 7)
+
+#define WOL_MODE_COUNT		8
+
+/* L2-L4 network traffic flow types */
+#define	TCP_V4_FLOW	0x01	/* hash or spec (tcp_ip4_spec) */
+#define	UDP_V4_FLOW	0x02	/* hash or spec (udp_ip4_spec) */
+#define	SCTP_V4_FLOW	0x03	/* hash or spec (sctp_ip4_spec) */
+#define	AH_ESP_V4_FLOW	0x04	/* hash only */
+#define	TCP_V6_FLOW	0x05	/* hash or spec (tcp_ip6_spec; nfc only) */
+#define	UDP_V6_FLOW	0x06	/* hash or spec (udp_ip6_spec; nfc only) */
+#define	SCTP_V6_FLOW	0x07	/* hash or spec (sctp_ip6_spec; nfc only) */
+#define	AH_ESP_V6_FLOW	0x08	/* hash only */
+#define	AH_V4_FLOW	0x09	/* hash or spec (ah_ip4_spec) */
+#define	ESP_V4_FLOW	0x0a	/* hash or spec (esp_ip4_spec) */
+#define	AH_V6_FLOW	0x0b	/* hash or spec (ah_ip6_spec; nfc only) */
+#define	ESP_V6_FLOW	0x0c	/* hash or spec (esp_ip6_spec; nfc only) */
+#define	IPV4_USER_FLOW	0x0d	/* spec only (usr_ip4_spec) */
+#define	IP_USER_FLOW	IPV4_USER_FLOW
+#define	IPV6_USER_FLOW	0x0e	/* spec only (usr_ip6_spec; nfc only) */
+#define	IPV4_FLOW	0x10	/* hash only */
+#define	IPV6_FLOW	0x11	/* hash only */
+#define	ETHER_FLOW	0x12	/* spec only (ether_spec) */
+/* Flag to enable additional fields in struct ethtool_rx_flow_spec */
+#define	FLOW_EXT	0x80000000
+#define	FLOW_MAC_EXT	0x40000000
+/* Flag to enable RSS spreading of traffic matching rule (nfc only) */
+#define	FLOW_RSS	0x20000000
+
+/* L3-L4 network traffic flow hash options */
+#define	RXH_L2DA	(1 << 1)
+#define	RXH_VLAN	(1 << 2)
+#define	RXH_L3_PROTO	(1 << 3)
+#define	RXH_IP_SRC	(1 << 4)
+#define	RXH_IP_DST	(1 << 5)
+#define	RXH_L4_B_0_1	(1 << 6) /* src port in case of TCP/UDP/SCTP */
+#define	RXH_L4_B_2_3	(1 << 7) /* dst port in case of TCP/UDP/SCTP */
+#define	RXH_DISCARD	(1 << 31)
+
+#define	RX_CLS_FLOW_DISC	0xffffffffffffffffULL
+#define RX_CLS_FLOW_WAKE	0xfffffffffffffffeULL
+
+/* Special RX classification rule insert location values */
+#define RX_CLS_LOC_SPECIAL	0x80000000	/* flag */
+#define RX_CLS_LOC_ANY		0xffffffff
+#define RX_CLS_LOC_FIRST	0xfffffffe
+#define RX_CLS_LOC_LAST		0xfffffffd
+
+/* EEPROM Standards for plug in modules */
+#define ETH_MODULE_SFF_8079		0x1
+#define ETH_MODULE_SFF_8079_LEN		256
+#define ETH_MODULE_SFF_8472		0x2
+#define ETH_MODULE_SFF_8472_LEN		512
+#define ETH_MODULE_SFF_8636		0x3
+#define ETH_MODULE_SFF_8636_LEN		256
+#define ETH_MODULE_SFF_8436		0x4
+#define ETH_MODULE_SFF_8436_LEN		256
+
+#define ETH_MODULE_SFF_8636_MAX_LEN     640
+#define ETH_MODULE_SFF_8436_MAX_LEN     640
+
+/* Reset flags */
+/* The reset() operation must clear the flags for the components which
+ * were actually reset.  On successful return, the flags indicate the
+ * components which were not reset, either because they do not exist
+ * in the hardware or because they cannot be reset independently.  The
+ * driver must never reset any components that were not requested.
+ */
+enum ethtool_reset_flags {
+	/* These flags represent components dedicated to the interface
+	 * the command is addressed to.  Shift any flag left by
+	 * ETH_RESET_SHARED_SHIFT to reset a shared component of the
+	 * same type.
+	 */
+	ETH_RESET_MGMT		= 1 << 0,	/* Management processor */
+	ETH_RESET_IRQ		= 1 << 1,	/* Interrupt requester */
+	ETH_RESET_DMA		= 1 << 2,	/* DMA engine */
+	ETH_RESET_FILTER	= 1 << 3,	/* Filtering/flow direction */
+	ETH_RESET_OFFLOAD	= 1 << 4,	/* Protocol offload */
+	ETH_RESET_MAC		= 1 << 5,	/* Media access controller */
+	ETH_RESET_PHY		= 1 << 6,	/* Transceiver/PHY */
+	ETH_RESET_RAM		= 1 << 7,	/* RAM shared between
+						 * multiple components */
+	ETH_RESET_AP		= 1 << 8,	/* Application processor */
+
+	ETH_RESET_DEDICATED	= 0x0000ffff,	/* All components dedicated to
+						 * this interface */
+	ETH_RESET_ALL		= 0xffffffff,	/* All components used by this
+						 * interface, even if shared */
+};
+#define ETH_RESET_SHARED_SHIFT	16
+
+
+/**
+ * struct ethtool_link_settings - link control and status
+ *
+ * IMPORTANT, Backward compatibility notice: When implementing new
+ *	user-space tools, please first try %ETHTOOL_GLINKSETTINGS, and
+ *	if it succeeds use %ETHTOOL_SLINKSETTINGS to change link
+ *	settings; do not use %ETHTOOL_SSET if %ETHTOOL_GLINKSETTINGS
+ *	succeeded: stick to %ETHTOOL_GLINKSETTINGS/%SLINKSETTINGS in
+ *	that case.  Conversely, if %ETHTOOL_GLINKSETTINGS fails, use
+ *	%ETHTOOL_GSET to query and %ETHTOOL_SSET to change link
+ *	settings; do not use %ETHTOOL_SLINKSETTINGS if
+ *	%ETHTOOL_GLINKSETTINGS failed: stick to
+ *	%ETHTOOL_GSET/%ETHTOOL_SSET in that case.
+ *
+ * @cmd: Command number = %ETHTOOL_GLINKSETTINGS or %ETHTOOL_SLINKSETTINGS
+ * @speed: Link speed (Mbps)
+ * @duplex: Duplex mode; one of %DUPLEX_*
+ * @port: Physical connector type; one of %PORT_*
+ * @phy_address: MDIO address of PHY (transceiver); 0 or 255 if not
+ *	applicable.  For clause 45 PHYs this is the PRTAD.
+ * @autoneg: Enable/disable autonegotiation and auto-detection;
+ *	either %AUTONEG_DISABLE or %AUTONEG_ENABLE
+ * @mdio_support: Bitmask of %ETH_MDIO_SUPPORTS_* flags for the MDIO
+ *	protocols supported by the interface; 0 if unknown.
+ *	Read-only.
+ * @eth_tp_mdix: Ethernet twisted-pair MDI(-X) status; one of
+ *	%ETH_TP_MDI_*.  If the status is unknown or not applicable, the
+ *	value will be %ETH_TP_MDI_INVALID.  Read-only.
+ * @eth_tp_mdix_ctrl: Ethernet twisted pair MDI(-X) control; one of
+ *	%ETH_TP_MDI_*.  If MDI(-X) control is not implemented, reads
+ *	yield %ETH_TP_MDI_INVALID and writes may be ignored or rejected.
+ *	When written successfully, the link should be renegotiated if
+ *	necessary.
+ * @link_mode_masks_nwords: Number of 32-bit words for each of the
+ *	supported, advertising, lp_advertising link mode bitmaps. For
+ *	%ETHTOOL_GLINKSETTINGS: on entry, number of words passed by user
+ *	(>= 0); on return, if handshake in progress, negative if
+ *	request size unsupported by kernel: absolute value indicates
+ *	kernel expected size and all the other fields but cmd
+ *	are 0; otherwise (handshake completed), strictly positive
+ *	to indicate size used by kernel and cmd field stays
+ *	%ETHTOOL_GLINKSETTINGS, all other fields populated by driver. For
+ *	%ETHTOOL_SLINKSETTINGS: must be valid on entry, ie. a positive
+ *	value returned previously by %ETHTOOL_GLINKSETTINGS, otherwise
+ *	refused. For drivers: ignore this field (use kernel's
+ *	__ETHTOOL_LINK_MODE_MASK_NBITS instead), any change to it will
+ *	be overwritten by kernel.
+ * @supported: Bitmap with each bit meaning given by
+ *	%ethtool_link_mode_bit_indices for the link modes, physical
+ *	connectors and other link features for which the interface
+ *	supports autonegotiation or auto-detection.  Read-only.
+ * @advertising: Bitmap with each bit meaning given by
+ *	%ethtool_link_mode_bit_indices for the link modes, physical
+ *	connectors and other link features that are advertised through
+ *	autonegotiation or enabled for auto-detection.
+ * @lp_advertising: Bitmap with each bit meaning given by
+ *	%ethtool_link_mode_bit_indices for the link modes, and other
+ *	link features that the link partner advertised through
+ *	autonegotiation; 0 if unknown or not applicable.  Read-only.
+ * @transceiver: Used to distinguish different possible PHY types,
+ *	reported consistently by PHYLIB.  Read-only.
+ * @master_slave_cfg: Master/slave port mode.
+ * @master_slave_state: Master/slave port state.
+ * @rate_matching: Rate adaptation performed by the PHY
+ * @reserved: Reserved for future use; see the note on reserved space.
+ * @link_mode_masks: Variable length bitmaps.
+ *
+ * If autonegotiation is disabled, the speed and @duplex represent the
+ * fixed link mode and are writable if the driver supports multiple
+ * link modes.  If it is enabled then they are read-only; if the link
+ * is up they represent the negotiated link mode; if the link is down,
+ * the speed is 0, %SPEED_UNKNOWN or the highest enabled speed and
+ * @duplex is %DUPLEX_UNKNOWN or the best enabled duplex mode.
+ *
+ * Some hardware interfaces may have multiple PHYs and/or physical
+ * connectors fitted or do not allow the driver to detect which are
+ * fitted.  For these interfaces @port and/or @phy_address may be
+ * writable, possibly dependent on @autoneg being %AUTONEG_DISABLE.
+ * Otherwise, attempts to write different values may be ignored or
+ * rejected.
+ *
+ * Deprecated %ethtool_cmd fields transceiver, maxtxpkt and maxrxpkt
+ * are not available in %ethtool_link_settings. These fields will be
+ * always set to zero in %ETHTOOL_GSET reply and %ETHTOOL_SSET will
+ * fail if any of them is set to non-zero value.
+ *
+ * Users should assume that all fields not marked read-only are
+ * writable and subject to validation by the driver.  They should use
+ * %ETHTOOL_GLINKSETTINGS to get the current values before making specific
+ * changes and then applying them with %ETHTOOL_SLINKSETTINGS.
+ *
+ * Drivers that implement %get_link_ksettings and/or
+ * %set_link_ksettings should ignore the @cmd
+ * and @link_mode_masks_nwords fields (any change to them overwritten
+ * by kernel), and rely only on kernel's internal
+ * %__ETHTOOL_LINK_MODE_MASK_NBITS and
+ * %ethtool_link_mode_mask_t. Drivers that implement
+ * %set_link_ksettings() should validate all fields other than @cmd
+ * and @link_mode_masks_nwords that are not described as read-only or
+ * deprecated, and must ignore all fields described as read-only.
+ */
+struct ethtool_link_settings {
+	__u32	cmd;
+	__u32	speed;
+	__u8	duplex;
+	__u8	port;
+	__u8	phy_address;
+	__u8	autoneg;
+	__u8	mdio_support;
+	__u8	eth_tp_mdix;
+	__u8	eth_tp_mdix_ctrl;
+	__s8	link_mode_masks_nwords;
+	__u8	transceiver;
+	__u8	master_slave_cfg;
+	__u8	master_slave_state;
+	__u8	rate_matching;
+	__u32	reserved[7];
+	__u32	link_mode_masks[];
+	/* layout of link_mode_masks fields:
+	 * __u32 map_supported[link_mode_masks_nwords];
+	 * __u32 map_advertising[link_mode_masks_nwords];
+	 * __u32 map_lp_advertising[link_mode_masks_nwords];
+	 */
+};
+#endif /* _LINUX_ETHTOOL_H */
diff --git a/include/linux-private/linux/falloc.h b/include/linux-private/linux/falloc.h
new file mode 100644
index 0000000..ca3904d
--- /dev/null
+++ b/include/linux-private/linux/falloc.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _FALLOC_H_
+#define _FALLOC_H_
+
+#define FALLOC_FL_KEEP_SIZE	0x01 /* default is extend size */
+#define FALLOC_FL_PUNCH_HOLE	0x02 /* de-allocates range */
+#define FALLOC_FL_NO_HIDE_STALE	0x04 /* reserved codepoint */
+
+/*
+ * FALLOC_FL_COLLAPSE_RANGE is used to remove a range of a file
+ * without leaving a hole in the file. The contents of the file beyond
+ * the range being removed is appended to the start offset of the range
+ * being removed (i.e. the hole that was punched is "collapsed"),
+ * resulting in a file layout that looks like the range that was
+ * removed never existed. As such collapsing a range of a file changes
+ * the size of the file, reducing it by the same length of the range
+ * that has been removed by the operation.
+ *
+ * Different filesystems may implement different limitations on the
+ * granularity of the operation. Most will limit operations to
+ * filesystem block size boundaries, but this boundary may be larger or
+ * smaller depending on the filesystem and/or the configuration of the
+ * filesystem or file.
+ *
+ * Attempting to collapse a range that crosses the end of the file is
+ * considered an illegal operation - just use ftruncate(2) if you need
+ * to collapse a range that crosses EOF.
+ */
+#define FALLOC_FL_COLLAPSE_RANGE	0x08
+
+/*
+ * FALLOC_FL_ZERO_RANGE is used to convert a range of file to zeros preferably
+ * without issuing data IO. Blocks should be preallocated for the regions that
+ * span holes in the file, and the entire range is preferable converted to
+ * unwritten extents - even though file system may choose to zero out the
+ * extent or do whatever which will result in reading zeros from the range
+ * while the range remains allocated for the file.
+ *
+ * This can be also used to preallocate blocks past EOF in the same way as
+ * with fallocate. Flag FALLOC_FL_KEEP_SIZE should cause the inode
+ * size to remain the same.
+ */
+#define FALLOC_FL_ZERO_RANGE		0x10
+
+/*
+ * FALLOC_FL_INSERT_RANGE is use to insert space within the file size without
+ * overwriting any existing data. The contents of the file beyond offset are
+ * shifted towards right by len bytes to create a hole.  As such, this
+ * operation will increase the size of the file by len bytes.
+ *
+ * Different filesystems may implement different limitations on the granularity
+ * of the operation. Most will limit operations to filesystem block size
+ * boundaries, but this boundary may be larger or smaller depending on
+ * the filesystem and/or the configuration of the filesystem or file.
+ *
+ * Attempting to insert space using this flag at OR beyond the end of
+ * the file is considered an illegal operation - just use ftruncate(2) or
+ * fallocate(2) with mode 0 for such type of operations.
+ */
+#define FALLOC_FL_INSERT_RANGE		0x20
+
+/*
+ * FALLOC_FL_UNSHARE_RANGE is used to unshare shared blocks within the
+ * file size without overwriting any existing data. The purpose of this
+ * call is to preemptively reallocate any blocks that are subject to
+ * copy-on-write.
+ *
+ * Different filesystems may implement different limitations on the
+ * granularity of the operation. Most will limit operations to filesystem
+ * block size boundaries, but this boundary may be larger or smaller
+ * depending on the filesystem and/or the configuration of the filesystem
+ * or file.
+ *
+ * This flag can only be used with allocate-mode fallocate, which is
+ * to say that it cannot be used with the punch, zero, collapse, or
+ * insert range modes.
+ */
+#define FALLOC_FL_UNSHARE_RANGE		0x40
+
+#endif /* _FALLOC_H_ */
diff --git a/include/linux-private/linux/gen_stats.h b/include/linux-private/linux/gen_stats.h
index 24a861c..852f234 100644
--- a/include/linux-private/linux/gen_stats.h
+++ b/include/linux-private/linux/gen_stats.h
@@ -12,6 +12,8 @@
 	TCA_STATS_APP,
 	TCA_STATS_RATE_EST64,
 	TCA_STATS_PAD,
+	TCA_STATS_BASIC_HW,
+	TCA_STATS_PKT64,
 	__TCA_STATS_MAX,
 };
 #define TCA_STATS_MAX (__TCA_STATS_MAX - 1)
@@ -25,10 +27,6 @@
 	__u64	bytes;
 	__u32	packets;
 };
-struct gnet_stats_basic_packed {
-	__u64	bytes;
-	__u32	packets;
-} __attribute__ ((packed));
 
 /**
  * struct gnet_stats_rate_est - rate estimator
diff --git a/include/linux-private/linux/genetlink.h b/include/linux-private/linux/genetlink.h
index 1317119..e9b8117 100644
--- a/include/linux-private/linux/genetlink.h
+++ b/include/linux-private/linux/genetlink.h
@@ -48,6 +48,7 @@
 	CTRL_CMD_NEWMCAST_GRP,
 	CTRL_CMD_DELMCAST_GRP,
 	CTRL_CMD_GETMCAST_GRP, /* unused */
+	CTRL_CMD_GETPOLICY,
 	__CTRL_CMD_MAX,
 };
 
@@ -62,6 +63,9 @@
 	CTRL_ATTR_MAXATTR,
 	CTRL_ATTR_OPS,
 	CTRL_ATTR_MCAST_GROUPS,
+	CTRL_ATTR_POLICY,
+	CTRL_ATTR_OP_POLICY,
+	CTRL_ATTR_OP,
 	__CTRL_ATTR_MAX,
 };
 
@@ -85,5 +89,15 @@
 
 #define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
 
+enum {
+	CTRL_ATTR_POLICY_UNSPEC,
+	CTRL_ATTR_POLICY_DO,
+	CTRL_ATTR_POLICY_DUMP,
+
+	__CTRL_ATTR_POLICY_DUMP_MAX,
+	CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1
+};
+
+#define CTRL_ATTR_POLICY_MAX (__CTRL_ATTR_POLICY_DUMP_MAX - 1)
 
 #endif /* __LINUX_GENERIC_NETLINK_H */
diff --git a/include/linux-private/linux/hdlc/ioctl.h b/include/linux-private/linux/hdlc/ioctl.h
new file mode 100644
index 0000000..b06341a
--- /dev/null
+++ b/include/linux-private/linux/hdlc/ioctl.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __HDLC_IOCTL_H__
+#define __HDLC_IOCTL_H__
+
+
+#define GENERIC_HDLC_VERSION 4	/* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0	/* Default setting */
+#define CLOCK_EXT	1	/* External TX and RX clock - DTE */
+#define CLOCK_INT	2	/* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT	3	/* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX	4	/* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT	0 /* Default setting */
+#define ENCODING_NRZ		1
+#define ENCODING_NRZI		2
+#define ENCODING_FM_MARK	3
+#define ENCODING_FM_SPACE	4
+#define ENCODING_MANCHESTER	5
+
+
+#define PARITY_DEFAULT		0 /* Default setting */
+#define PARITY_NONE		1 /* No parity */
+#define PARITY_CRC16_PR0	2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1	3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT	4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT	5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT	6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT	7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT		0 /* Default setting */
+#define LMI_NONE		1 /* No LMI, all PVCs are static */
+#define LMI_ANSI		2 /* ANSI Annex D */
+#define LMI_CCITT		3 /* ITU-T Annex A */
+#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+} sync_serial_settings;          /* V.35, V.24, X.21 */
+
+typedef struct {
+	unsigned int clock_rate; /* bits per second */
+	unsigned int clock_type; /* internal, external, TX-internal etc. */
+	unsigned short loopback;
+	unsigned int slot_map;
+} te1_settings;                  /* T1, E1 */
+
+typedef struct {
+	unsigned short encoding;
+	unsigned short parity;
+} raw_hdlc_proto;
+
+typedef struct {
+	unsigned int t391;
+	unsigned int t392;
+	unsigned int n391;
+	unsigned int n392;
+	unsigned int n393;
+	unsigned short lmi;
+	unsigned short dce; /* 1 for DCE (network side) operation */
+} fr_proto;
+
+typedef struct {
+	unsigned int dlci;
+} fr_proto_pvc;          /* for creating/deleting FR PVCs */
+
+typedef struct {
+	unsigned int dlci;
+	char master[IFNAMSIZ];	/* Name of master FRAD device */
+}fr_proto_pvc_info;		/* for returning PVC information only */
+
+typedef struct {
+    unsigned int interval;
+    unsigned int timeout;
+} cisco_proto;
+
+typedef struct {
+	unsigned short dce; /* 1 for DCE (network side) operation */
+	unsigned int modulo; /* modulo (8 = basic / 128 = extended) */
+	unsigned int window; /* frame window size */
+	unsigned int t1; /* timeout t1 */
+	unsigned int t2; /* timeout t2 */
+	unsigned int n2; /* frame retry counter */
+} x25_hdlc_proto;
+
+/* PPP doesn't need any info now - supply length = 0 to ioctl */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __HDLC_IOCTL_H__ */
diff --git a/include/linux-private/linux/if.h b/include/linux-private/linux/if.h
index 495cdd2..b287b2a 100644
--- a/include/linux-private/linux/if.h
+++ b/include/linux-private/linux/if.h
@@ -31,6 +31,7 @@
 #define	IFNAMSIZ	16
 #endif /* __UAPI_DEF_IF_IFNAMSIZ */
 #define	IFALIASZ	256
+#define	ALTIFNAMSIZ	128
 #include <linux/hdlc/ioctl.h>
 
 /* For glibc compatibility. An empty enum does not compile. */
@@ -175,6 +176,7 @@
 enum {
 	IF_LINK_MODE_DEFAULT,
 	IF_LINK_MODE_DORMANT,	/* limit upward transition to dormant */
+	IF_LINK_MODE_TESTING,	/* limit upward transition to testing */
 };
 
 /*
@@ -210,6 +212,7 @@
 		fr_proto		*fr;
 		fr_proto_pvc		*fr_pvc;
 		fr_proto_pvc_info	*fr_pvc_info;
+		x25_hdlc_proto		*x25;
 
 		/* interface settings */
 		sync_serial_settings	*sync;
diff --git a/include/linux-private/linux/if_addr.h b/include/linux-private/linux/if_addr.h
index a924606..d6db3ff 100644
--- a/include/linux-private/linux/if_addr.h
+++ b/include/linux-private/linux/if_addr.h
@@ -33,7 +33,9 @@
 	IFA_CACHEINFO,
 	IFA_MULTICAST,
 	IFA_FLAGS,
-	IFA_RT_PRIORITY,  /* u32, priority/metric for prefix route */
+	IFA_RT_PRIORITY,	/* u32, priority/metric for prefix route */
+	IFA_TARGET_NETNSID,
+	IFA_PROTO,		/* u8, address protocol */
 	__IFA_MAX,
 };
 
@@ -66,4 +68,10 @@
 #define IFA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
 #define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
 
+/* ifa_proto */
+#define IFAPROT_UNSPEC		0
+#define IFAPROT_KERNEL_LO	1	/* loopback */
+#define IFAPROT_KERNEL_RA	2	/* set by kernel from router announcement */
+#define IFAPROT_KERNEL_LL	3	/* link-local set by kernel */
+
 #endif
diff --git a/include/linux-private/linux/if_arp.h b/include/linux-private/linux/if_arp.h
index cd136a6..12d06bb 100644
--- a/include/linux-private/linux/if_arp.h
+++ b/include/linux-private/linux/if_arp.h
@@ -54,6 +54,7 @@
 #define ARPHRD_X25	271		/* CCITT X.25			*/
 #define ARPHRD_HWX25	272		/* Boards with X.25 in firmware	*/
 #define ARPHRD_CAN	280		/* Controller Area Network      */
+#define ARPHRD_MCTP	290
 #define ARPHRD_PPP	512
 #define ARPHRD_CISCO	513		/* Cisco HDLC	 		*/
 #define ARPHRD_HDLC	ARPHRD_CISCO
@@ -114,18 +115,18 @@
 
 /* ARP ioctl request. */
 struct arpreq {
-  struct sockaddr	arp_pa;		/* protocol address		*/
-  struct sockaddr	arp_ha;		/* hardware address		*/
-  int			arp_flags;	/* flags			*/
-  struct sockaddr       arp_netmask;    /* netmask (only for proxy arps) */
-  char			arp_dev[16];
+	struct sockaddr	arp_pa;		/* protocol address		 */
+	struct sockaddr	arp_ha;		/* hardware address		 */
+	int		arp_flags;	/* flags			 */
+	struct sockaddr arp_netmask;    /* netmask (only for proxy arps) */
+	char		arp_dev[IFNAMSIZ];
 };
 
 struct arpreq_old {
-  struct sockaddr	arp_pa;		/* protocol address		*/
-  struct sockaddr	arp_ha;		/* hardware address		*/
-  int			arp_flags;	/* flags			*/
-  struct sockaddr       arp_netmask;    /* netmask (only for proxy arps) */
+	struct sockaddr	arp_pa;		/* protocol address		 */
+	struct sockaddr	arp_ha;		/* hardware address		 */
+	int		arp_flags;	/* flags			 */
+	struct sockaddr	arp_netmask;    /* netmask (only for proxy arps) */
 };
 
 /* ARP Flag values. */
diff --git a/include/linux-private/linux/if_bridge.h b/include/linux-private/linux/if_bridge.h
index e206aa8..e3d55b1 100644
--- a/include/linux-private/linux/if_bridge.h
+++ b/include/linux-private/linux/if_bridge.h
@@ -120,6 +120,9 @@
 	IFLA_BRIDGE_MODE,
 	IFLA_BRIDGE_VLAN_INFO,
 	IFLA_BRIDGE_VLAN_TUNNEL_INFO,
+	IFLA_BRIDGE_MRP,
+	IFLA_BRIDGE_CFM,
+	IFLA_BRIDGE_MST,
 	__IFLA_BRIDGE_MAX,
 };
 #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
@@ -130,6 +133,7 @@
 #define BRIDGE_VLAN_INFO_RANGE_BEGIN	(1<<3) /* VLAN is start of vlan range */
 #define BRIDGE_VLAN_INFO_RANGE_END	(1<<4) /* VLAN is end of vlan range */
 #define BRIDGE_VLAN_INFO_BRENTRY	(1<<5) /* Global bridge VLAN entry */
+#define BRIDGE_VLAN_INFO_ONLY_OPTS	(1<<6) /* Skip create/delete/flags */
 
 struct bridge_vlan_info {
 	__u16 flags;
@@ -156,6 +160,434 @@
 	__u32 pad2;
 };
 
+enum {
+	IFLA_BRIDGE_MRP_UNSPEC,
+	IFLA_BRIDGE_MRP_INSTANCE,
+	IFLA_BRIDGE_MRP_PORT_STATE,
+	IFLA_BRIDGE_MRP_PORT_ROLE,
+	IFLA_BRIDGE_MRP_RING_STATE,
+	IFLA_BRIDGE_MRP_RING_ROLE,
+	IFLA_BRIDGE_MRP_START_TEST,
+	IFLA_BRIDGE_MRP_INFO,
+	IFLA_BRIDGE_MRP_IN_ROLE,
+	IFLA_BRIDGE_MRP_IN_STATE,
+	IFLA_BRIDGE_MRP_START_IN_TEST,
+	__IFLA_BRIDGE_MRP_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_MAX (__IFLA_BRIDGE_MRP_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_INSTANCE_UNSPEC,
+	IFLA_BRIDGE_MRP_INSTANCE_RING_ID,
+	IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX,
+	IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX,
+	IFLA_BRIDGE_MRP_INSTANCE_PRIO,
+	__IFLA_BRIDGE_MRP_INSTANCE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_INSTANCE_MAX (__IFLA_BRIDGE_MRP_INSTANCE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_PORT_STATE_UNSPEC,
+	IFLA_BRIDGE_MRP_PORT_STATE_STATE,
+	__IFLA_BRIDGE_MRP_PORT_STATE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_PORT_STATE_MAX (__IFLA_BRIDGE_MRP_PORT_STATE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_PORT_ROLE_UNSPEC,
+	IFLA_BRIDGE_MRP_PORT_ROLE_ROLE,
+	__IFLA_BRIDGE_MRP_PORT_ROLE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_PORT_ROLE_MAX (__IFLA_BRIDGE_MRP_PORT_ROLE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_RING_STATE_UNSPEC,
+	IFLA_BRIDGE_MRP_RING_STATE_RING_ID,
+	IFLA_BRIDGE_MRP_RING_STATE_STATE,
+	__IFLA_BRIDGE_MRP_RING_STATE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_RING_STATE_MAX (__IFLA_BRIDGE_MRP_RING_STATE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_RING_ROLE_UNSPEC,
+	IFLA_BRIDGE_MRP_RING_ROLE_RING_ID,
+	IFLA_BRIDGE_MRP_RING_ROLE_ROLE,
+	__IFLA_BRIDGE_MRP_RING_ROLE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_RING_ROLE_MAX (__IFLA_BRIDGE_MRP_RING_ROLE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_START_TEST_UNSPEC,
+	IFLA_BRIDGE_MRP_START_TEST_RING_ID,
+	IFLA_BRIDGE_MRP_START_TEST_INTERVAL,
+	IFLA_BRIDGE_MRP_START_TEST_MAX_MISS,
+	IFLA_BRIDGE_MRP_START_TEST_PERIOD,
+	IFLA_BRIDGE_MRP_START_TEST_MONITOR,
+	__IFLA_BRIDGE_MRP_START_TEST_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_START_TEST_MAX (__IFLA_BRIDGE_MRP_START_TEST_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_INFO_UNSPEC,
+	IFLA_BRIDGE_MRP_INFO_RING_ID,
+	IFLA_BRIDGE_MRP_INFO_P_IFINDEX,
+	IFLA_BRIDGE_MRP_INFO_S_IFINDEX,
+	IFLA_BRIDGE_MRP_INFO_PRIO,
+	IFLA_BRIDGE_MRP_INFO_RING_STATE,
+	IFLA_BRIDGE_MRP_INFO_RING_ROLE,
+	IFLA_BRIDGE_MRP_INFO_TEST_INTERVAL,
+	IFLA_BRIDGE_MRP_INFO_TEST_MAX_MISS,
+	IFLA_BRIDGE_MRP_INFO_TEST_MONITOR,
+	IFLA_BRIDGE_MRP_INFO_I_IFINDEX,
+	IFLA_BRIDGE_MRP_INFO_IN_STATE,
+	IFLA_BRIDGE_MRP_INFO_IN_ROLE,
+	IFLA_BRIDGE_MRP_INFO_IN_TEST_INTERVAL,
+	IFLA_BRIDGE_MRP_INFO_IN_TEST_MAX_MISS,
+	__IFLA_BRIDGE_MRP_INFO_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_INFO_MAX (__IFLA_BRIDGE_MRP_INFO_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_IN_STATE_UNSPEC,
+	IFLA_BRIDGE_MRP_IN_STATE_IN_ID,
+	IFLA_BRIDGE_MRP_IN_STATE_STATE,
+	__IFLA_BRIDGE_MRP_IN_STATE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_IN_STATE_MAX (__IFLA_BRIDGE_MRP_IN_STATE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_IN_ROLE_UNSPEC,
+	IFLA_BRIDGE_MRP_IN_ROLE_RING_ID,
+	IFLA_BRIDGE_MRP_IN_ROLE_IN_ID,
+	IFLA_BRIDGE_MRP_IN_ROLE_ROLE,
+	IFLA_BRIDGE_MRP_IN_ROLE_I_IFINDEX,
+	__IFLA_BRIDGE_MRP_IN_ROLE_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_IN_ROLE_MAX (__IFLA_BRIDGE_MRP_IN_ROLE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC,
+	IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID,
+	IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL,
+	IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS,
+	IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD,
+	__IFLA_BRIDGE_MRP_START_IN_TEST_MAX,
+};
+
+#define IFLA_BRIDGE_MRP_START_IN_TEST_MAX (__IFLA_BRIDGE_MRP_START_IN_TEST_MAX - 1)
+
+struct br_mrp_instance {
+	__u32 ring_id;
+	__u32 p_ifindex;
+	__u32 s_ifindex;
+	__u16 prio;
+};
+
+struct br_mrp_ring_state {
+	__u32 ring_id;
+	__u32 ring_state;
+};
+
+struct br_mrp_ring_role {
+	__u32 ring_id;
+	__u32 ring_role;
+};
+
+struct br_mrp_start_test {
+	__u32 ring_id;
+	__u32 interval;
+	__u32 max_miss;
+	__u32 period;
+	__u32 monitor;
+};
+
+struct br_mrp_in_state {
+	__u32 in_state;
+	__u16 in_id;
+};
+
+struct br_mrp_in_role {
+	__u32 ring_id;
+	__u32 in_role;
+	__u32 i_ifindex;
+	__u16 in_id;
+};
+
+struct br_mrp_start_in_test {
+	__u32 interval;
+	__u32 max_miss;
+	__u32 period;
+	__u16 in_id;
+};
+
+enum {
+	IFLA_BRIDGE_CFM_UNSPEC,
+	IFLA_BRIDGE_CFM_MEP_CREATE,
+	IFLA_BRIDGE_CFM_MEP_DELETE,
+	IFLA_BRIDGE_CFM_MEP_CONFIG,
+	IFLA_BRIDGE_CFM_CC_CONFIG,
+	IFLA_BRIDGE_CFM_CC_PEER_MEP_ADD,
+	IFLA_BRIDGE_CFM_CC_PEER_MEP_REMOVE,
+	IFLA_BRIDGE_CFM_CC_RDI,
+	IFLA_BRIDGE_CFM_CC_CCM_TX,
+	IFLA_BRIDGE_CFM_MEP_CREATE_INFO,
+	IFLA_BRIDGE_CFM_MEP_CONFIG_INFO,
+	IFLA_BRIDGE_CFM_CC_CONFIG_INFO,
+	IFLA_BRIDGE_CFM_CC_RDI_INFO,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_INFO,
+	IFLA_BRIDGE_CFM_CC_PEER_MEP_INFO,
+	IFLA_BRIDGE_CFM_MEP_STATUS_INFO,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_INFO,
+	__IFLA_BRIDGE_CFM_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_MAX (__IFLA_BRIDGE_CFM_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_MEP_CREATE_UNSPEC,
+	IFLA_BRIDGE_CFM_MEP_CREATE_INSTANCE,
+	IFLA_BRIDGE_CFM_MEP_CREATE_DOMAIN,
+	IFLA_BRIDGE_CFM_MEP_CREATE_DIRECTION,
+	IFLA_BRIDGE_CFM_MEP_CREATE_IFINDEX,
+	__IFLA_BRIDGE_CFM_MEP_CREATE_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_MEP_CREATE_MAX (__IFLA_BRIDGE_CFM_MEP_CREATE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_MEP_DELETE_UNSPEC,
+	IFLA_BRIDGE_CFM_MEP_DELETE_INSTANCE,
+	__IFLA_BRIDGE_CFM_MEP_DELETE_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_MEP_DELETE_MAX (__IFLA_BRIDGE_CFM_MEP_DELETE_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_MEP_CONFIG_UNSPEC,
+	IFLA_BRIDGE_CFM_MEP_CONFIG_INSTANCE,
+	IFLA_BRIDGE_CFM_MEP_CONFIG_UNICAST_MAC,
+	IFLA_BRIDGE_CFM_MEP_CONFIG_MDLEVEL,
+	IFLA_BRIDGE_CFM_MEP_CONFIG_MEPID,
+	__IFLA_BRIDGE_CFM_MEP_CONFIG_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_MEP_CONFIG_MAX (__IFLA_BRIDGE_CFM_MEP_CONFIG_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_CC_CONFIG_UNSPEC,
+	IFLA_BRIDGE_CFM_CC_CONFIG_INSTANCE,
+	IFLA_BRIDGE_CFM_CC_CONFIG_ENABLE,
+	IFLA_BRIDGE_CFM_CC_CONFIG_EXP_INTERVAL,
+	IFLA_BRIDGE_CFM_CC_CONFIG_EXP_MAID,
+	__IFLA_BRIDGE_CFM_CC_CONFIG_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_CC_CONFIG_MAX (__IFLA_BRIDGE_CFM_CC_CONFIG_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_CC_PEER_MEP_UNSPEC,
+	IFLA_BRIDGE_CFM_CC_PEER_MEP_INSTANCE,
+	IFLA_BRIDGE_CFM_CC_PEER_MEPID,
+	__IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX (__IFLA_BRIDGE_CFM_CC_PEER_MEP_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_CC_RDI_UNSPEC,
+	IFLA_BRIDGE_CFM_CC_RDI_INSTANCE,
+	IFLA_BRIDGE_CFM_CC_RDI_RDI,
+	__IFLA_BRIDGE_CFM_CC_RDI_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_CC_RDI_MAX (__IFLA_BRIDGE_CFM_CC_RDI_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_CC_CCM_TX_UNSPEC,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_INSTANCE,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_DMAC,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_SEQ_NO_UPDATE,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_PERIOD,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_IF_TLV_VALUE,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV,
+	IFLA_BRIDGE_CFM_CC_CCM_TX_PORT_TLV_VALUE,
+	__IFLA_BRIDGE_CFM_CC_CCM_TX_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_CC_CCM_TX_MAX (__IFLA_BRIDGE_CFM_CC_CCM_TX_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_MEP_STATUS_UNSPEC,
+	IFLA_BRIDGE_CFM_MEP_STATUS_INSTANCE,
+	IFLA_BRIDGE_CFM_MEP_STATUS_OPCODE_UNEXP_SEEN,
+	IFLA_BRIDGE_CFM_MEP_STATUS_VERSION_UNEXP_SEEN,
+	IFLA_BRIDGE_CFM_MEP_STATUS_RX_LEVEL_LOW_SEEN,
+	__IFLA_BRIDGE_CFM_MEP_STATUS_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_MEP_STATUS_MAX (__IFLA_BRIDGE_CFM_MEP_STATUS_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_UNSPEC,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_INSTANCE,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_PEER_MEPID,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_CCM_DEFECT,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_RDI,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_PORT_TLV_VALUE,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_IF_TLV_VALUE,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEEN,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_TLV_SEEN,
+	IFLA_BRIDGE_CFM_CC_PEER_STATUS_SEQ_UNEXP_SEEN,
+	__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX,
+};
+
+#define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MST_UNSPEC,
+	IFLA_BRIDGE_MST_ENTRY,
+	__IFLA_BRIDGE_MST_MAX,
+};
+#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1)
+
+enum {
+	IFLA_BRIDGE_MST_ENTRY_UNSPEC,
+	IFLA_BRIDGE_MST_ENTRY_MSTI,
+	IFLA_BRIDGE_MST_ENTRY_STATE,
+	__IFLA_BRIDGE_MST_ENTRY_MAX,
+};
+#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1)
+
+struct bridge_stp_xstats {
+	__u64 transition_blk;
+	__u64 transition_fwd;
+	__u64 rx_bpdu;
+	__u64 tx_bpdu;
+	__u64 rx_tcn;
+	__u64 tx_tcn;
+};
+
+/* Bridge vlan RTM header */
+struct br_vlan_msg {
+	__u8 family;
+	__u8 reserved1;
+	__u16 reserved2;
+	__u32 ifindex;
+};
+
+enum {
+	BRIDGE_VLANDB_DUMP_UNSPEC,
+	BRIDGE_VLANDB_DUMP_FLAGS,
+	__BRIDGE_VLANDB_DUMP_MAX,
+};
+#define BRIDGE_VLANDB_DUMP_MAX (__BRIDGE_VLANDB_DUMP_MAX - 1)
+
+/* flags used in BRIDGE_VLANDB_DUMP_FLAGS attribute to affect dumps */
+#define BRIDGE_VLANDB_DUMPF_STATS	(1 << 0) /* Include stats in the dump */
+#define BRIDGE_VLANDB_DUMPF_GLOBAL	(1 << 1) /* Dump global vlan options only */
+
+/* Bridge vlan RTM attributes
+ * [BRIDGE_VLANDB_ENTRY] = {
+ *     [BRIDGE_VLANDB_ENTRY_INFO]
+ *     ...
+ * }
+ * [BRIDGE_VLANDB_GLOBAL_OPTIONS] = {
+ *     [BRIDGE_VLANDB_GOPTS_ID]
+ *     ...
+ * }
+ */
+enum {
+	BRIDGE_VLANDB_UNSPEC,
+	BRIDGE_VLANDB_ENTRY,
+	BRIDGE_VLANDB_GLOBAL_OPTIONS,
+	__BRIDGE_VLANDB_MAX,
+};
+#define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1)
+
+enum {
+	BRIDGE_VLANDB_ENTRY_UNSPEC,
+	BRIDGE_VLANDB_ENTRY_INFO,
+	BRIDGE_VLANDB_ENTRY_RANGE,
+	BRIDGE_VLANDB_ENTRY_STATE,
+	BRIDGE_VLANDB_ENTRY_TUNNEL_INFO,
+	BRIDGE_VLANDB_ENTRY_STATS,
+	BRIDGE_VLANDB_ENTRY_MCAST_ROUTER,
+	BRIDGE_VLANDB_ENTRY_MCAST_N_GROUPS,
+	BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS,
+	BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS,
+	__BRIDGE_VLANDB_ENTRY_MAX,
+};
+#define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1)
+
+/* [BRIDGE_VLANDB_ENTRY] = {
+ *     [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = {
+ *         [BRIDGE_VLANDB_TINFO_ID]
+ *         ...
+ *     }
+ * }
+ */
+enum {
+	BRIDGE_VLANDB_TINFO_UNSPEC,
+	BRIDGE_VLANDB_TINFO_ID,
+	BRIDGE_VLANDB_TINFO_CMD,
+	__BRIDGE_VLANDB_TINFO_MAX,
+};
+#define BRIDGE_VLANDB_TINFO_MAX (__BRIDGE_VLANDB_TINFO_MAX - 1)
+
+/* [BRIDGE_VLANDB_ENTRY] = {
+ *     [BRIDGE_VLANDB_ENTRY_STATS] = {
+ *         [BRIDGE_VLANDB_STATS_RX_BYTES]
+ *         ...
+ *     }
+ *     ...
+ * }
+ */
+enum {
+	BRIDGE_VLANDB_STATS_UNSPEC,
+	BRIDGE_VLANDB_STATS_RX_BYTES,
+	BRIDGE_VLANDB_STATS_RX_PACKETS,
+	BRIDGE_VLANDB_STATS_TX_BYTES,
+	BRIDGE_VLANDB_STATS_TX_PACKETS,
+	BRIDGE_VLANDB_STATS_PAD,
+	__BRIDGE_VLANDB_STATS_MAX,
+};
+#define BRIDGE_VLANDB_STATS_MAX (__BRIDGE_VLANDB_STATS_MAX - 1)
+
+enum {
+	BRIDGE_VLANDB_GOPTS_UNSPEC,
+	BRIDGE_VLANDB_GOPTS_ID,
+	BRIDGE_VLANDB_GOPTS_RANGE,
+	BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING,
+	BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION,
+	BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION,
+	BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT,
+	BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
+	BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL,
+	BRIDGE_VLANDB_GOPTS_PAD,
+	BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL,
+	BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL,
+	BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL,
+	BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
+	BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
+	BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
+	BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS,
+	BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE,
+	BRIDGE_VLANDB_GOPTS_MSTI,
+	__BRIDGE_VLANDB_GOPTS_MAX
+};
+#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
+
 /* Bridge multicast database attributes
  * [MDBA_MDB] = {
  *     [MDBA_MDB_ENTRY] = {
@@ -198,10 +630,38 @@
 enum {
 	MDBA_MDB_EATTR_UNSPEC,
 	MDBA_MDB_EATTR_TIMER,
+	MDBA_MDB_EATTR_SRC_LIST,
+	MDBA_MDB_EATTR_GROUP_MODE,
+	MDBA_MDB_EATTR_SOURCE,
+	MDBA_MDB_EATTR_RTPROT,
+	MDBA_MDB_EATTR_DST,
+	MDBA_MDB_EATTR_DST_PORT,
+	MDBA_MDB_EATTR_VNI,
+	MDBA_MDB_EATTR_IFINDEX,
+	MDBA_MDB_EATTR_SRC_VNI,
 	__MDBA_MDB_EATTR_MAX
 };
 #define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1)
 
+/* per mdb entry source */
+enum {
+	MDBA_MDB_SRCLIST_UNSPEC,
+	MDBA_MDB_SRCLIST_ENTRY,
+	__MDBA_MDB_SRCLIST_MAX
+};
+#define MDBA_MDB_SRCLIST_MAX (__MDBA_MDB_SRCLIST_MAX - 1)
+
+/* per mdb entry per source attributes
+ * these are embedded in MDBA_MDB_SRCLIST_ENTRY
+ */
+enum {
+	MDBA_MDB_SRCATTR_UNSPEC,
+	MDBA_MDB_SRCATTR_ADDRESS,
+	MDBA_MDB_SRCATTR_TIMER,
+	__MDBA_MDB_SRCATTR_MAX
+};
+#define MDBA_MDB_SRCATTR_MAX (__MDBA_MDB_SRCATTR_MAX - 1)
+
 /* multicast router types */
 enum {
 	MDB_RTR_TYPE_DISABLED,
@@ -222,6 +682,9 @@
 	MDBA_ROUTER_PATTR_UNSPEC,
 	MDBA_ROUTER_PATTR_TIMER,
 	MDBA_ROUTER_PATTR_TYPE,
+	MDBA_ROUTER_PATTR_INET_TIMER,
+	MDBA_ROUTER_PATTR_INET6_TIMER,
+	MDBA_ROUTER_PATTR_VID,
 	__MDBA_ROUTER_PATTR_MAX
 };
 #define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1)
@@ -237,6 +700,9 @@
 #define MDB_PERMANENT 1
 	__u8 state;
 #define MDB_FLAGS_OFFLOAD	(1 << 0)
+#define MDB_FLAGS_FAST_LEAVE	(1 << 1)
+#define MDB_FLAGS_STAR_EXCL	(1 << 2)
+#define MDB_FLAGS_BLOCKED	(1 << 3)
 	__u8 flags;
 	__u16 vid;
 	struct {
@@ -252,16 +718,56 @@
 enum {
 	MDBA_SET_ENTRY_UNSPEC,
 	MDBA_SET_ENTRY,
+	MDBA_SET_ENTRY_ATTRS,
 	__MDBA_SET_ENTRY_MAX,
 };
 #define MDBA_SET_ENTRY_MAX (__MDBA_SET_ENTRY_MAX - 1)
 
+/* [MDBA_SET_ENTRY_ATTRS] = {
+ *    [MDBE_ATTR_xxx]
+ *    ...
+ * }
+ */
+enum {
+	MDBE_ATTR_UNSPEC,
+	MDBE_ATTR_SOURCE,
+	MDBE_ATTR_SRC_LIST,
+	MDBE_ATTR_GROUP_MODE,
+	MDBE_ATTR_RTPROT,
+	MDBE_ATTR_DST,
+	MDBE_ATTR_DST_PORT,
+	MDBE_ATTR_VNI,
+	MDBE_ATTR_IFINDEX,
+	MDBE_ATTR_SRC_VNI,
+	__MDBE_ATTR_MAX,
+};
+#define MDBE_ATTR_MAX (__MDBE_ATTR_MAX - 1)
+
+/* per mdb entry source */
+enum {
+	MDBE_SRC_LIST_UNSPEC,
+	MDBE_SRC_LIST_ENTRY,
+	__MDBE_SRC_LIST_MAX,
+};
+#define MDBE_SRC_LIST_MAX (__MDBE_SRC_LIST_MAX - 1)
+
+/* per mdb entry per source attributes
+ * these are embedded in MDBE_SRC_LIST_ENTRY
+ */
+enum {
+	MDBE_SRCATTR_UNSPEC,
+	MDBE_SRCATTR_ADDRESS,
+	__MDBE_SRCATTR_MAX,
+};
+#define MDBE_SRCATTR_MAX (__MDBE_SRCATTR_MAX - 1)
+
 /* Embedded inside LINK_XSTATS_TYPE_BRIDGE */
 enum {
 	BRIDGE_XSTATS_UNSPEC,
 	BRIDGE_XSTATS_VLAN,
 	BRIDGE_XSTATS_MCAST,
 	BRIDGE_XSTATS_PAD,
+	BRIDGE_XSTATS_STP,
 	__BRIDGE_XSTATS_MAX
 };
 #define BRIDGE_XSTATS_MAX (__BRIDGE_XSTATS_MAX - 1)
@@ -293,4 +799,41 @@
 	__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
 	__u64 mcast_packets[BR_MCAST_DIR_SIZE];
 };
+
+/* bridge boolean options
+ * BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets
+ * BR_BOOLOPT_MCAST_VLAN_SNOOPING - control vlan multicast snooping
+ *
+ * IMPORTANT: if adding a new option do not forget to handle
+ *            it in br_boolopt_toggle/get and bridge sysfs
+ */
+enum br_boolopt_id {
+	BR_BOOLOPT_NO_LL_LEARN,
+	BR_BOOLOPT_MCAST_VLAN_SNOOPING,
+	BR_BOOLOPT_MST_ENABLE,
+	BR_BOOLOPT_MAX
+};
+
+/* struct br_boolopt_multi - change multiple bridge boolean options
+ *
+ * @optval: new option values (bit per option)
+ * @optmask: options to change (bit per option)
+ */
+struct br_boolopt_multi {
+	__u32 optval;
+	__u32 optmask;
+};
+
+enum {
+	BRIDGE_QUERIER_UNSPEC,
+	BRIDGE_QUERIER_IP_ADDRESS,
+	BRIDGE_QUERIER_IP_PORT,
+	BRIDGE_QUERIER_IP_OTHER_TIMER,
+	BRIDGE_QUERIER_PAD,
+	BRIDGE_QUERIER_IPV6_ADDRESS,
+	BRIDGE_QUERIER_IPV6_PORT,
+	BRIDGE_QUERIER_IPV6_OTHER_TIMER,
+	__BRIDGE_QUERIER_MAX
+};
+#define BRIDGE_QUERIER_MAX (__BRIDGE_QUERIER_MAX - 1)
 #endif /* _LINUX_IF_BRIDGE_H */
diff --git a/include/linux-private/linux/if_ether.h b/include/linux-private/linux/if_ether.h
index 8c36f63..a1aff8e 100644
--- a/include/linux-private/linux/if_ether.h
+++ b/include/linux-private/linux/if_ether.h
@@ -86,17 +86,23 @@
 					 * over Ethernet
 					 */
 #define ETH_P_PAE	0x888E		/* Port Access Entity (IEEE 802.1X) */
+#define ETH_P_PROFINET	0x8892		/* PROFINET			*/
+#define ETH_P_REALTEK	0x8899          /* Multiple proprietary protocols */
 #define ETH_P_AOE	0x88A2		/* ATA over Ethernet		*/
+#define ETH_P_ETHERCAT	0x88A4		/* EtherCAT			*/
 #define ETH_P_8021AD	0x88A8          /* 802.1ad Service VLAN		*/
 #define ETH_P_802_EX1	0x88B5		/* 802.1 Local Experimental 1.  */
 #define ETH_P_PREAUTH	0x88C7		/* 802.11 Preauthentication */
 #define ETH_P_TIPC	0x88CA		/* TIPC 			*/
+#define ETH_P_LLDP	0x88CC		/* Link Layer Discovery Protocol */
+#define ETH_P_MRP	0x88E3		/* Media Redundancy Protocol	*/
 #define ETH_P_MACSEC	0x88E5		/* 802.1ae MACsec */
 #define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
 #define ETH_P_MVRP	0x88F5          /* 802.1Q MVRP                  */
 #define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
 #define ETH_P_NCSI	0x88F8		/* NCSI protocol		*/
 #define ETH_P_PRP	0x88FB		/* IEC 62439-3 PRP/HSRv0	*/
+#define ETH_P_CFM	0x8902		/* Connectivity Fault Management */
 #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
 #define ETH_P_IBOE	0x8915		/* Infiniband over Ethernet	*/
 #define ETH_P_TDLS	0x890D          /* TDLS */
@@ -109,10 +115,12 @@
 #define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ3	0x9300		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_EDSA	0xDADA		/* Ethertype DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_8021Q	0xDADB		/* Fake VLAN Header for DSA [ NOT AN OFFICIALLY REGISTERED ID ] */
+#define ETH_P_DSA_A5PSW	0xE001		/* A5PSW Tag Value [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IFE	0xED3E		/* ForCES inter-FE LFB type */
 #define ETH_P_AF_IUCV   0xFBFB		/* IBM af_iucv [ NOT AN OFFICIALLY REGISTERED ID ] */
 
-#define ETH_P_802_3_MIN	0x0600		/* If the value in the ethernet type is less than this value
+#define ETH_P_802_3_MIN	0x0600		/* If the value in the ethernet type is more than this value
 					 * then the frame is Ethernet II. Else it is 802.3 */
 
 /*
@@ -130,6 +138,7 @@
 #define ETH_P_LOCALTALK 0x0009		/* Localtalk pseudo type 	*/
 #define ETH_P_CAN	0x000C		/* CAN: Controller Area Network */
 #define ETH_P_CANFD	0x000D		/* CANFD: CAN flexible data rate*/
+#define ETH_P_CANXL	0x000E		/* CANXL: eXtended frame Length */
 #define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
 #define ETH_P_TR_802_2	0x0011		/* 802.2 frames 		*/
 #define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@cafe.net)	*/
@@ -147,6 +156,9 @@
 #define ETH_P_MAP	0x00F9		/* Qualcomm multiplexing and
 					 * aggregation protocol
 					 */
+#define ETH_P_MCTP	0x00FA		/* Management component transport
+					 * protocol packets
+					 */
 
 /*
  *	This is an Ethernet frame header.
diff --git a/include/linux-private/linux/if_link.h b/include/linux-private/linux/if_link.h
index 47ccf7f..94fb7ef 100644
--- a/include/linux-private/linux/if_link.h
+++ b/include/linux-private/linux/if_link.h
@@ -7,24 +7,23 @@
 
 /* This struct should be in sync with struct rtnl_link_stats64 */
 struct rtnl_link_stats {
-	__u32	rx_packets;		/* total packets received	*/
-	__u32	tx_packets;		/* total packets transmitted	*/
-	__u32	rx_bytes;		/* total bytes received 	*/
-	__u32	tx_bytes;		/* total bytes transmitted	*/
-	__u32	rx_errors;		/* bad packets received		*/
-	__u32	tx_errors;		/* packet transmit problems	*/
-	__u32	rx_dropped;		/* no space in linux buffers	*/
-	__u32	tx_dropped;		/* no space available in linux	*/
-	__u32	multicast;		/* multicast packets received	*/
+	__u32	rx_packets;
+	__u32	tx_packets;
+	__u32	rx_bytes;
+	__u32	tx_bytes;
+	__u32	rx_errors;
+	__u32	tx_errors;
+	__u32	rx_dropped;
+	__u32	tx_dropped;
+	__u32	multicast;
 	__u32	collisions;
-
 	/* detailed rx_errors: */
 	__u32	rx_length_errors;
-	__u32	rx_over_errors;		/* receiver ring buff overflow	*/
-	__u32	rx_crc_errors;		/* recved pkt with crc error	*/
-	__u32	rx_frame_errors;	/* recv'd frame alignment error */
-	__u32	rx_fifo_errors;		/* recv'r fifo overrun		*/
-	__u32	rx_missed_errors;	/* receiver missed packet	*/
+	__u32	rx_over_errors;
+	__u32	rx_crc_errors;
+	__u32	rx_frame_errors;
+	__u32	rx_fifo_errors;
+	__u32	rx_missed_errors;
 
 	/* detailed tx_errors */
 	__u32	tx_aborted_errors;
@@ -37,29 +36,204 @@
 	__u32	rx_compressed;
 	__u32	tx_compressed;
 
-	__u32	rx_nohandler;		/* dropped, no handler found	*/
+	__u32	rx_nohandler;
 };
 
-/* The main device statistics structure */
+/**
+ * struct rtnl_link_stats64 - The main device statistics structure.
+ *
+ * @rx_packets: Number of good packets received by the interface.
+ *   For hardware interfaces counts all good packets received from the device
+ *   by the host, including packets which host had to drop at various stages
+ *   of processing (even in the driver).
+ *
+ * @tx_packets: Number of packets successfully transmitted.
+ *   For hardware interfaces counts packets which host was able to successfully
+ *   hand over to the device, which does not necessarily mean that packets
+ *   had been successfully transmitted out of the device, only that device
+ *   acknowledged it copied them out of host memory.
+ *
+ * @rx_bytes: Number of good received bytes, corresponding to @rx_packets.
+ *
+ *   For IEEE 802.3 devices should count the length of Ethernet Frames
+ *   excluding the FCS.
+ *
+ * @tx_bytes: Number of good transmitted bytes, corresponding to @tx_packets.
+ *
+ *   For IEEE 802.3 devices should count the length of Ethernet Frames
+ *   excluding the FCS.
+ *
+ * @rx_errors: Total number of bad packets received on this network device.
+ *   This counter must include events counted by @rx_length_errors,
+ *   @rx_crc_errors, @rx_frame_errors and other errors not otherwise
+ *   counted.
+ *
+ * @tx_errors: Total number of transmit problems.
+ *   This counter must include events counter by @tx_aborted_errors,
+ *   @tx_carrier_errors, @tx_fifo_errors, @tx_heartbeat_errors,
+ *   @tx_window_errors and other errors not otherwise counted.
+ *
+ * @rx_dropped: Number of packets received but not processed,
+ *   e.g. due to lack of resources or unsupported protocol.
+ *   For hardware interfaces this counter may include packets discarded
+ *   due to L2 address filtering but should not include packets dropped
+ *   by the device due to buffer exhaustion which are counted separately in
+ *   @rx_missed_errors (since procfs folds those two counters together).
+ *
+ * @tx_dropped: Number of packets dropped on their way to transmission,
+ *   e.g. due to lack of resources.
+ *
+ * @multicast: Multicast packets received.
+ *   For hardware interfaces this statistic is commonly calculated
+ *   at the device level (unlike @rx_packets) and therefore may include
+ *   packets which did not reach the host.
+ *
+ *   For IEEE 802.3 devices this counter may be equivalent to:
+ *
+ *    - 30.3.1.1.21 aMulticastFramesReceivedOK
+ *
+ * @collisions: Number of collisions during packet transmissions.
+ *
+ * @rx_length_errors: Number of packets dropped due to invalid length.
+ *   Part of aggregate "frame" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices this counter should be equivalent to a sum
+ *   of the following attributes:
+ *
+ *    - 30.3.1.1.23 aInRangeLengthErrors
+ *    - 30.3.1.1.24 aOutOfRangeLengthField
+ *    - 30.3.1.1.25 aFrameTooLongErrors
+ *
+ * @rx_over_errors: Receiver FIFO overflow event counter.
+ *
+ *   Historically the count of overflow events. Such events may be
+ *   reported in the receive descriptors or via interrupts, and may
+ *   not correspond one-to-one with dropped packets.
+ *
+ *   The recommended interpretation for high speed interfaces is -
+ *   number of packets dropped because they did not fit into buffers
+ *   provided by the host, e.g. packets larger than MTU or next buffer
+ *   in the ring was not available for a scatter transfer.
+ *
+ *   Part of aggregate "frame" errors in `/proc/net/dev`.
+ *
+ *   This statistics was historically used interchangeably with
+ *   @rx_fifo_errors.
+ *
+ *   This statistic corresponds to hardware events and is not commonly used
+ *   on software devices.
+ *
+ * @rx_crc_errors: Number of packets received with a CRC error.
+ *   Part of aggregate "frame" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices this counter must be equivalent to:
+ *
+ *    - 30.3.1.1.6 aFrameCheckSequenceErrors
+ *
+ * @rx_frame_errors: Receiver frame alignment errors.
+ *   Part of aggregate "frame" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices this counter should be equivalent to:
+ *
+ *    - 30.3.1.1.7 aAlignmentErrors
+ *
+ * @rx_fifo_errors: Receiver FIFO error counter.
+ *
+ *   Historically the count of overflow events. Those events may be
+ *   reported in the receive descriptors or via interrupts, and may
+ *   not correspond one-to-one with dropped packets.
+ *
+ *   This statistics was used interchangeably with @rx_over_errors.
+ *   Not recommended for use in drivers for high speed interfaces.
+ *
+ *   This statistic is used on software devices, e.g. to count software
+ *   packet queue overflow (can) or sequencing errors (GRE).
+ *
+ * @rx_missed_errors: Count of packets missed by the host.
+ *   Folded into the "drop" counter in `/proc/net/dev`.
+ *
+ *   Counts number of packets dropped by the device due to lack
+ *   of buffer space. This usually indicates that the host interface
+ *   is slower than the network interface, or host is not keeping up
+ *   with the receive packet rate.
+ *
+ *   This statistic corresponds to hardware events and is not used
+ *   on software devices.
+ *
+ * @tx_aborted_errors:
+ *   Part of aggregate "carrier" errors in `/proc/net/dev`.
+ *   For IEEE 802.3 devices capable of half-duplex operation this counter
+ *   must be equivalent to:
+ *
+ *    - 30.3.1.1.11 aFramesAbortedDueToXSColls
+ *
+ *   High speed interfaces may use this counter as a general device
+ *   discard counter.
+ *
+ * @tx_carrier_errors: Number of frame transmission errors due to loss
+ *   of carrier during transmission.
+ *   Part of aggregate "carrier" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices this counter must be equivalent to:
+ *
+ *    - 30.3.1.1.13 aCarrierSenseErrors
+ *
+ * @tx_fifo_errors: Number of frame transmission errors due to device
+ *   FIFO underrun / underflow. This condition occurs when the device
+ *   begins transmission of a frame but is unable to deliver the
+ *   entire frame to the transmitter in time for transmission.
+ *   Part of aggregate "carrier" errors in `/proc/net/dev`.
+ *
+ * @tx_heartbeat_errors: Number of Heartbeat / SQE Test errors for
+ *   old half-duplex Ethernet.
+ *   Part of aggregate "carrier" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices possibly equivalent to:
+ *
+ *    - 30.3.2.1.4 aSQETestErrors
+ *
+ * @tx_window_errors: Number of frame transmission errors due
+ *   to late collisions (for Ethernet - after the first 64B of transmission).
+ *   Part of aggregate "carrier" errors in `/proc/net/dev`.
+ *
+ *   For IEEE 802.3 devices this counter must be equivalent to:
+ *
+ *    - 30.3.1.1.10 aLateCollisions
+ *
+ * @rx_compressed: Number of correctly received compressed packets.
+ *   This counters is only meaningful for interfaces which support
+ *   packet compression (e.g. CSLIP, PPP).
+ *
+ * @tx_compressed: Number of transmitted compressed packets.
+ *   This counters is only meaningful for interfaces which support
+ *   packet compression (e.g. CSLIP, PPP).
+ *
+ * @rx_nohandler: Number of packets received on the interface
+ *   but dropped by the networking stack because the device is
+ *   not designated to receive packets (e.g. backup link in a bond).
+ *
+ * @rx_otherhost_dropped: Number of packets dropped due to mismatch
+ *   in destination MAC address.
+ */
 struct rtnl_link_stats64 {
-	__u64	rx_packets;		/* total packets received	*/
-	__u64	tx_packets;		/* total packets transmitted	*/
-	__u64	rx_bytes;		/* total bytes received 	*/
-	__u64	tx_bytes;		/* total bytes transmitted	*/
-	__u64	rx_errors;		/* bad packets received		*/
-	__u64	tx_errors;		/* packet transmit problems	*/
-	__u64	rx_dropped;		/* no space in linux buffers	*/
-	__u64	tx_dropped;		/* no space available in linux	*/
-	__u64	multicast;		/* multicast packets received	*/
+	__u64	rx_packets;
+	__u64	tx_packets;
+	__u64	rx_bytes;
+	__u64	tx_bytes;
+	__u64	rx_errors;
+	__u64	tx_errors;
+	__u64	rx_dropped;
+	__u64	tx_dropped;
+	__u64	multicast;
 	__u64	collisions;
 
 	/* detailed rx_errors: */
 	__u64	rx_length_errors;
-	__u64	rx_over_errors;		/* receiver ring buff overflow	*/
-	__u64	rx_crc_errors;		/* recved pkt with crc error	*/
-	__u64	rx_frame_errors;	/* recv'd frame alignment error */
-	__u64	rx_fifo_errors;		/* recv'r fifo overrun		*/
-	__u64	rx_missed_errors;	/* receiver missed packet	*/
+	__u64	rx_over_errors;
+	__u64	rx_crc_errors;
+	__u64	rx_frame_errors;
+	__u64	rx_fifo_errors;
+	__u64	rx_missed_errors;
 
 	/* detailed tx_errors */
 	__u64	tx_aborted_errors;
@@ -71,8 +245,24 @@
 	/* for cslip etc */
 	__u64	rx_compressed;
 	__u64	tx_compressed;
+	__u64	rx_nohandler;
 
-	__u64	rx_nohandler;		/* dropped, no handler found	*/
+	__u64	rx_otherhost_dropped;
+};
+
+/* Subset of link stats useful for in-HW collection. Meaning of the fields is as
+ * for struct rtnl_link_stats64.
+ */
+struct rtnl_hw_stats64 {
+	__u64	rx_packets;
+	__u64	tx_packets;
+	__u64	rx_bytes;
+	__u64	tx_bytes;
+	__u64	rx_errors;
+	__u64	tx_errors;
+	__u64	rx_dropped;
+	__u64	tx_dropped;
+	__u64	multicast;
 };
 
 /* The struct should be in sync with struct ifmap */
@@ -161,17 +351,47 @@
 	IFLA_EVENT,
 	IFLA_NEW_NETNSID,
 	IFLA_IF_NETNSID,
+	IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */
 	IFLA_CARRIER_UP_COUNT,
 	IFLA_CARRIER_DOWN_COUNT,
 	IFLA_NEW_IFINDEX,
 	IFLA_MIN_MTU,
 	IFLA_MAX_MTU,
+	IFLA_PROP_LIST,
+	IFLA_ALT_IFNAME, /* Alternative ifname */
+	IFLA_PERM_ADDRESS,
+	IFLA_PROTO_DOWN_REASON,
+
+	/* device (sysfs) name as parent, used instead
+	 * of IFLA_LINK where there's no parent netdev
+	 */
+	IFLA_PARENT_DEV_NAME,
+	IFLA_PARENT_DEV_BUS_NAME,
+	IFLA_GRO_MAX_SIZE,
+	IFLA_TSO_MAX_SIZE,
+	IFLA_TSO_MAX_SEGS,
+	IFLA_ALLMULTI,		/* Allmulti count: > 0 means acts ALLMULTI */
+
+	IFLA_DEVLINK_PORT,
+
+	IFLA_GSO_IPV4_MAX_SIZE,
+	IFLA_GRO_IPV4_MAX_SIZE,
+
 	__IFLA_MAX
 };
 
 
 #define IFLA_MAX (__IFLA_MAX - 1)
 
+enum {
+	IFLA_PROTO_DOWN_REASON_UNSPEC,
+	IFLA_PROTO_DOWN_REASON_MASK,	/* u32, mask for reason bits */
+	IFLA_PROTO_DOWN_REASON_VALUE,   /* u32, reason bit value */
+
+	__IFLA_PROTO_DOWN_REASON_CNT,
+	IFLA_PROTO_DOWN_REASON_MAX = __IFLA_PROTO_DOWN_REASON_CNT - 1
+};
+
 /* backwards compatibility for userspace */
 #define IFLA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
@@ -224,6 +444,7 @@
 	IFLA_INET6_ICMP6STATS,	/* statistics (icmpv6)		*/
 	IFLA_INET6_TOKEN,	/* device token			*/
 	IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */
+	IFLA_INET6_RA_MTU,	/* mtu carried in the RA message */
 	__IFLA_INET6_MAX
 };
 
@@ -284,6 +505,9 @@
 	IFLA_BR_MCAST_STATS_ENABLED,
 	IFLA_BR_MCAST_IGMP_VERSION,
 	IFLA_BR_MCAST_MLD_VERSION,
+	IFLA_BR_VLAN_STATS_PER_PORT,
+	IFLA_BR_MULTI_BOOLOPT,
+	IFLA_BR_MCAST_QUERIER_STATE,
 	__IFLA_BR_MAX,
 };
 
@@ -335,6 +559,15 @@
 	IFLA_BRPORT_NEIGH_SUPPRESS,
 	IFLA_BRPORT_ISOLATED,
 	IFLA_BRPORT_BACKUP_PORT,
+	IFLA_BRPORT_MRP_RING_OPEN,
+	IFLA_BRPORT_MRP_IN_OPEN,
+	IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT,
+	IFLA_BRPORT_MCAST_EHT_HOSTS_CNT,
+	IFLA_BRPORT_LOCKED,
+	IFLA_BRPORT_MAB,
+	IFLA_BRPORT_MCAST_N_GROUPS,
+	IFLA_BRPORT_MCAST_MAX_GROUPS,
+	IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
 	__IFLA_BRPORT_MAX
 };
 #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -399,6 +632,9 @@
 	IFLA_MACVLAN_MACADDR,
 	IFLA_MACVLAN_MACADDR_DATA,
 	IFLA_MACVLAN_MACADDR_COUNT,
+	IFLA_MACVLAN_BC_QUEUE_LEN,
+	IFLA_MACVLAN_BC_QUEUE_LEN_USED,
+	IFLA_MACVLAN_BC_CUTOFF,
 	__IFLA_MACVLAN_MAX,
 };
 
@@ -420,6 +656,7 @@
 };
 
 #define MACVLAN_FLAG_NOPROMISC	1
+#define MACVLAN_FLAG_NODST	2 /* skip dst macvlan if matching src macvlan */
 
 /* VRF section */
 enum {
@@ -466,6 +703,7 @@
 	IFLA_XFRM_UNSPEC,
 	IFLA_XFRM_LINK,
 	IFLA_XFRM_IF_ID,
+	IFLA_XFRM_COLLECT_METADATA,
 	__IFLA_XFRM_MAX
 };
 
@@ -479,6 +717,14 @@
 	MACSEC_VALIDATE_MAX = __MACSEC_VALIDATE_END - 1,
 };
 
+enum macsec_offload {
+	MACSEC_OFFLOAD_OFF = 0,
+	MACSEC_OFFLOAD_PHY = 1,
+	MACSEC_OFFLOAD_MAC = 2,
+	__MACSEC_OFFLOAD_END,
+	MACSEC_OFFLOAD_MAX = __MACSEC_OFFLOAD_END - 1,
+};
+
 /* IPVLAN section */
 enum {
 	IFLA_IPVLAN_UNSPEC,
@@ -499,7 +745,55 @@
 #define IPVLAN_F_PRIVATE	0x01
 #define IPVLAN_F_VEPA		0x02
 
+/* Tunnel RTM header */
+struct tunnel_msg {
+	__u8 family;
+	__u8 flags;
+	__u16 reserved2;
+	__u32 ifindex;
+};
+
 /* VXLAN section */
+
+/* include statistics in the dump */
+#define TUNNEL_MSG_FLAG_STATS	0x01
+
+#define TUNNEL_MSG_VALID_USER_FLAGS TUNNEL_MSG_FLAG_STATS
+
+/* Embedded inside VXLAN_VNIFILTER_ENTRY_STATS */
+enum {
+	VNIFILTER_ENTRY_STATS_UNSPEC,
+	VNIFILTER_ENTRY_STATS_RX_BYTES,
+	VNIFILTER_ENTRY_STATS_RX_PKTS,
+	VNIFILTER_ENTRY_STATS_RX_DROPS,
+	VNIFILTER_ENTRY_STATS_RX_ERRORS,
+	VNIFILTER_ENTRY_STATS_TX_BYTES,
+	VNIFILTER_ENTRY_STATS_TX_PKTS,
+	VNIFILTER_ENTRY_STATS_TX_DROPS,
+	VNIFILTER_ENTRY_STATS_TX_ERRORS,
+	VNIFILTER_ENTRY_STATS_PAD,
+	__VNIFILTER_ENTRY_STATS_MAX
+};
+#define VNIFILTER_ENTRY_STATS_MAX (__VNIFILTER_ENTRY_STATS_MAX - 1)
+
+enum {
+	VXLAN_VNIFILTER_ENTRY_UNSPEC,
+	VXLAN_VNIFILTER_ENTRY_START,
+	VXLAN_VNIFILTER_ENTRY_END,
+	VXLAN_VNIFILTER_ENTRY_GROUP,
+	VXLAN_VNIFILTER_ENTRY_GROUP6,
+	VXLAN_VNIFILTER_ENTRY_STATS,
+	__VXLAN_VNIFILTER_ENTRY_MAX
+};
+#define VXLAN_VNIFILTER_ENTRY_MAX	(__VXLAN_VNIFILTER_ENTRY_MAX - 1)
+
+enum {
+	VXLAN_VNIFILTER_UNSPEC,
+	VXLAN_VNIFILTER_ENTRY,
+	__VXLAN_VNIFILTER_MAX
+};
+#define VXLAN_VNIFILTER_MAX	(__VXLAN_VNIFILTER_MAX - 1)
+
 enum {
 	IFLA_VXLAN_UNSPEC,
 	IFLA_VXLAN_ID,
@@ -530,6 +824,8 @@
 	IFLA_VXLAN_LABEL,
 	IFLA_VXLAN_GPE,
 	IFLA_VXLAN_TTL_INHERIT,
+	IFLA_VXLAN_DF,
+	IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
 	__IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX	(__IFLA_VXLAN_MAX - 1)
@@ -539,6 +835,14 @@
 	__be16	high;
 };
 
+enum ifla_vxlan_df {
+	VXLAN_DF_UNSET = 0,
+	VXLAN_DF_SET,
+	VXLAN_DF_INHERIT,
+	__VXLAN_DF_END,
+	VXLAN_DF_MAX = __VXLAN_DF_END - 1,
+};
+
 /* GENEVE section */
 enum {
 	IFLA_GENEVE_UNSPEC,
@@ -553,10 +857,33 @@
 	IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
 	IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
 	IFLA_GENEVE_LABEL,
+	IFLA_GENEVE_TTL_INHERIT,
+	IFLA_GENEVE_DF,
+	IFLA_GENEVE_INNER_PROTO_INHERIT,
 	__IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX	(__IFLA_GENEVE_MAX - 1)
 
+enum ifla_geneve_df {
+	GENEVE_DF_UNSET = 0,
+	GENEVE_DF_SET,
+	GENEVE_DF_INHERIT,
+	__GENEVE_DF_END,
+	GENEVE_DF_MAX = __GENEVE_DF_END - 1,
+};
+
+/* Bareudp section  */
+enum {
+	IFLA_BAREUDP_UNSPEC,
+	IFLA_BAREUDP_PORT,
+	IFLA_BAREUDP_ETHERTYPE,
+	IFLA_BAREUDP_SRCPORT_MIN,
+	IFLA_BAREUDP_MULTIPROTO_MODE,
+	__IFLA_BAREUDP_MAX
+};
+
+#define IFLA_BAREUDP_MAX (__IFLA_BAREUDP_MAX - 1)
+
 /* PPP section */
 enum {
 	IFLA_PPP_UNSPEC,
@@ -578,6 +905,8 @@
 	IFLA_GTP_FD1,
 	IFLA_GTP_PDP_HASHSIZE,
 	IFLA_GTP_ROLE,
+	IFLA_GTP_CREATE_SOCKETS,
+	IFLA_GTP_RESTART_COUNT,
 	__IFLA_GTP_MAX,
 };
 #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
@@ -613,6 +942,10 @@
 	IFLA_BOND_AD_USER_PORT_KEY,
 	IFLA_BOND_AD_ACTOR_SYSTEM,
 	IFLA_BOND_TLB_DYNAMIC_LB,
+	IFLA_BOND_PEER_NOTIF_DELAY,
+	IFLA_BOND_AD_LACP_ACTIVE,
+	IFLA_BOND_MISSED_MAX,
+	IFLA_BOND_NS_IP6_TARGET,
 	__IFLA_BOND_MAX,
 };
 
@@ -640,6 +973,7 @@
 	IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
 	IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
 	IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
+	IFLA_BOND_SLAVE_PRIO,
 	__IFLA_BOND_SLAVE_MAX,
 };
 
@@ -671,6 +1005,7 @@
 	IFLA_VF_IB_NODE_GUID,	/* VF Infiniband node GUID */
 	IFLA_VF_IB_PORT_GUID,	/* VF Infiniband port GUID */
 	IFLA_VF_VLAN_LIST,	/* nested list of vlans, option for QinQ */
+	IFLA_VF_BROADCAST,	/* VF broadcast */
 	__IFLA_VF_MAX,
 };
 
@@ -681,6 +1016,10 @@
 	__u8 mac[32]; /* MAX_ADDR_LEN */
 };
 
+struct ifla_vf_broadcast {
+	__u8 broadcast[32];
+};
+
 struct ifla_vf_vlan {
 	__u32 vf;
 	__u32 vlan; /* 0 - 4095, 0 disables VLAN filter */
@@ -852,7 +1191,14 @@
 #define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
 
 
-/* HSR section */
+/* HSR/PRP section, both uses same interface */
+
+/* Different redundancy protocols for hsr device */
+enum {
+	HSR_PROTOCOL_HSR,
+	HSR_PROTOCOL_PRP,
+	HSR_PROTOCOL_MAX,
+};
 
 enum {
 	IFLA_HSR_UNSPEC,
@@ -862,6 +1208,9 @@
 	IFLA_HSR_SUPERVISION_ADDR,	/* Supervision frame multicast addr */
 	IFLA_HSR_SEQ_NR,
 	IFLA_HSR_VERSION,		/* HSR version */
+	IFLA_HSR_PROTOCOL,		/* Indicate different protocol than
+					 * HSR. For example PRP.
+					 */
 	__IFLA_HSR_MAX,
 };
 
@@ -894,6 +1243,17 @@
 
 #define IFLA_STATS_FILTER_BIT(ATTR)	(1 << (ATTR - 1))
 
+enum {
+	IFLA_STATS_GETSET_UNSPEC,
+	IFLA_STATS_GET_FILTERS, /* Nest of IFLA_STATS_LINK_xxx, each a u32 with
+				 * a filter mask for the corresponding group.
+				 */
+	IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS, /* 0 or 1 as u8 */
+	__IFLA_STATS_GETSET_MAX,
+};
+
+#define IFLA_STATS_GETSET_MAX (__IFLA_STATS_GETSET_MAX - 1)
+
 /* These are embedded into IFLA_STATS_LINK_XSTATS:
  * [IFLA_STATS_LINK_XSTATS]
  * -> [LINK_XSTATS_TYPE_xxx]
@@ -902,6 +1262,7 @@
 enum {
 	LINK_XSTATS_TYPE_UNSPEC,
 	LINK_XSTATS_TYPE_BRIDGE,
+	LINK_XSTATS_TYPE_BOND,
 	__LINK_XSTATS_TYPE_MAX
 };
 #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
@@ -910,21 +1271,33 @@
 enum {
 	IFLA_OFFLOAD_XSTATS_UNSPEC,
 	IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */
+	IFLA_OFFLOAD_XSTATS_HW_S_INFO,	/* HW stats info. A nest */
+	IFLA_OFFLOAD_XSTATS_L3_STATS,	/* struct rtnl_hw_stats64 */
 	__IFLA_OFFLOAD_XSTATS_MAX
 };
 #define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1)
 
+enum {
+	IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC,
+	IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST,		/* u8 */
+	IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED,		/* u8 */
+	__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX,
+};
+#define IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX \
+	(__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX - 1)
+
 /* XDP section */
 
 #define XDP_FLAGS_UPDATE_IF_NOEXIST	(1U << 0)
 #define XDP_FLAGS_SKB_MODE		(1U << 1)
 #define XDP_FLAGS_DRV_MODE		(1U << 2)
 #define XDP_FLAGS_HW_MODE		(1U << 3)
+#define XDP_FLAGS_REPLACE		(1U << 4)
 #define XDP_FLAGS_MODES			(XDP_FLAGS_SKB_MODE | \
 					 XDP_FLAGS_DRV_MODE | \
 					 XDP_FLAGS_HW_MODE)
 #define XDP_FLAGS_MASK			(XDP_FLAGS_UPDATE_IF_NOEXIST | \
-					 XDP_FLAGS_MODES)
+					 XDP_FLAGS_MODES | XDP_FLAGS_REPLACE)
 
 /* These are stored into IFLA_XDP_ATTACHED on dump. */
 enum {
@@ -944,6 +1317,7 @@
 	IFLA_XDP_DRV_PROG_ID,
 	IFLA_XDP_SKB_PROG_ID,
 	IFLA_XDP_HW_PROG_ID,
+	IFLA_XDP_EXPECTED_FD,
 	__IFLA_XDP_MAX,
 };
 
@@ -983,6 +1357,8 @@
 #define RMNET_FLAGS_INGRESS_MAP_COMMANDS          (1U << 1)
 #define RMNET_FLAGS_INGRESS_MAP_CKSUMV4           (1U << 2)
 #define RMNET_FLAGS_EGRESS_MAP_CKSUMV4            (1U << 3)
+#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5           (1U << 4)
+#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5            (1U << 5)
 
 enum {
 	IFLA_RMNET_UNSPEC,
@@ -998,4 +1374,24 @@
 	__u32	mask;
 };
 
+/* MCTP section */
+
+enum {
+	IFLA_MCTP_UNSPEC,
+	IFLA_MCTP_NET,
+	__IFLA_MCTP_MAX,
+};
+
+#define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1)
+
+/* DSA section */
+
+enum {
+	IFLA_DSA_UNSPEC,
+	IFLA_DSA_MASTER,
+	__IFLA_DSA_MAX,
+};
+
+#define IFLA_DSA_MAX	(__IFLA_DSA_MAX - 1)
+
 #endif /* _LINUX_IF_LINK_H */
diff --git a/include/linux-private/linux/if_macsec.h b/include/linux-private/linux/if_macsec.h
index 7743993..6edfea0 100644
--- a/include/linux-private/linux/if_macsec.h
+++ b/include/linux-private/linux/if_macsec.h
@@ -22,9 +22,13 @@
 
 #define MACSEC_KEYID_LEN 16
 
-/* cipher IDs as per IEEE802.1AEbn-2011 */
+#define MACSEC_SALT_LEN 12
+
+/* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */
 #define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL
 #define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL
+#define MACSEC_CIPHER_ID_GCM_AES_XPN_128 0x0080C20001000003ULL
+#define MACSEC_CIPHER_ID_GCM_AES_XPN_256 0x0080C20001000004ULL
 
 /* deprecated cipher ID for GCM-AES-128 */
 #define MACSEC_DEFAULT_CIPHER_ID     0x0080020001000001ULL
@@ -45,6 +49,7 @@
 	MACSEC_ATTR_RXSC_LIST,   /* dump, nested, macsec_rxsc_attrs for each RXSC */
 	MACSEC_ATTR_TXSC_STATS,  /* dump, nested, macsec_txsc_stats_attr */
 	MACSEC_ATTR_SECY_STATS,  /* dump, nested, macsec_secy_stats_attr */
+	MACSEC_ATTR_OFFLOAD,     /* config, nested, macsec_offload_attrs */
 	__MACSEC_ATTR_END,
 	NUM_MACSEC_ATTR = __MACSEC_ATTR_END,
 	MACSEC_ATTR_MAX = __MACSEC_ATTR_END - 1,
@@ -87,16 +92,27 @@
 	MACSEC_SA_ATTR_UNSPEC,
 	MACSEC_SA_ATTR_AN,     /* config/dump, u8 0..3 */
 	MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */
-	MACSEC_SA_ATTR_PN,     /* config/dump, u32 */
+	MACSEC_SA_ATTR_PN,     /* config/dump, u32/u64 (u64 if XPN) */
 	MACSEC_SA_ATTR_KEY,    /* config, data */
 	MACSEC_SA_ATTR_KEYID,  /* config/dump, 128-bit */
 	MACSEC_SA_ATTR_STATS,  /* dump, nested, macsec_sa_stats_attr */
 	MACSEC_SA_ATTR_PAD,
+	MACSEC_SA_ATTR_SSCI,   /* config/dump, u32 - XPN only */
+	MACSEC_SA_ATTR_SALT,   /* config, 96-bit - XPN only */
 	__MACSEC_SA_ATTR_END,
 	NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END,
 	MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1,
 };
 
+enum macsec_offload_attrs {
+	MACSEC_OFFLOAD_ATTR_UNSPEC,
+	MACSEC_OFFLOAD_ATTR_TYPE, /* config/dump, u8 0..2 */
+	MACSEC_OFFLOAD_ATTR_PAD,
+	__MACSEC_OFFLOAD_ATTR_END,
+	NUM_MACSEC_OFFLOAD_ATTR = __MACSEC_OFFLOAD_ATTR_END,
+	MACSEC_OFFLOAD_ATTR_MAX = __MACSEC_OFFLOAD_ATTR_END - 1,
+};
+
 enum macsec_nl_commands {
 	MACSEC_CMD_GET_TXSC,
 	MACSEC_CMD_ADD_RXSC,
@@ -108,6 +124,7 @@
 	MACSEC_CMD_ADD_RXSA,
 	MACSEC_CMD_DEL_RXSA,
 	MACSEC_CMD_UPD_RXSA,
+	MACSEC_CMD_UPD_OFFLOAD,
 };
 
 /* u64 per-RXSC stats */
diff --git a/include/linux-private/linux/if_packet.h b/include/linux-private/linux/if_packet.h
new file mode 100644
index 0000000..9efc423
--- /dev/null
+++ b/include/linux-private/linux/if_packet.h
@@ -0,0 +1,319 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_PACKET_H
+#define __LINUX_IF_PACKET_H
+
+#include <asm/byteorder.h>
+#include <linux/types.h>
+
+struct sockaddr_pkt {
+	unsigned short spkt_family;
+	unsigned char spkt_device[14];
+	__be16 spkt_protocol;
+};
+
+struct sockaddr_ll {
+	unsigned short	sll_family;
+	__be16		sll_protocol;
+	int		sll_ifindex;
+	unsigned short	sll_hatype;
+	unsigned char	sll_pkttype;
+	unsigned char	sll_halen;
+	unsigned char	sll_addr[8];
+};
+
+/* Packet types */
+
+#define PACKET_HOST		0		/* To us		*/
+#define PACKET_BROADCAST	1		/* To all		*/
+#define PACKET_MULTICAST	2		/* To group		*/
+#define PACKET_OTHERHOST	3		/* To someone else 	*/
+#define PACKET_OUTGOING		4		/* Outgoing of any type */
+#define PACKET_LOOPBACK		5		/* MC/BRD frame looped back */
+#define PACKET_USER		6		/* To user space	*/
+#define PACKET_KERNEL		7		/* To kernel space	*/
+/* Unused, PACKET_FASTROUTE and PACKET_LOOPBACK are invisible to user space */
+#define PACKET_FASTROUTE	6		/* Fastrouted frame	*/
+
+/* Packet socket options */
+
+#define PACKET_ADD_MEMBERSHIP		1
+#define PACKET_DROP_MEMBERSHIP		2
+#define PACKET_RECV_OUTPUT		3
+/* Value 4 is still used by obsolete turbo-packet. */
+#define PACKET_RX_RING			5
+#define PACKET_STATISTICS		6
+#define PACKET_COPY_THRESH		7
+#define PACKET_AUXDATA			8
+#define PACKET_ORIGDEV			9
+#define PACKET_VERSION			10
+#define PACKET_HDRLEN			11
+#define PACKET_RESERVE			12
+#define PACKET_TX_RING			13
+#define PACKET_LOSS			14
+#define PACKET_VNET_HDR			15
+#define PACKET_TX_TIMESTAMP		16
+#define PACKET_TIMESTAMP		17
+#define PACKET_FANOUT			18
+#define PACKET_TX_HAS_OFF		19
+#define PACKET_QDISC_BYPASS		20
+#define PACKET_ROLLOVER_STATS		21
+#define PACKET_FANOUT_DATA		22
+#define PACKET_IGNORE_OUTGOING		23
+#define PACKET_VNET_HDR_SZ		24
+
+#define PACKET_FANOUT_HASH		0
+#define PACKET_FANOUT_LB		1
+#define PACKET_FANOUT_CPU		2
+#define PACKET_FANOUT_ROLLOVER		3
+#define PACKET_FANOUT_RND		4
+#define PACKET_FANOUT_QM		5
+#define PACKET_FANOUT_CBPF		6
+#define PACKET_FANOUT_EBPF		7
+#define PACKET_FANOUT_FLAG_ROLLOVER	0x1000
+#define PACKET_FANOUT_FLAG_UNIQUEID	0x2000
+#define PACKET_FANOUT_FLAG_IGNORE_OUTGOING     0x4000
+#define PACKET_FANOUT_FLAG_DEFRAG	0x8000
+
+struct tpacket_stats {
+	unsigned int	tp_packets;
+	unsigned int	tp_drops;
+};
+
+struct tpacket_stats_v3 {
+	unsigned int	tp_packets;
+	unsigned int	tp_drops;
+	unsigned int	tp_freeze_q_cnt;
+};
+
+struct tpacket_rollover_stats {
+	__aligned_u64	tp_all;
+	__aligned_u64	tp_huge;
+	__aligned_u64	tp_failed;
+};
+
+union tpacket_stats_u {
+	struct tpacket_stats stats1;
+	struct tpacket_stats_v3 stats3;
+};
+
+struct tpacket_auxdata {
+	__u32		tp_status;
+	__u32		tp_len;
+	__u32		tp_snaplen;
+	__u16		tp_mac;
+	__u16		tp_net;
+	__u16		tp_vlan_tci;
+	__u16		tp_vlan_tpid;
+};
+
+/* Rx ring - header status */
+#define TP_STATUS_KERNEL		      0
+#define TP_STATUS_USER			(1 << 0)
+#define TP_STATUS_COPY			(1 << 1)
+#define TP_STATUS_LOSING		(1 << 2)
+#define TP_STATUS_CSUMNOTREADY		(1 << 3)
+#define TP_STATUS_VLAN_VALID		(1 << 4) /* auxdata has valid tp_vlan_tci */
+#define TP_STATUS_BLK_TMO		(1 << 5)
+#define TP_STATUS_VLAN_TPID_VALID	(1 << 6) /* auxdata has valid tp_vlan_tpid */
+#define TP_STATUS_CSUM_VALID		(1 << 7)
+#define TP_STATUS_GSO_TCP		(1 << 8)
+
+/* Tx ring - header status */
+#define TP_STATUS_AVAILABLE	      0
+#define TP_STATUS_SEND_REQUEST	(1 << 0)
+#define TP_STATUS_SENDING	(1 << 1)
+#define TP_STATUS_WRONG_FORMAT	(1 << 2)
+
+/* Rx and Tx ring - header status */
+#define TP_STATUS_TS_SOFTWARE		(1 << 29)
+#define TP_STATUS_TS_SYS_HARDWARE	(1 << 30) /* deprecated, never set */
+#define TP_STATUS_TS_RAW_HARDWARE	(1U << 31)
+
+/* Rx ring - feature request bits */
+#define TP_FT_REQ_FILL_RXHASH	0x1
+
+struct tpacket_hdr {
+	unsigned long	tp_status;
+	unsigned int	tp_len;
+	unsigned int	tp_snaplen;
+	unsigned short	tp_mac;
+	unsigned short	tp_net;
+	unsigned int	tp_sec;
+	unsigned int	tp_usec;
+};
+
+#define TPACKET_ALIGNMENT	16
+#define TPACKET_ALIGN(x)	(((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1))
+#define TPACKET_HDRLEN		(TPACKET_ALIGN(sizeof(struct tpacket_hdr)) + sizeof(struct sockaddr_ll))
+
+struct tpacket2_hdr {
+	__u32		tp_status;
+	__u32		tp_len;
+	__u32		tp_snaplen;
+	__u16		tp_mac;
+	__u16		tp_net;
+	__u32		tp_sec;
+	__u32		tp_nsec;
+	__u16		tp_vlan_tci;
+	__u16		tp_vlan_tpid;
+	__u8		tp_padding[4];
+};
+
+struct tpacket_hdr_variant1 {
+	__u32	tp_rxhash;
+	__u32	tp_vlan_tci;
+	__u16	tp_vlan_tpid;
+	__u16	tp_padding;
+};
+
+struct tpacket3_hdr {
+	__u32		tp_next_offset;
+	__u32		tp_sec;
+	__u32		tp_nsec;
+	__u32		tp_snaplen;
+	__u32		tp_len;
+	__u32		tp_status;
+	__u16		tp_mac;
+	__u16		tp_net;
+	/* pkt_hdr variants */
+	union {
+		struct tpacket_hdr_variant1 hv1;
+	};
+	__u8		tp_padding[8];
+};
+
+struct tpacket_bd_ts {
+	unsigned int ts_sec;
+	union {
+		unsigned int ts_usec;
+		unsigned int ts_nsec;
+	};
+};
+
+struct tpacket_hdr_v1 {
+	__u32	block_status;
+	__u32	num_pkts;
+	__u32	offset_to_first_pkt;
+
+	/* Number of valid bytes (including padding)
+	 * blk_len <= tp_block_size
+	 */
+	__u32	blk_len;
+
+	/*
+	 * Quite a few uses of sequence number:
+	 * 1. Make sure cache flush etc worked.
+	 *    Well, one can argue - why not use the increasing ts below?
+	 *    But look at 2. below first.
+	 * 2. When you pass around blocks to other user space decoders,
+	 *    you can see which blk[s] is[are] outstanding etc.
+	 * 3. Validate kernel code.
+	 */
+	__aligned_u64	seq_num;
+
+	/*
+	 * ts_last_pkt:
+	 *
+	 * Case 1.	Block has 'N'(N >=1) packets and TMO'd(timed out)
+	 *		ts_last_pkt == 'time-stamp of last packet' and NOT the
+	 *		time when the timer fired and the block was closed.
+	 *		By providing the ts of the last packet we can absolutely
+	 *		guarantee that time-stamp wise, the first packet in the
+	 *		next block will never precede the last packet of the
+	 *		previous block.
+	 * Case 2.	Block has zero packets and TMO'd
+	 *		ts_last_pkt = time when the timer fired and the block
+	 *		was closed.
+	 * Case 3.	Block has 'N' packets and NO TMO.
+	 *		ts_last_pkt = time-stamp of the last pkt in the block.
+	 *
+	 * ts_first_pkt:
+	 *		Is always the time-stamp when the block was opened.
+	 *		Case a)	ZERO packets
+	 *			No packets to deal with but atleast you know the
+	 *			time-interval of this block.
+	 *		Case b) Non-zero packets
+	 *			Use the ts of the first packet in the block.
+	 *
+	 */
+	struct tpacket_bd_ts	ts_first_pkt, ts_last_pkt;
+};
+
+union tpacket_bd_header_u {
+	struct tpacket_hdr_v1 bh1;
+};
+
+struct tpacket_block_desc {
+	__u32 version;
+	__u32 offset_to_priv;
+	union tpacket_bd_header_u hdr;
+};
+
+#define TPACKET2_HDRLEN		(TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
+#define TPACKET3_HDRLEN		(TPACKET_ALIGN(sizeof(struct tpacket3_hdr)) + sizeof(struct sockaddr_ll))
+
+enum tpacket_versions {
+	TPACKET_V1,
+	TPACKET_V2,
+	TPACKET_V3
+};
+
+/*
+   Frame structure:
+
+   - Start. Frame must be aligned to TPACKET_ALIGNMENT=16
+   - struct tpacket_hdr
+   - pad to TPACKET_ALIGNMENT=16
+   - struct sockaddr_ll
+   - Gap, chosen so that packet data (Start+tp_net) alignes to TPACKET_ALIGNMENT=16
+   - Start+tp_mac: [ Optional MAC header ]
+   - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
+   - Pad to align to TPACKET_ALIGNMENT=16
+ */
+
+struct tpacket_req {
+	unsigned int	tp_block_size;	/* Minimal size of contiguous block */
+	unsigned int	tp_block_nr;	/* Number of blocks */
+	unsigned int	tp_frame_size;	/* Size of frame */
+	unsigned int	tp_frame_nr;	/* Total number of frames */
+};
+
+struct tpacket_req3 {
+	unsigned int	tp_block_size;	/* Minimal size of contiguous block */
+	unsigned int	tp_block_nr;	/* Number of blocks */
+	unsigned int	tp_frame_size;	/* Size of frame */
+	unsigned int	tp_frame_nr;	/* Total number of frames */
+	unsigned int	tp_retire_blk_tov; /* timeout in msecs */
+	unsigned int	tp_sizeof_priv; /* offset to private data area */
+	unsigned int	tp_feature_req_word;
+};
+
+union tpacket_req_u {
+	struct tpacket_req	req;
+	struct tpacket_req3	req3;
+};
+
+struct packet_mreq {
+	int		mr_ifindex;
+	unsigned short	mr_type;
+	unsigned short	mr_alen;
+	unsigned char	mr_address[8];
+};
+
+struct fanout_args {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	__u16		id;
+	__u16		type_flags;
+#else
+	__u16		type_flags;
+	__u16		id;
+#endif
+	__u32		max_num_members;
+};
+
+#define PACKET_MR_MULTICAST	0
+#define PACKET_MR_PROMISC	1
+#define PACKET_MR_ALLMULTI	2
+#define PACKET_MR_UNICAST	3
+
+#endif
diff --git a/include/linux-private/linux/if_tunnel.h b/include/linux-private/linux/if_tunnel.h
index ecdc766..edaea41 100644
--- a/include/linux-private/linux/if_tunnel.h
+++ b/include/linux-private/linux/if_tunnel.h
@@ -160,4 +160,26 @@
 };
 
 #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
+
+#define TUNNEL_CSUM		__cpu_to_be16(0x01)
+#define TUNNEL_ROUTING		__cpu_to_be16(0x02)
+#define TUNNEL_KEY		__cpu_to_be16(0x04)
+#define TUNNEL_SEQ		__cpu_to_be16(0x08)
+#define TUNNEL_STRICT		__cpu_to_be16(0x10)
+#define TUNNEL_REC		__cpu_to_be16(0x20)
+#define TUNNEL_VERSION		__cpu_to_be16(0x40)
+#define TUNNEL_NO_KEY		__cpu_to_be16(0x80)
+#define TUNNEL_DONT_FRAGMENT    __cpu_to_be16(0x0100)
+#define TUNNEL_OAM		__cpu_to_be16(0x0200)
+#define TUNNEL_CRIT_OPT		__cpu_to_be16(0x0400)
+#define TUNNEL_GENEVE_OPT	__cpu_to_be16(0x0800)
+#define TUNNEL_VXLAN_OPT	__cpu_to_be16(0x1000)
+#define TUNNEL_NOCACHE		__cpu_to_be16(0x2000)
+#define TUNNEL_ERSPAN_OPT	__cpu_to_be16(0x4000)
+#define TUNNEL_GTP_OPT		__cpu_to_be16(0x8000)
+
+#define TUNNEL_OPTIONS_PRESENT \
+		(TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | \
+		TUNNEL_GTP_OPT)
+
 #endif /* _IF_TUNNEL_H_ */
diff --git a/include/linux-private/linux/in.h b/include/linux-private/linux/in.h
index a4f143b..7bdd684 100644
--- a/include/linux-private/linux/in.h
+++ b/include/linux-private/linux/in.h
@@ -20,6 +20,7 @@
 #define _LINUX_IN_H
 
 #include <linux/types.h>
+#include <linux/stddef.h>
 #include <linux/libc-compat.h>
 #include <linux/socket.h>
 
@@ -68,14 +69,20 @@
 #define IPPROTO_PIM		IPPROTO_PIM
   IPPROTO_COMP = 108,		/* Compression Header Protocol		*/
 #define IPPROTO_COMP		IPPROTO_COMP
+  IPPROTO_L2TP = 115,		/* Layer 2 Tunnelling Protocol		*/
+#define IPPROTO_L2TP		IPPROTO_L2TP
   IPPROTO_SCTP = 132,		/* Stream Control Transport Protocol	*/
 #define IPPROTO_SCTP		IPPROTO_SCTP
   IPPROTO_UDPLITE = 136,	/* UDP-Lite (RFC 3828)			*/
 #define IPPROTO_UDPLITE		IPPROTO_UDPLITE
   IPPROTO_MPLS = 137,		/* MPLS in IP (RFC 4023)		*/
 #define IPPROTO_MPLS		IPPROTO_MPLS
+  IPPROTO_ETHERNET = 143,	/* Ethernet-within-IPv6 Encapsulation	*/
+#define IPPROTO_ETHERNET	IPPROTO_ETHERNET
   IPPROTO_RAW = 255,		/* Raw IP packets			*/
 #define IPPROTO_RAW		IPPROTO_RAW
+  IPPROTO_MPTCP = 262,		/* Multipath TCP connection		*/
+#define IPPROTO_MPTCP		IPPROTO_MPTCP
   IPPROTO_MAX
 };
 #endif
@@ -119,6 +126,7 @@
 #define IP_CHECKSUM	23
 #define IP_BIND_ADDRESS_NO_PORT	24
 #define IP_RECVFRAGSIZE	25
+#define IP_RECVERR_RFC4884	26
 
 /* IP_MTU_DISCOVER values */
 #define IP_PMTUDISC_DONT		0	/* Never send DF frames */
@@ -130,7 +138,7 @@
  * this socket to prevent accepting spoofed ones.
  */
 #define IP_PMTUDISC_INTERFACE		4
-/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get
+/* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get
  * fragmented if they exeed the interface mtu
  */
 #define IP_PMTUDISC_OMIT		5
@@ -154,6 +162,8 @@
 #define MCAST_MSFILTER			48
 #define IP_MULTICAST_ALL		49
 #define IP_UNICAST_IF			50
+#define IP_LOCAL_PORT_RANGE		51
+#define IP_PROTOCOL			52
 
 #define MCAST_EXCLUDE	0
 #define MCAST_INCLUDE	1
@@ -187,7 +197,10 @@
 	__be32		imsf_interface;
 	__u32		imsf_fmode;
 	__u32		imsf_numsrc;
-	__be32		imsf_slist[1];
+	union {
+		__be32		imsf_slist[1];
+		__DECLARE_FLEX_ARRAY(__be32, imsf_slist_flex);
+	};
 };
 
 #define IP_MSFILTER_SIZE(numsrc) \
@@ -206,11 +219,22 @@
 };
 
 struct group_filter {
-	__u32				 gf_interface;	/* interface index */
-	struct __kernel_sockaddr_storage gf_group;	/* multicast address */
-	__u32				 gf_fmode;	/* filter mode */
-	__u32				 gf_numsrc;	/* number of sources */
-	struct __kernel_sockaddr_storage gf_slist[1];	/* interface index */
+	union {
+		struct {
+			__u32				 gf_interface_aux; /* interface index */
+			struct __kernel_sockaddr_storage gf_group_aux;	   /* multicast address */
+			__u32				 gf_fmode_aux;	   /* filter mode */
+			__u32				 gf_numsrc_aux;	   /* number of sources */
+			struct __kernel_sockaddr_storage gf_slist[1];	   /* interface index */
+		};
+		struct {
+			__u32				 gf_interface;	  /* interface index */
+			struct __kernel_sockaddr_storage gf_group;	  /* multicast address */
+			__u32				 gf_fmode;	  /* filter mode */
+			__u32				 gf_numsrc;	  /* number of sources */
+			struct __kernel_sockaddr_storage gf_slist_flex[]; /* interface index */
+		};
+	};
 };
 
 #define GROUP_FILTER_SIZE(numsrc) \
@@ -266,10 +290,14 @@
 
 #define	IN_CLASSD(a)		((((long int) (a)) & 0xf0000000) == 0xe0000000)
 #define	IN_MULTICAST(a)		IN_CLASSD(a)
-#define IN_MULTICAST_NET	0xF0000000
+#define	IN_MULTICAST_NET	0xe0000000
 
-#define	IN_EXPERIMENTAL(a)	((((long int) (a)) & 0xf0000000) == 0xf0000000)
-#define	IN_BADCLASS(a)		IN_EXPERIMENTAL((a))
+#define	IN_BADCLASS(a)		(((long int) (a) ) == (long int)0xffffffff)
+#define	IN_EXPERIMENTAL(a)	IN_BADCLASS((a))
+
+#define	IN_CLASSE(a)		((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define	IN_CLASSE_NET		0xffffffff
+#define	IN_CLASSE_NSHIFT	0
 
 /* Address to accept any incoming messages. */
 #define	INADDR_ANY		((unsigned long int) 0x00000000)
@@ -280,6 +308,9 @@
 /* Address indicating an error return. */
 #define	INADDR_NONE		((unsigned long int) 0xffffffff)
 
+/* Dummy address for src of ICMP replies if no real address is set (RFC7600). */
+#define	INADDR_DUMMY		((unsigned long int) 0xc0000008)
+
 /* Network number for local host loopback. */
 #define	IN_LOOPBACKNET		127
 
@@ -288,10 +319,11 @@
 #define	IN_LOOPBACK(a)		((((long int) (a)) & 0xff000000) == 0x7f000000)
 
 /* Defines for Multicast INADDR */
-#define INADDR_UNSPEC_GROUP   	0xe0000000U	/* 224.0.0.0   */
-#define INADDR_ALLHOSTS_GROUP 	0xe0000001U	/* 224.0.0.1   */
-#define INADDR_ALLRTRS_GROUP    0xe0000002U	/* 224.0.0.2 */
-#define INADDR_MAX_LOCAL_GROUP  0xe00000ffU	/* 224.0.0.255 */
+#define INADDR_UNSPEC_GROUP		0xe0000000U	/* 224.0.0.0   */
+#define INADDR_ALLHOSTS_GROUP		0xe0000001U	/* 224.0.0.1   */
+#define INADDR_ALLRTRS_GROUP		0xe0000002U	/* 224.0.0.2 */
+#define INADDR_ALLSNOOPERS_GROUP	0xe000006aU	/* 224.0.0.106 */
+#define INADDR_MAX_LOCAL_GROUP		0xe00000ffU	/* 224.0.0.255 */
 #endif
 
 /* <asm/byteorder.h> contains the htonl type stuff.. */
diff --git a/include/linux-private/linux/in6.h b/include/linux-private/linux/in6.h
index 409bb3f..a17363e 100644
--- a/include/linux-private/linux/in6.h
+++ b/include/linux-private/linux/in6.h
@@ -145,6 +145,7 @@
 #define IPV6_TLV_PADN		1
 #define IPV6_TLV_ROUTERALERT	5
 #define IPV6_TLV_CALIPSO	7	/* RFC 5570 */
+#define IPV6_TLV_IOAM		49	/* TEMPORARY IANA allocation for IOAM */
 #define IPV6_TLV_JUMBO		194
 #define IPV6_TLV_HAO		201	/* home address option */
 
@@ -177,6 +178,9 @@
 #define IPV6_V6ONLY		26
 #define IPV6_JOIN_ANYCAST	27
 #define IPV6_LEAVE_ANYCAST	28
+#define IPV6_MULTICAST_ALL	29
+#define IPV6_ROUTER_ALERT_ISOLATE	30
+#define IPV6_RECVERR_RFC4884	31
 
 /* IPV6_MTU_DISCOVER values */
 #define IPV6_PMTUDISC_DONT		0
diff --git a/include/linux-private/linux/in_route.h b/include/linux-private/linux/in_route.h
new file mode 100644
index 0000000..0cc2c23
--- /dev/null
+++ b/include/linux-private/linux/in_route.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_IN_ROUTE_H
+#define _LINUX_IN_ROUTE_H
+
+/* IPv4 routing cache flags */
+
+#define RTCF_DEAD	RTNH_F_DEAD
+#define RTCF_ONLINK	RTNH_F_ONLINK
+
+/* Obsolete flag. About to be deleted */
+#define RTCF_NOPMTUDISC RTM_F_NOPMTUDISC
+
+#define RTCF_NOTIFY	0x00010000
+#define RTCF_DIRECTDST	0x00020000 /* unused */
+#define RTCF_REDIRECTED	0x00040000
+#define RTCF_TPROXY	0x00080000 /* unused */
+
+#define RTCF_FAST	0x00200000 /* unused */
+#define RTCF_MASQ	0x00400000 /* unused */
+#define RTCF_SNAT	0x00800000 /* unused */
+#define RTCF_DOREDIRECT 0x01000000
+#define RTCF_DIRECTSRC	0x04000000
+#define RTCF_DNAT	0x08000000
+#define RTCF_BROADCAST	0x10000000
+#define RTCF_MULTICAST	0x20000000
+#define RTCF_REJECT	0x40000000 /* unused */
+#define RTCF_LOCAL	0x80000000
+
+#define RTCF_NAT	(RTCF_DNAT|RTCF_SNAT)
+
+#define RT_TOS(tos)	((tos)&IPTOS_TOS_MASK)
+
+#endif /* _LINUX_IN_ROUTE_H */
diff --git a/include/linux-private/linux/inet_diag.h b/include/linux-private/linux/inet_diag.h
index f3bcd7e..d81cb69 100644
--- a/include/linux-private/linux/inet_diag.h
+++ b/include/linux-private/linux/inet_diag.h
@@ -64,9 +64,12 @@
 enum {
 	INET_DIAG_REQ_NONE,
 	INET_DIAG_REQ_BYTECODE,
+	INET_DIAG_REQ_SK_BPF_STORAGES,
+	INET_DIAG_REQ_PROTOCOL,
+	__INET_DIAG_REQ_MAX,
 };
 
-#define INET_DIAG_REQ_MAX INET_DIAG_REQ_BYTECODE
+#define INET_DIAG_REQ_MAX (__INET_DIAG_REQ_MAX - 1)
 
 /* Bytecode is sequence of 4 byte commands followed by variable arguments.
  * All the commands identified by "code" are conditional jumps forward:
@@ -94,13 +97,14 @@
 	INET_DIAG_BC_MARK_COND,
 	INET_DIAG_BC_S_EQ,
 	INET_DIAG_BC_D_EQ,
+	INET_DIAG_BC_CGROUP_COND,   /* u64 cgroup v2 ID */
 };
 
 struct inet_diag_hostcond {
 	__u8	family;
 	__u8	prefix_len;
 	int	port;
-	__be32	addr[0];
+	__be32	addr[];
 };
 
 struct inet_diag_markcond {
@@ -153,11 +157,24 @@
 	INET_DIAG_BBRINFO,	/* request as INET_DIAG_VEGASINFO */
 	INET_DIAG_CLASS_ID,	/* request as INET_DIAG_TCLASS */
 	INET_DIAG_MD5SIG,
+	INET_DIAG_ULP_INFO,
+	INET_DIAG_SK_BPF_STORAGES,
+	INET_DIAG_CGROUP_ID,
+	INET_DIAG_SOCKOPT,
 	__INET_DIAG_MAX,
 };
 
 #define INET_DIAG_MAX (__INET_DIAG_MAX - 1)
 
+enum {
+	INET_ULP_INFO_UNSPEC,
+	INET_ULP_INFO_NAME,
+	INET_ULP_INFO_TLS,
+	INET_ULP_INFO_MPTCP,
+	__INET_ULP_INFO_MAX,
+};
+#define INET_ULP_INFO_MAX (__INET_ULP_INFO_MAX - 1)
+
 /* INET_DIAG_MEM */
 
 struct inet_diag_meminfo {
@@ -167,6 +184,23 @@
 	__u32	idiag_tmem;
 };
 
+/* INET_DIAG_SOCKOPT */
+
+struct inet_diag_sockopt {
+	__u8	recverr:1,
+		is_icsk:1,
+		freebind:1,
+		hdrincl:1,
+		mc_loop:1,
+		transparent:1,
+		mc_all:1,
+		nodefrag:1;
+	__u8	bind_address_no_port:1,
+		recverr_rfc4884:1,
+		defer_connect:1,
+		unused:5;
+};
+
 /* INET_DIAG_VEGASINFO */
 
 struct tcpvegas_info {
diff --git a/include/linux-private/linux/ioctl.h b/include/linux-private/linux/ioctl.h
new file mode 100644
index 0000000..b292e80
--- /dev/null
+++ b/include/linux-private/linux/ioctl.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_IOCTL_H
+#define _LINUX_IOCTL_H
+
+#include <asm/ioctl.h>
+
+#endif /* _LINUX_IOCTL_H */
+
diff --git a/include/linux-private/linux/ip.h b/include/linux-private/linux/ip.h
index f4ecd2f..9b4dd89 100644
--- a/include/linux-private/linux/ip.h
+++ b/include/linux-private/linux/ip.h
@@ -18,6 +18,7 @@
 #ifndef _LINUX_IP_H
 #define _LINUX_IP_H
 #include <linux/types.h>
+#include <linux/stddef.h>
 #include <asm/byteorder.h>
 
 #define IPTOS_TOS_MASK		0x1E
@@ -100,8 +101,10 @@
 	__u8	ttl;
 	__u8	protocol;
 	__sum16	check;
-	__be32	saddr;
-	__be32	daddr;
+	__struct_group(/* no tag */, addrs, /* no attrs */,
+		__be32	saddr;
+		__be32	daddr;
+	);
 	/*The options start here. */
 };
 
@@ -112,13 +115,13 @@
 	__be16 reserved;
 	__be32 spi;
 	__be32 seq_no;		/* Sequence number */
-	__u8  auth_data[0];	/* Variable len but >=4. Mind the 64 bit alignment! */
+	__u8  auth_data[];	/* Variable len but >=4. Mind the 64 bit alignment! */
 };
 
 struct ip_esp_hdr {
 	__be32 spi;
 	__be32 seq_no;		/* Sequence number */
-	__u8  enc_data[0];	/* Variable len but >=8. Mind the 64 bit alignment! */
+	__u8  enc_data[];	/* Variable len but >=8. Mind the 64 bit alignment! */
 };
 
 struct ip_comp_hdr {
@@ -169,6 +172,7 @@
 	IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST,
 	IPV4_DEVCONF_DROP_GRATUITOUS_ARP,
 	IPV4_DEVCONF_BC_FORWARDING,
+	IPV4_DEVCONF_ARP_EVICT_NOCARRIER,
 	__IPV4_DEVCONF_MAX
 };
 
diff --git a/include/linux-private/linux/ipv6.h b/include/linux-private/linux/ipv6.h
index 769b4a3..fcf05a6 100644
--- a/include/linux-private/linux/ipv6.h
+++ b/include/linux-private/linux/ipv6.h
@@ -4,6 +4,7 @@
 
 #include <linux/libc-compat.h>
 #include <linux/types.h>
+#include <linux/stddef.h>
 #include <linux/in6.h>
 #include <asm/byteorder.h>
 
@@ -40,6 +41,7 @@
 #define IPV6_SRCRT_STRICT	0x01	/* Deprecated; will be removed */
 #define IPV6_SRCRT_TYPE_0	0	/* Deprecated; will be removed */
 #define IPV6_SRCRT_TYPE_2	2	/* IPv6 type 2 Routing Header	*/
+#define IPV6_SRCRT_TYPE_3	3	/* RPL Segment Routing with IPv6 */
 #define IPV6_SRCRT_TYPE_4	4	/* Segment Routing with IPv6 */
 
 /*
@@ -79,7 +81,7 @@
 struct rt0_hdr {
 	struct ipv6_rt_hdr	rt_hdr;
 	__u32			reserved;
-	struct in6_addr		addr[0];
+	struct in6_addr		addr[];
 
 #define rt0_type		rt_hdr.type
 };
@@ -129,8 +131,10 @@
 	__u8			nexthdr;
 	__u8			hop_limit;
 
-	struct	in6_addr	saddr;
-	struct	in6_addr	daddr;
+	__struct_group(/* no tag */, addrs, /* no attrs */,
+		struct	in6_addr	saddr;
+		struct	in6_addr	daddr;
+	);
 };
 
 
@@ -187,6 +191,13 @@
 	DEVCONF_DISABLE_POLICY,
 	DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN,
 	DEVCONF_NDISC_TCLASS,
+	DEVCONF_RPL_SEG_ENABLED,
+	DEVCONF_RA_DEFRTR_METRIC,
+	DEVCONF_IOAM6_ENABLED,
+	DEVCONF_IOAM6_ID,
+	DEVCONF_IOAM6_ID_WIDE,
+	DEVCONF_NDISC_EVICT_NOCARRIER,
+	DEVCONF_ACCEPT_UNTRACKED_NA,
 	DEVCONF_MAX
 };
 
diff --git a/include/linux-private/linux/limits.h b/include/linux-private/linux/limits.h
new file mode 100644
index 0000000..c3547f0
--- /dev/null
+++ b/include/linux-private/linux/limits.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_LIMITS_H
+#define _LINUX_LIMITS_H
+
+#define NR_OPEN	        1024
+
+#define NGROUPS_MAX    65536	/* supplemental group IDs are available */
+#define ARG_MAX       131072	/* # bytes of args + environ for exec() */
+#define LINK_MAX         127	/* # links a file may have */
+#define MAX_CANON        255	/* size of the canonical input queue */
+#define MAX_INPUT        255	/* size of the type-ahead buffer */
+#define NAME_MAX         255	/* # chars in a file name */
+#define PATH_MAX        4096	/* # chars in a path name including nul */
+#define PIPE_BUF        4096	/* # bytes in atomic write to a pipe */
+#define XATTR_NAME_MAX   255	/* # chars in an extended attribute name */
+#define XATTR_SIZE_MAX 65536	/* size of an extended attribute value (64k) */
+#define XATTR_LIST_MAX 65536	/* size of extended attribute namelist (64k) */
+
+#define RTSIG_MAX	  32
+
+#endif
diff --git a/include/linux-private/linux/lwtunnel.h b/include/linux-private/linux/lwtunnel.h
index 3f3fe6f..9d22961 100644
--- a/include/linux-private/linux/lwtunnel.h
+++ b/include/linux-private/linux/lwtunnel.h
@@ -13,6 +13,9 @@
 	LWTUNNEL_ENCAP_SEG6,
 	LWTUNNEL_ENCAP_BPF,
 	LWTUNNEL_ENCAP_SEG6_LOCAL,
+	LWTUNNEL_ENCAP_RPL,
+	LWTUNNEL_ENCAP_IOAM6,
+	LWTUNNEL_ENCAP_XFRM,
 	__LWTUNNEL_ENCAP_MAX,
 };
 
@@ -27,6 +30,7 @@
 	LWTUNNEL_IP_TOS,
 	LWTUNNEL_IP_FLAGS,
 	LWTUNNEL_IP_PAD,
+	LWTUNNEL_IP_OPTS,
 	__LWTUNNEL_IP_MAX,
 };
 
@@ -41,12 +45,52 @@
 	LWTUNNEL_IP6_TC,
 	LWTUNNEL_IP6_FLAGS,
 	LWTUNNEL_IP6_PAD,
+	LWTUNNEL_IP6_OPTS,
 	__LWTUNNEL_IP6_MAX,
 };
 
 #define LWTUNNEL_IP6_MAX (__LWTUNNEL_IP6_MAX - 1)
 
 enum {
+	LWTUNNEL_IP_OPTS_UNSPEC,
+	LWTUNNEL_IP_OPTS_GENEVE,
+	LWTUNNEL_IP_OPTS_VXLAN,
+	LWTUNNEL_IP_OPTS_ERSPAN,
+	__LWTUNNEL_IP_OPTS_MAX,
+};
+
+#define LWTUNNEL_IP_OPTS_MAX (__LWTUNNEL_IP_OPTS_MAX - 1)
+
+enum {
+	LWTUNNEL_IP_OPT_GENEVE_UNSPEC,
+	LWTUNNEL_IP_OPT_GENEVE_CLASS,
+	LWTUNNEL_IP_OPT_GENEVE_TYPE,
+	LWTUNNEL_IP_OPT_GENEVE_DATA,
+	__LWTUNNEL_IP_OPT_GENEVE_MAX,
+};
+
+#define LWTUNNEL_IP_OPT_GENEVE_MAX (__LWTUNNEL_IP_OPT_GENEVE_MAX - 1)
+
+enum {
+	LWTUNNEL_IP_OPT_VXLAN_UNSPEC,
+	LWTUNNEL_IP_OPT_VXLAN_GBP,
+	__LWTUNNEL_IP_OPT_VXLAN_MAX,
+};
+
+#define LWTUNNEL_IP_OPT_VXLAN_MAX (__LWTUNNEL_IP_OPT_VXLAN_MAX - 1)
+
+enum {
+	LWTUNNEL_IP_OPT_ERSPAN_UNSPEC,
+	LWTUNNEL_IP_OPT_ERSPAN_VER,
+	LWTUNNEL_IP_OPT_ERSPAN_INDEX,
+	LWTUNNEL_IP_OPT_ERSPAN_DIR,
+	LWTUNNEL_IP_OPT_ERSPAN_HWID,
+	__LWTUNNEL_IP_OPT_ERSPAN_MAX,
+};
+
+#define LWTUNNEL_IP_OPT_ERSPAN_MAX (__LWTUNNEL_IP_OPT_ERSPAN_MAX - 1)
+
+enum {
 	LWT_BPF_PROG_UNSPEC,
 	LWT_BPF_PROG_FD,
 	LWT_BPF_PROG_NAME,
@@ -68,4 +112,13 @@
 
 #define LWT_BPF_MAX_HEADROOM 256
 
+enum {
+	LWT_XFRM_UNSPEC,
+	LWT_XFRM_IF_ID,
+	LWT_XFRM_LINK,
+	__LWT_XFRM_MAX,
+};
+
+#define LWT_XFRM_MAX (__LWT_XFRM_MAX - 1)
+
 #endif /* _LWTUNNEL_H_ */
diff --git a/include/linux-private/linux/neighbour.h b/include/linux-private/linux/neighbour.h
index 904db61..5e67a7e 100644
--- a/include/linux-private/linux/neighbour.h
+++ b/include/linux-private/linux/neighbour.h
@@ -28,6 +28,12 @@
 	NDA_MASTER,
 	NDA_LINK_NETNSID,
 	NDA_SRC_VNI,
+	NDA_PROTOCOL,  /* Originator of entry */
+	NDA_NH_ID,
+	NDA_FDB_EXT_ATTRS,
+	NDA_FLAGS_EXT,
+	NDA_NDM_STATE_MASK,
+	NDA_NDM_FLAGS_MASK,
 	__NDA_MAX
 };
 
@@ -37,13 +43,17 @@
  *	Neighbor Cache Entry Flags
  */
 
-#define NTF_USE		0x01
-#define NTF_SELF	0x02
-#define NTF_MASTER	0x04
-#define NTF_PROXY	0x08	/* == ATF_PUBL */
-#define NTF_EXT_LEARNED	0x10
-#define NTF_OFFLOADED   0x20
-#define NTF_ROUTER	0x80
+#define NTF_USE		(1 << 0)
+#define NTF_SELF	(1 << 1)
+#define NTF_MASTER	(1 << 2)
+#define NTF_PROXY	(1 << 3)	/* == ATF_PUBL */
+#define NTF_EXT_LEARNED	(1 << 4)
+#define NTF_OFFLOADED   (1 << 5)
+#define NTF_STICKY	(1 << 6)
+#define NTF_ROUTER	(1 << 7)
+/* Extended flags under NDA_FLAGS_EXT: */
+#define NTF_EXT_MANAGED		(1 << 0)
+#define NTF_EXT_LOCKED		(1 << 1)
 
 /*
  *	Neighbor Cache Entry States.
@@ -61,9 +71,27 @@
 #define NUD_PERMANENT	0x80
 #define NUD_NONE	0x00
 
-/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
-   and make no address resolution or NUD.
-   NUD_PERMANENT also cannot be deleted by garbage collectors.
+/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no
+ * address resolution or NUD.
+ *
+ * NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true
+ * for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier
+ * down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED
+ * flagged entries explicitly are (which is also consistent with the routing
+ * subsystem).
+ *
+ * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
+ * states don't make sense and thus are ignored. Such entries don't age and
+ * can roam.
+ *
+ * NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf
+ * of a user space control plane, and automatically refreshed so that (if
+ * possible) they remain in NUD_REACHABLE state.
+ *
+ * NTF_EXT_LOCKED flagged bridge FDB entries are entries generated by the
+ * bridge in response to a host trying to communicate via a locked bridge port
+ * with MAB enabled. Their purpose is to notify user space that a host requires
+ * authentication.
  */
 
 struct nda_cacheinfo {
@@ -132,6 +160,7 @@
 	NDTPA_QUEUE_LENBYTES,		/* u32 */
 	NDTPA_MCAST_REPROBES,		/* u32 */
 	NDTPA_PAD,
+	NDTPA_INTERVAL_PROBE_TIME_MS,	/* u64, msecs */
 	__NDTPA_MAX
 };
 #define NDTPA_MAX (__NDTPA_MAX - 1)
@@ -169,4 +198,27 @@
 };
 #define NDTA_MAX (__NDTA_MAX - 1)
 
+ /* FDB activity notification bits used in NFEA_ACTIVITY_NOTIFY:
+  * - FDB_NOTIFY_BIT - notify on activity/expire for any entry
+  * - FDB_NOTIFY_INACTIVE_BIT - mark as inactive to avoid multiple notifications
+  */
+enum {
+	FDB_NOTIFY_BIT		= (1 << 0),
+	FDB_NOTIFY_INACTIVE_BIT	= (1 << 1)
+};
+
+/* embedded into NDA_FDB_EXT_ATTRS:
+ * [NDA_FDB_EXT_ATTRS] = {
+ *     [NFEA_ACTIVITY_NOTIFY]
+ *     ...
+ * }
+ */
+enum {
+	NFEA_UNSPEC,
+	NFEA_ACTIVITY_NOTIFY,
+	NFEA_DONT_REFRESH,
+	__NFEA_MAX
+};
+#define NFEA_MAX (__NFEA_MAX - 1)
+
 #endif
diff --git a/include/linux-private/linux/netdevice.h b/include/linux-private/linux/netdevice.h
new file mode 100644
index 0000000..86d961c
--- /dev/null
+++ b/include/linux-private/linux/netdevice.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * 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.
+ *
+ *		Definitions for the Interfaces handler.
+ *
+ * Version:	@(#)dev.h	1.0.10	08/12/93
+ *
+ * Authors:	Ross Biro
+ *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *		Corey Minyard <wf-rch!minyard@relay.EU.net>
+ *		Donald J. Becker, <becker@cesdis.gsfc.nasa.gov>
+ *		Alan Cox, <alan@lxorguk.ukuu.org.uk>
+ *		Bjorn Ekwall. <bj0rn@blox.se>
+ *              Pekka Riikonen <priikone@poseidon.pspt.fi>
+ *
+ *		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.
+ *
+ *		Moved to /usr/include/linux for NET3
+ */
+#ifndef _LINUX_NETDEVICE_H
+#define _LINUX_NETDEVICE_H
+
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <linux/if_link.h>
+
+
+#define MAX_ADDR_LEN	32		/* Largest hardware address length */
+
+/* Initial net device group. All devices belong to group 0 by default. */
+#define INIT_NETDEV_GROUP	0
+
+
+/* interface name assignment types (sysfs name_assign_type attribute) */
+#define NET_NAME_UNKNOWN	0	/* unknown origin (not exposed to userspace) */
+#define NET_NAME_ENUM		1	/* enumerated by kernel */
+#define NET_NAME_PREDICTABLE	2	/* predictably named by the kernel */
+#define NET_NAME_USER		3	/* provided by user-space */
+#define NET_NAME_RENAMED	4	/* renamed by user-space */
+
+/* Media selection options. */
+enum {
+        IF_PORT_UNKNOWN = 0,
+        IF_PORT_10BASE2,
+        IF_PORT_10BASET,
+        IF_PORT_AUI,
+        IF_PORT_100BASET,
+        IF_PORT_100BASETX,
+        IF_PORT_100BASEFX
+};
+
+/* hardware address assignment types */
+#define NET_ADDR_PERM		0	/* address is permanent (default) */
+#define NET_ADDR_RANDOM		1	/* address is generated randomly */
+#define NET_ADDR_STOLEN		2	/* address is stolen from other device */
+#define NET_ADDR_SET		3	/* address is set using
+					 * dev_set_mac_address() */
+
+#endif /* _LINUX_NETDEVICE_H */
diff --git a/include/linux-private/linux/netfilter.h b/include/linux-private/linux/netfilter.h
index 36378a0..30c045b 100644
--- a/include/linux-private/linux/netfilter.h
+++ b/include/linux-private/linux/netfilter.h
@@ -33,10 +33,6 @@
 #define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP)
 
 /* only for userspace compatibility */
-/* Generic cache responses from hook functions.
-   <= 0x2000 is used for protocol-flags. */
-#define NFC_UNKNOWN 0x4000
-#define NFC_ALTERED 0x8000
 
 /* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */
 #define NF_VERDICT_BITS 16
@@ -47,11 +43,13 @@
 	NF_INET_FORWARD,
 	NF_INET_LOCAL_OUT,
 	NF_INET_POST_ROUTING,
-	NF_INET_NUMHOOKS
+	NF_INET_NUMHOOKS,
+	NF_INET_INGRESS = NF_INET_NUMHOOKS,
 };
 
 enum nf_dev_hooks {
 	NF_NETDEV_INGRESS,
+	NF_NETDEV_EGRESS,
 	NF_NETDEV_NUMHOOKS
 };
 
diff --git a/include/linux-private/linux/netfilter/nf_conntrack_common.h b/include/linux-private/linux/netfilter/nf_conntrack_common.h
index dc374c9..3c99056 100644
--- a/include/linux-private/linux/netfilter/nf_conntrack_common.h
+++ b/include/linux-private/linux/netfilter/nf_conntrack_common.h
@@ -93,7 +93,8 @@
 	IPS_UNTRACKED_BIT = 12,
 	IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT),
 
-	/* Conntrack got a helper explicitly attached via CT target. */
+
+	/* Conntrack got a helper explicitly attached (ruleset, ctnetlink). */
 	IPS_HELPER_BIT = 13,
 	IPS_HELPER = (1 << IPS_HELPER_BIT),
 
@@ -101,14 +102,19 @@
 	IPS_OFFLOAD_BIT = 14,
 	IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT),
 
+	/* Conntrack has been offloaded to hardware. */
+	IPS_HW_OFFLOAD_BIT = 15,
+	IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT),
+
 	/* Be careful here, modifying these bits can make things messy,
 	 * so don't let users modify them directly.
 	 */
 	IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK |
 				 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
-				 IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
+				 IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED |
+				 IPS_OFFLOAD | IPS_HW_OFFLOAD),
 
-	__IPS_MAX_BIT = 15,
+	__IPS_MAX_BIT = 16,
 };
 
 /* Connection tracking event types */
diff --git a/include/linux-private/linux/netfilter/nf_conntrack_tcp.h b/include/linux-private/linux/netfilter/nf_conntrack_tcp.h
new file mode 100644
index 0000000..a589dbc
--- /dev/null
+++ b/include/linux-private/linux/netfilter/nf_conntrack_tcp.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _NF_CONNTRACK_TCP_H
+#define _NF_CONNTRACK_TCP_H
+/* TCP tracking. */
+
+#include <linux/types.h>
+
+/* This is exposed to userspace (ctnetlink) */
+enum tcp_conntrack {
+	TCP_CONNTRACK_NONE,
+	TCP_CONNTRACK_SYN_SENT,
+	TCP_CONNTRACK_SYN_RECV,
+	TCP_CONNTRACK_ESTABLISHED,
+	TCP_CONNTRACK_FIN_WAIT,
+	TCP_CONNTRACK_CLOSE_WAIT,
+	TCP_CONNTRACK_LAST_ACK,
+	TCP_CONNTRACK_TIME_WAIT,
+	TCP_CONNTRACK_CLOSE,
+	TCP_CONNTRACK_LISTEN,	/* obsolete */
+#define TCP_CONNTRACK_SYN_SENT2	TCP_CONNTRACK_LISTEN
+	TCP_CONNTRACK_MAX,
+	TCP_CONNTRACK_IGNORE,
+	TCP_CONNTRACK_RETRANS,
+	TCP_CONNTRACK_UNACK,
+	TCP_CONNTRACK_TIMEOUT_MAX
+};
+
+/* Window scaling is advertised by the sender */
+#define IP_CT_TCP_FLAG_WINDOW_SCALE		0x01
+
+/* SACK is permitted by the sender */
+#define IP_CT_TCP_FLAG_SACK_PERM		0x02
+
+/* This sender sent FIN first */
+#define IP_CT_TCP_FLAG_CLOSE_INIT		0x04
+
+/* Be liberal in window checking */
+#define IP_CT_TCP_FLAG_BE_LIBERAL		0x08
+
+/* Has unacknowledged data */
+#define IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED	0x10
+
+/* The field td_maxack has been set */
+#define IP_CT_TCP_FLAG_MAXACK_SET		0x20
+
+/* Marks possibility for expected RFC5961 challenge ACK */
+#define IP_CT_EXP_CHALLENGE_ACK 		0x40
+
+/* Simultaneous open initialized */
+#define IP_CT_TCP_SIMULTANEOUS_OPEN		0x80
+
+struct nf_ct_tcp_flags {
+	__u8 flags;
+	__u8 mask;
+};
+
+
+#endif /* _NF_CONNTRACK_TCP_H */
diff --git a/include/linux-private/linux/netfilter/nfnetlink.h b/include/linux-private/linux/netfilter/nfnetlink.h
index a89f3a5..b89a3e6 100644
--- a/include/linux-private/linux/netfilter/nfnetlink.h
+++ b/include/linux-private/linux/netfilter/nfnetlink.h
@@ -60,7 +60,8 @@
 #define NFNL_SUBSYS_CTHELPER		9
 #define NFNL_SUBSYS_NFTABLES		10
 #define NFNL_SUBSYS_NFT_COMPAT		11
-#define NFNL_SUBSYS_COUNT		12
+#define NFNL_SUBSYS_HOOK		12
+#define NFNL_SUBSYS_COUNT		13
 
 /* Reserved control nfnetlink messages */
 #define NFNL_MSG_BATCH_BEGIN		NLMSG_MIN_TYPE
diff --git a/include/linux-private/linux/netfilter/nfnetlink_conntrack.h b/include/linux-private/linux/netfilter/nfnetlink_conntrack.h
index 1d41810..c2ac726 100644
--- a/include/linux-private/linux/netfilter/nfnetlink_conntrack.h
+++ b/include/linux-private/linux/netfilter/nfnetlink_conntrack.h
@@ -55,6 +55,8 @@
 	CTA_LABELS,
 	CTA_LABELS_MASK,
 	CTA_SYNPROXY,
+	CTA_FILTER,
+	CTA_STATUS_MASK,
 	__CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
@@ -246,7 +248,7 @@
 	CTA_STATS_FOUND,
 	CTA_STATS_NEW,		/* no longer used */
 	CTA_STATS_INVALID,
-	CTA_STATS_IGNORE,
+	CTA_STATS_IGNORE,	/* no longer used */
 	CTA_STATS_DELETE,	/* no longer used */
 	CTA_STATS_DELETE_LIST,	/* no longer used */
 	CTA_STATS_INSERT,
@@ -255,6 +257,8 @@
 	CTA_STATS_EARLY_DROP,
 	CTA_STATS_ERROR,
 	CTA_STATS_SEARCH_RESTART,
+	CTA_STATS_CLASH_RESOLVE,
+	CTA_STATS_CHAIN_TOOLONG,
 	__CTA_STATS_MAX,
 };
 #define CTA_STATS_MAX (__CTA_STATS_MAX - 1)
@@ -276,4 +280,12 @@
 };
 #define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
 
+enum ctattr_filter {
+	CTA_FILTER_UNSPEC,
+	CTA_FILTER_ORIG_FLAGS,
+	CTA_FILTER_REPLY_FLAGS,
+	__CTA_FILTER_MAX
+};
+#define CTA_FILTER_MAX (__CTA_FILTER_MAX - 1)
+
 #endif /* _IPCONNTRACK_NETLINK_H */
diff --git a/include/linux-private/linux/netfilter/nfnetlink_log.h b/include/linux-private/linux/netfilter/nfnetlink_log.h
index 45c8d3b..0af9c11 100644
--- a/include/linux-private/linux/netfilter/nfnetlink_log.h
+++ b/include/linux-private/linux/netfilter/nfnetlink_log.h
@@ -61,7 +61,7 @@
 	NFULA_HWTYPE,			/* hardware type */
 	NFULA_HWHEADER,			/* hardware header */
 	NFULA_HWLEN,			/* hardware header length */
-	NFULA_CT,                       /* nf_conntrack_netlink.h */
+	NFULA_CT,                       /* nfnetlink_conntrack.h */
 	NFULA_CT_INFO,                  /* enum ip_conntrack_info */
 	NFULA_VLAN,			/* nested attribute: packet vlan info */
 	NFULA_L2HDR,			/* full L2 header */
diff --git a/include/linux-private/linux/netfilter/nfnetlink_queue.h b/include/linux-private/linux/netfilter/nfnetlink_queue.h
index bcb2cb5..efcb7c0 100644
--- a/include/linux-private/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux-private/linux/netfilter/nfnetlink_queue.h
@@ -51,16 +51,18 @@
 	NFQA_IFINDEX_PHYSOUTDEV,	/* __u32 ifindex */
 	NFQA_HWADDR,			/* nfqnl_msg_packet_hw */
 	NFQA_PAYLOAD,			/* opaque data payload */
-	NFQA_CT,			/* nf_conntrack_netlink.h */
+	NFQA_CT,			/* nfnetlink_conntrack.h */
 	NFQA_CT_INFO,			/* enum ip_conntrack_info */
 	NFQA_CAP_LEN,			/* __u32 length of captured packet */
 	NFQA_SKB_INFO,			/* __u32 skb meta information */
-	NFQA_EXP,			/* nf_conntrack_netlink.h */
+	NFQA_EXP,			/* nfnetlink_conntrack.h */
 	NFQA_UID,			/* __u32 sk uid */
 	NFQA_GID,			/* __u32 sk gid */
 	NFQA_SECCTX,			/* security context string */
 	NFQA_VLAN,			/* nested attribute: packet vlan info */
 	NFQA_L2HDR,			/* full L2 header */
+	NFQA_PRIORITY,			/* skb->priority */
+	NFQA_CGROUP_CLASSID,		/* __u32 cgroup classid */
 
 	__NFQA_MAX
 };
diff --git a/include/linux-private/linux/netlink.h b/include/linux-private/linux/netlink.h
index 0b2c29b..47bac97 100644
--- a/include/linux-private/linux/netlink.h
+++ b/include/linux-private/linux/netlink.h
@@ -2,7 +2,7 @@
 #ifndef __LINUX_NETLINK_H
 #define __LINUX_NETLINK_H
 
-#include <linux/kernel.h>
+#include <linux/const.h>
 #include <linux/socket.h> /* for __kernel_sa_family_t */
 #include <linux/types.h>
 
@@ -20,7 +20,7 @@
 #define NETLINK_CONNECTOR	11
 #define NETLINK_NETFILTER	12	/* netfilter subsystem */
 #define NETLINK_IP6_FW		13
-#define NETLINK_DNRTMSG		14	/* DECnet routing messages */
+#define NETLINK_DNRTMSG		14	/* DECnet routing messages (obsolete) */
 #define NETLINK_KOBJECT_UEVENT	15	/* Kernel messages to userspace */
 #define NETLINK_GENERIC		16
 /* leave room for NETLINK_DM (DM Events) */
@@ -41,12 +41,20 @@
        	__u32		nl_groups;	/* multicast groups mask */
 };
 
+/**
+ * struct nlmsghdr - fixed format metadata header of Netlink messages
+ * @nlmsg_len:   Length of message including header
+ * @nlmsg_type:  Message content type
+ * @nlmsg_flags: Additional flags
+ * @nlmsg_seq:   Sequence number
+ * @nlmsg_pid:   Sending process port ID
+ */
 struct nlmsghdr {
-	__u32		nlmsg_len;	/* Length of message including header */
-	__u16		nlmsg_type;	/* Message content */
-	__u16		nlmsg_flags;	/* Additional flags */
-	__u32		nlmsg_seq;	/* Sequence number */
-	__u32		nlmsg_pid;	/* Sending process port ID */
+	__u32		nlmsg_len;
+	__u16		nlmsg_type;
+	__u16		nlmsg_flags;
+	__u32		nlmsg_seq;
+	__u32		nlmsg_pid;
 };
 
 /* Flags values */
@@ -54,7 +62,7 @@
 #define NLM_F_REQUEST		0x01	/* It is request message. 	*/
 #define NLM_F_MULTI		0x02	/* Multipart message, terminated by NLMSG_DONE */
 #define NLM_F_ACK		0x04	/* Reply with ack, with zero or error code */
-#define NLM_F_ECHO		0x08	/* Echo this request 		*/
+#define NLM_F_ECHO		0x08	/* Receive resulting notifications */
 #define NLM_F_DUMP_INTR		0x10	/* Dump was inconsistent due to sequence change */
 #define NLM_F_DUMP_FILTERED	0x20	/* Dump was filtered as requested */
 
@@ -72,6 +80,7 @@
 
 /* Modifiers to DELETE request */
 #define NLM_F_NONREC	0x100	/* Do not delete recursively	*/
+#define NLM_F_BULK	0x200	/* Delete multiple objects	*/
 
 /* Flags for ACK message */
 #define NLM_F_CAPPED	0x100	/* request was capped */
@@ -91,9 +100,10 @@
 #define NLMSG_HDRLEN	 ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
 #define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
 #define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
-#define NLMSG_DATA(nlh)  ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
+#define NLMSG_DATA(nlh)  ((void *)(((char *)nlh) + NLMSG_HDRLEN))
 #define NLMSG_NEXT(nlh,len)	 ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
-				  (struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
+				  (struct nlmsghdr *)(((char *)(nlh)) + \
+				  NLMSG_ALIGN((nlh)->nlmsg_len)))
 #define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
 			   (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
 			   (nlh)->nlmsg_len <= (len))
@@ -129,6 +139,11 @@
  * @NLMSGERR_ATTR_COOKIE: arbitrary subsystem specific cookie to
  *	be used - in the success case - to identify a created
  *	object or operation or similar (binary)
+ * @NLMSGERR_ATTR_POLICY: policy for a rejected attribute
+ * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
+ *	%NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
+ *	missing at the message level
+ * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
  * @__NLMSGERR_ATTR_MAX: number of attributes
  * @NLMSGERR_ATTR_MAX: highest attribute number
  */
@@ -137,6 +152,9 @@
 	NLMSGERR_ATTR_MSG,
 	NLMSGERR_ATTR_OFFS,
 	NLMSGERR_ATTR_COOKIE,
+	NLMSGERR_ATTR_POLICY,
+	NLMSGERR_ATTR_MISS_TYPE,
+	NLMSGERR_ATTR_MISS_NEST,
 
 	__NLMSGERR_ATTR_MAX,
 	NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
@@ -153,6 +171,7 @@
 #define NETLINK_LIST_MEMBERSHIPS	9
 #define NETLINK_CAP_ACK			10
 #define NETLINK_EXT_ACK			11
+#define NETLINK_GET_STRICT_CHK		12
 
 struct nl_pktinfo {
 	__u32	group;
@@ -244,4 +263,112 @@
 	__u32 selector;
 };
 
+/*
+ * policy descriptions - it's specific to each family how this is used
+ * Normally, it should be retrieved via a dump inside another attribute
+ * specifying where it applies.
+ */
+
+/**
+ * enum netlink_attribute_type - type of an attribute
+ * @NL_ATTR_TYPE_INVALID: unused
+ * @NL_ATTR_TYPE_FLAG: flag attribute (present/not present)
+ * @NL_ATTR_TYPE_U8: 8-bit unsigned attribute
+ * @NL_ATTR_TYPE_U16: 16-bit unsigned attribute
+ * @NL_ATTR_TYPE_U32: 32-bit unsigned attribute
+ * @NL_ATTR_TYPE_U64: 64-bit unsigned attribute
+ * @NL_ATTR_TYPE_S8: 8-bit signed attribute
+ * @NL_ATTR_TYPE_S16: 16-bit signed attribute
+ * @NL_ATTR_TYPE_S32: 32-bit signed attribute
+ * @NL_ATTR_TYPE_S64: 64-bit signed attribute
+ * @NL_ATTR_TYPE_BINARY: binary data, min/max length may be specified
+ * @NL_ATTR_TYPE_STRING: string, min/max length may be specified
+ * @NL_ATTR_TYPE_NUL_STRING: NUL-terminated string,
+ *	min/max length may be specified
+ * @NL_ATTR_TYPE_NESTED: nested, i.e. the content of this attribute
+ *	consists of sub-attributes. The nested policy and maxtype
+ *	inside may be specified.
+ * @NL_ATTR_TYPE_NESTED_ARRAY: nested array, i.e. the content of this
+ *	attribute contains sub-attributes whose type is irrelevant
+ *	(just used to separate the array entries) and each such array
+ *	entry has attributes again, the policy for those inner ones
+ *	and the corresponding maxtype may be specified.
+ * @NL_ATTR_TYPE_BITFIELD32: &struct nla_bitfield32 attribute
+ */
+enum netlink_attribute_type {
+	NL_ATTR_TYPE_INVALID,
+
+	NL_ATTR_TYPE_FLAG,
+
+	NL_ATTR_TYPE_U8,
+	NL_ATTR_TYPE_U16,
+	NL_ATTR_TYPE_U32,
+	NL_ATTR_TYPE_U64,
+
+	NL_ATTR_TYPE_S8,
+	NL_ATTR_TYPE_S16,
+	NL_ATTR_TYPE_S32,
+	NL_ATTR_TYPE_S64,
+
+	NL_ATTR_TYPE_BINARY,
+	NL_ATTR_TYPE_STRING,
+	NL_ATTR_TYPE_NUL_STRING,
+
+	NL_ATTR_TYPE_NESTED,
+	NL_ATTR_TYPE_NESTED_ARRAY,
+
+	NL_ATTR_TYPE_BITFIELD32,
+};
+
+/**
+ * enum netlink_policy_type_attr - policy type attributes
+ * @NL_POLICY_TYPE_ATTR_UNSPEC: unused
+ * @NL_POLICY_TYPE_ATTR_TYPE: type of the attribute,
+ *	&enum netlink_attribute_type (U32)
+ * @NL_POLICY_TYPE_ATTR_MIN_VALUE_S: minimum value for signed
+ *	integers (S64)
+ * @NL_POLICY_TYPE_ATTR_MAX_VALUE_S: maximum value for signed
+ *	integers (S64)
+ * @NL_POLICY_TYPE_ATTR_MIN_VALUE_U: minimum value for unsigned
+ *	integers (U64)
+ * @NL_POLICY_TYPE_ATTR_MAX_VALUE_U: maximum value for unsigned
+ *	integers (U64)
+ * @NL_POLICY_TYPE_ATTR_MIN_LENGTH: minimum length for binary
+ *	attributes, no minimum if not given (U32)
+ * @NL_POLICY_TYPE_ATTR_MAX_LENGTH: maximum length for binary
+ *	attributes, no maximum if not given (U32)
+ * @NL_POLICY_TYPE_ATTR_POLICY_IDX: sub policy for nested and
+ *	nested array types (U32)
+ * @NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE: maximum sub policy
+ *	attribute for nested and nested array types, this can
+ *	in theory be < the size of the policy pointed to by
+ *	the index, if limited inside the nesting (U32)
+ * @NL_POLICY_TYPE_ATTR_BITFIELD32_MASK: valid mask for the
+ *	bitfield32 type (U32)
+ * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64)
+ * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
+ *
+ * @__NL_POLICY_TYPE_ATTR_MAX: number of attributes
+ * @NL_POLICY_TYPE_ATTR_MAX: highest attribute number
+ */
+enum netlink_policy_type_attr {
+	NL_POLICY_TYPE_ATTR_UNSPEC,
+	NL_POLICY_TYPE_ATTR_TYPE,
+	NL_POLICY_TYPE_ATTR_MIN_VALUE_S,
+	NL_POLICY_TYPE_ATTR_MAX_VALUE_S,
+	NL_POLICY_TYPE_ATTR_MIN_VALUE_U,
+	NL_POLICY_TYPE_ATTR_MAX_VALUE_U,
+	NL_POLICY_TYPE_ATTR_MIN_LENGTH,
+	NL_POLICY_TYPE_ATTR_MAX_LENGTH,
+	NL_POLICY_TYPE_ATTR_POLICY_IDX,
+	NL_POLICY_TYPE_ATTR_POLICY_MAXTYPE,
+	NL_POLICY_TYPE_ATTR_BITFIELD32_MASK,
+	NL_POLICY_TYPE_ATTR_PAD,
+	NL_POLICY_TYPE_ATTR_MASK,
+
+	/* keep last */
+	__NL_POLICY_TYPE_ATTR_MAX,
+	NL_POLICY_TYPE_ATTR_MAX = __NL_POLICY_TYPE_ATTR_MAX - 1
+};
+
 #endif /* __LINUX_NETLINK_H */
diff --git a/include/linux-private/linux/nexthop.h b/include/linux-private/linux/nexthop.h
new file mode 100644
index 0000000..37b14b4
--- /dev/null
+++ b/include/linux-private/linux/nexthop.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_NEXTHOP_H
+#define _LINUX_NEXTHOP_H
+
+#include <linux/types.h>
+
+struct nhmsg {
+	unsigned char	nh_family;
+	unsigned char	nh_scope;     /* return only */
+	unsigned char	nh_protocol;  /* Routing protocol that installed nh */
+	unsigned char	resvd;
+	unsigned int	nh_flags;     /* RTNH_F flags */
+};
+
+/* entry in a nexthop group */
+struct nexthop_grp {
+	__u32	id;	  /* nexthop id - must exist */
+	__u8	weight;   /* weight of this nexthop */
+	__u8	resvd1;
+	__u16	resvd2;
+};
+
+enum {
+	NEXTHOP_GRP_TYPE_MPATH,  /* hash-threshold nexthop group
+				  * default type if not specified
+				  */
+	NEXTHOP_GRP_TYPE_RES,    /* resilient nexthop group */
+	__NEXTHOP_GRP_TYPE_MAX,
+};
+
+#define NEXTHOP_GRP_TYPE_MAX (__NEXTHOP_GRP_TYPE_MAX - 1)
+
+enum {
+	NHA_UNSPEC,
+	NHA_ID,		/* u32; id for nexthop. id == 0 means auto-assign */
+
+	NHA_GROUP,	/* array of nexthop_grp */
+	NHA_GROUP_TYPE,	/* u16 one of NEXTHOP_GRP_TYPE */
+	/* if NHA_GROUP attribute is added, no other attributes can be set */
+
+	NHA_BLACKHOLE,	/* flag; nexthop used to blackhole packets */
+	/* if NHA_BLACKHOLE is added, OIF, GATEWAY, ENCAP can not be set */
+
+	NHA_OIF,	/* u32; nexthop device */
+	NHA_GATEWAY,	/* be32 (IPv4) or in6_addr (IPv6) gw address */
+	NHA_ENCAP_TYPE, /* u16; lwt encap type */
+	NHA_ENCAP,	/* lwt encap data */
+
+	/* NHA_OIF can be appended to dump request to return only
+	 * nexthops using given device
+	 */
+	NHA_GROUPS,	/* flag; only return nexthop groups in dump */
+	NHA_MASTER,	/* u32;  only return nexthops with given master dev */
+
+	NHA_FDB,	/* flag; nexthop belongs to a bridge fdb */
+	/* if NHA_FDB is added, OIF, BLACKHOLE, ENCAP cannot be set */
+
+	/* nested; resilient nexthop group attributes */
+	NHA_RES_GROUP,
+	/* nested; nexthop bucket attributes */
+	NHA_RES_BUCKET,
+
+	__NHA_MAX,
+};
+
+#define NHA_MAX	(__NHA_MAX - 1)
+
+enum {
+	NHA_RES_GROUP_UNSPEC,
+	/* Pad attribute for 64-bit alignment. */
+	NHA_RES_GROUP_PAD = NHA_RES_GROUP_UNSPEC,
+
+	/* u16; number of nexthop buckets in a resilient nexthop group */
+	NHA_RES_GROUP_BUCKETS,
+	/* clock_t as u32; nexthop bucket idle timer (per-group) */
+	NHA_RES_GROUP_IDLE_TIMER,
+	/* clock_t as u32; nexthop unbalanced timer */
+	NHA_RES_GROUP_UNBALANCED_TIMER,
+	/* clock_t as u64; nexthop unbalanced time */
+	NHA_RES_GROUP_UNBALANCED_TIME,
+
+	__NHA_RES_GROUP_MAX,
+};
+
+#define NHA_RES_GROUP_MAX	(__NHA_RES_GROUP_MAX - 1)
+
+enum {
+	NHA_RES_BUCKET_UNSPEC,
+	/* Pad attribute for 64-bit alignment. */
+	NHA_RES_BUCKET_PAD = NHA_RES_BUCKET_UNSPEC,
+
+	/* u16; nexthop bucket index */
+	NHA_RES_BUCKET_INDEX,
+	/* clock_t as u64; nexthop bucket idle time */
+	NHA_RES_BUCKET_IDLE_TIME,
+	/* u32; nexthop id assigned to the nexthop bucket */
+	NHA_RES_BUCKET_NH_ID,
+
+	__NHA_RES_BUCKET_MAX,
+};
+
+#define NHA_RES_BUCKET_MAX	(__NHA_RES_BUCKET_MAX - 1)
+
+#endif
diff --git a/include/linux-private/linux/pkt_cls.h b/include/linux-private/linux/pkt_cls.h
index be382fb..648a82f 100644
--- a/include/linux-private/linux/pkt_cls.h
+++ b/include/linux-private/linux/pkt_cls.h
@@ -16,9 +16,40 @@
 	TCA_ACT_STATS,
 	TCA_ACT_PAD,
 	TCA_ACT_COOKIE,
+	TCA_ACT_FLAGS,
+	TCA_ACT_HW_STATS,
+	TCA_ACT_USED_HW_STATS,
+	TCA_ACT_IN_HW_COUNT,
 	__TCA_ACT_MAX
 };
 
+/* See other TCA_ACT_FLAGS_ * flags in include/net/act_api.h. */
+#define TCA_ACT_FLAGS_NO_PERCPU_STATS (1 << 0) /* Don't use percpu allocator for
+						* actions stats.
+						*/
+#define TCA_ACT_FLAGS_SKIP_HW	(1 << 1) /* don't offload action to HW */
+#define TCA_ACT_FLAGS_SKIP_SW	(1 << 2) /* don't use action in SW */
+
+/* tca HW stats type
+ * When user does not pass the attribute, he does not care.
+ * It is the same as if he would pass the attribute with
+ * all supported bits set.
+ * In case no bits are set, user is not interested in getting any HW statistics.
+ */
+#define TCA_ACT_HW_STATS_IMMEDIATE (1 << 0) /* Means that in dump, user
+					     * gets the current HW stats
+					     * state from the device
+					     * queried at the dump time.
+					     */
+#define TCA_ACT_HW_STATS_DELAYED (1 << 1) /* Means that in dump, user gets
+					   * HW stats that might be out of date
+					   * for some time, maybe couple of
+					   * seconds. This is the case when
+					   * driver polls stats updates
+					   * periodically or when it gets async
+					   * stats update from the device.
+					   */
+
 #define TCA_ACT_MAX __TCA_ACT_MAX
 #define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
 #define TCA_ACT_MAX_PRIO 32
@@ -63,12 +94,53 @@
 #define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
 #define TC_ACT_EXT_OPCODE_MAX	TC_ACT_GOTO_CHAIN
 
+/* These macros are put here for binary compatibility with userspace apps that
+ * make use of them. For kernel code and new userspace apps, use the TCA_ID_*
+ * versions.
+ */
+#define TCA_ACT_GACT 5
+#define TCA_ACT_IPT 6
+#define TCA_ACT_PEDIT 7
+#define TCA_ACT_MIRRED 8
+#define TCA_ACT_NAT 9
+#define TCA_ACT_XT 10
+#define TCA_ACT_SKBEDIT 11
+#define TCA_ACT_VLAN 12
+#define TCA_ACT_BPF 13
+#define TCA_ACT_CONNMARK 14
+#define TCA_ACT_SKBMOD 15
+#define TCA_ACT_CSUM 16
+#define TCA_ACT_TUNNEL_KEY 17
+#define TCA_ACT_SIMP 22
+#define TCA_ACT_IFE 25
+#define TCA_ACT_SAMPLE 26
+
 /* Action type identifiers*/
-enum {
-	TCA_ID_UNSPEC=0,
-	TCA_ID_POLICE=1,
+enum tca_id {
+	TCA_ID_UNSPEC = 0,
+	TCA_ID_POLICE = 1,
+	TCA_ID_GACT = TCA_ACT_GACT,
+	TCA_ID_IPT = TCA_ACT_IPT,
+	TCA_ID_PEDIT = TCA_ACT_PEDIT,
+	TCA_ID_MIRRED = TCA_ACT_MIRRED,
+	TCA_ID_NAT = TCA_ACT_NAT,
+	TCA_ID_XT = TCA_ACT_XT,
+	TCA_ID_SKBEDIT = TCA_ACT_SKBEDIT,
+	TCA_ID_VLAN = TCA_ACT_VLAN,
+	TCA_ID_BPF = TCA_ACT_BPF,
+	TCA_ID_CONNMARK = TCA_ACT_CONNMARK,
+	TCA_ID_SKBMOD = TCA_ACT_SKBMOD,
+	TCA_ID_CSUM = TCA_ACT_CSUM,
+	TCA_ID_TUNNEL_KEY = TCA_ACT_TUNNEL_KEY,
+	TCA_ID_SIMP = TCA_ACT_SIMP,
+	TCA_ID_IFE = TCA_ACT_IFE,
+	TCA_ID_SAMPLE = TCA_ACT_SAMPLE,
+	TCA_ID_CTINFO,
+	TCA_ID_MPLS,
+	TCA_ID_CT,
+	TCA_ID_GATE,
 	/* other actions go here */
-	__TCA_ID_MAX=255
+	__TCA_ID_MAX = 255
 };
 
 #define TCA_ID_MAX __TCA_ID_MAX
@@ -120,6 +192,10 @@
 	TCA_POLICE_RESULT,
 	TCA_POLICE_TM,
 	TCA_POLICE_PAD,
+	TCA_POLICE_RATE64,
+	TCA_POLICE_PEAKRATE64,
+	TCA_POLICE_PKTRATE64,
+	TCA_POLICE_PKTBURST64,
 	__TCA_POLICE_MAX
 #define TCA_POLICE_RESULT TCA_POLICE_RESULT
 };
@@ -180,7 +256,7 @@
 
 	short			hoff;
 	__be32			hmask;
-	struct tc_u32_key	keys[0];
+	struct tc_u32_key	keys[];
 };
 
 struct tc_u32_mark {
@@ -192,7 +268,7 @@
 struct tc_u32_pcnt {
 	__u64 rcnt;
 	__u64 rhit;
-	__u64 kcnts[0];
+	__u64 kcnts[];
 };
 
 /* Flags */
@@ -257,7 +333,7 @@
 	TCA_FW_UNSPEC,
 	TCA_FW_CLASSID,
 	TCA_FW_POLICE,
-	TCA_FW_INDEV, /*  used by CONFIG_NET_CLS_IND */
+	TCA_FW_INDEV,
 	TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
 	TCA_FW_MASK,
 	__TCA_FW_MAX
@@ -333,12 +409,19 @@
 
 /* Basic filter */
 
+struct tc_basic_pcnt {
+	__u64 rcnt;
+	__u64 rhit;
+};
+
 enum {
 	TCA_BASIC_UNSPEC,
 	TCA_BASIC_CLASSID,
 	TCA_BASIC_EMATCHES,
 	TCA_BASIC_ACT,
 	TCA_BASIC_POLICE,
+	TCA_BASIC_PCNT,
+	TCA_BASIC_PAD,
 	__TCA_BASIC_MAX
 };
 
@@ -483,17 +566,67 @@
 	TCA_FLOWER_KEY_ENC_OPTS,
 	TCA_FLOWER_KEY_ENC_OPTS_MASK,
 
+	TCA_FLOWER_IN_HW_COUNT,
+
+	TCA_FLOWER_KEY_PORT_SRC_MIN,	/* be16 */
+	TCA_FLOWER_KEY_PORT_SRC_MAX,	/* be16 */
+	TCA_FLOWER_KEY_PORT_DST_MIN,	/* be16 */
+	TCA_FLOWER_KEY_PORT_DST_MAX,	/* be16 */
+
+	TCA_FLOWER_KEY_CT_STATE,	/* u16 */
+	TCA_FLOWER_KEY_CT_STATE_MASK,	/* u16 */
+	TCA_FLOWER_KEY_CT_ZONE,		/* u16 */
+	TCA_FLOWER_KEY_CT_ZONE_MASK,	/* u16 */
+	TCA_FLOWER_KEY_CT_MARK,		/* u32 */
+	TCA_FLOWER_KEY_CT_MARK_MASK,	/* u32 */
+	TCA_FLOWER_KEY_CT_LABELS,	/* u128 */
+	TCA_FLOWER_KEY_CT_LABELS_MASK,	/* u128 */
+
+	TCA_FLOWER_KEY_MPLS_OPTS,
+
+	TCA_FLOWER_KEY_HASH,		/* u32 */
+	TCA_FLOWER_KEY_HASH_MASK,	/* u32 */
+
+	TCA_FLOWER_KEY_NUM_OF_VLANS,    /* u8 */
+
+	TCA_FLOWER_KEY_PPPOE_SID,	/* be16 */
+	TCA_FLOWER_KEY_PPP_PROTO,	/* be16 */
+
+	TCA_FLOWER_KEY_L2TPV3_SID,	/* be32 */
+
 	__TCA_FLOWER_MAX,
 };
 
 #define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
 
 enum {
+	TCA_FLOWER_KEY_CT_FLAGS_NEW = 1 << 0, /* Beginning of a new connection. */
+	TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */
+	TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */
+	TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */
+	TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */
+	TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */
+	__TCA_FLOWER_KEY_CT_FLAGS_MAX,
+};
+
+enum {
 	TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
 	TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
 					 * TCA_FLOWER_KEY_ENC_OPT_GENEVE_
 					 * attributes
 					 */
+	TCA_FLOWER_KEY_ENC_OPTS_VXLAN,	/* Nested
+					 * TCA_FLOWER_KEY_ENC_OPT_VXLAN_
+					 * attributes
+					 */
+	TCA_FLOWER_KEY_ENC_OPTS_ERSPAN,	/* Nested
+					 * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_
+					 * attributes
+					 */
+	TCA_FLOWER_KEY_ENC_OPTS_GTP,	/* Nested
+					 * TCA_FLOWER_KEY_ENC_OPT_GTP_
+					 * attributes
+					 */
 	__TCA_FLOWER_KEY_ENC_OPTS_MAX,
 };
 
@@ -512,17 +645,78 @@
 		(__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
 
 enum {
+	TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC,
+	TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP,		/* u32 */
+	__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \
+		(__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1)
+
+enum {
+	TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC,
+	TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER,              /* u8 */
+	TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX,            /* be32 */
+	TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR,              /* u8 */
+	TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID,             /* u8 */
+	__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \
+		(__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
+
+enum {
+	TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC,
+	TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE,		/* u8 */
+	TCA_FLOWER_KEY_ENC_OPT_GTP_QFI,			/* u8 */
+
+	__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX \
+		(__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1)
+
+enum {
+	TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
+	TCA_FLOWER_KEY_MPLS_OPTS_LSE,
+	__TCA_FLOWER_KEY_MPLS_OPTS_MAX,
+};
+
+#define TCA_FLOWER_KEY_MPLS_OPTS_MAX (__TCA_FLOWER_KEY_MPLS_OPTS_MAX - 1)
+
+enum {
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_UNSPEC,
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH,
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL,
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS,
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_TC,
+	TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL,
+	__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX,
+};
+
+#define TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX \
+		(__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX - 1)
+
+enum {
 	TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
 	TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
 };
 
+#define TCA_FLOWER_MASK_FLAGS_RANGE	(1 << 0) /* Range-based match */
+
 /* Match-all classifier */
 
+struct tc_matchall_pcnt {
+	__u64 rhit;
+};
+
 enum {
 	TCA_MATCHALL_UNSPEC,
 	TCA_MATCHALL_CLASSID,
 	TCA_MATCHALL_ACT,
 	TCA_MATCHALL_FLAGS,
+	TCA_MATCHALL_PCNT,
+	TCA_MATCHALL_PAD,
 	__TCA_MATCHALL_MAX,
 };
 
diff --git a/include/linux-private/linux/pkt_sched.h b/include/linux-private/linux/pkt_sched.h
index 8975fd1..51a7add 100644
--- a/include/linux-private/linux/pkt_sched.h
+++ b/include/linux-private/linux/pkt_sched.h
@@ -2,6 +2,7 @@
 #ifndef __LINUX_PKT_SCHED_H
 #define __LINUX_PKT_SCHED_H
 
+#include <linux/const.h>
 #include <linux/types.h>
 
 /* Logical priority bands not depending on specific packet scheduler.
@@ -255,6 +256,9 @@
 	TCA_RED_PARMS,
 	TCA_RED_STAB,
 	TCA_RED_MAX_P,
+	TCA_RED_FLAGS,		/* bitfield32 */
+	TCA_RED_EARLY_DROP_BLOCK, /* u32 */
+	TCA_RED_MARK_BLOCK,	/* u32 */
 	__TCA_RED_MAX,
 };
 
@@ -267,12 +271,28 @@
 	unsigned char   Wlog;		/* log(W)		*/
 	unsigned char   Plog;		/* log(P_max/(qth_max-qth_min))	*/
 	unsigned char   Scell_log;	/* cell size for idle damping */
+
+	/* This field can be used for flags that a RED-like qdisc has
+	 * historically supported. E.g. when configuring RED, it can be used for
+	 * ECN, HARDDROP and ADAPTATIVE. For SFQ it can be used for ECN,
+	 * HARDDROP. Etc. Because this field has not been validated, and is
+	 * copied back on dump, any bits besides those to which a given qdisc
+	 * has assigned a historical meaning need to be considered for free use
+	 * by userspace tools.
+	 *
+	 * Any further flags need to be passed differently, e.g. through an
+	 * attribute (such as TCA_RED_FLAGS above). Such attribute should allow
+	 * passing both recent and historic flags in one value.
+	 */
 	unsigned char	flags;
 #define TC_RED_ECN		1
 #define TC_RED_HARDDROP		2
 #define TC_RED_ADAPTATIVE	4
+#define TC_RED_NODROP		8
 };
 
+#define TC_RED_HISTORIC_FLAGS (TC_RED_ECN | TC_RED_HARDDROP | TC_RED_ADAPTATIVE)
+
 struct tc_red_xstats {
 	__u32           early;          /* Early drops */
 	__u32           pdrop;          /* Drops due to queue limits */
@@ -291,11 +311,38 @@
        TCA_GRED_DPS,
        TCA_GRED_MAX_P,
        TCA_GRED_LIMIT,
+       TCA_GRED_VQ_LIST,	/* nested TCA_GRED_VQ_ENTRY */
        __TCA_GRED_MAX,
 };
 
 #define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
 
+enum {
+	TCA_GRED_VQ_ENTRY_UNSPEC,
+	TCA_GRED_VQ_ENTRY,	/* nested TCA_GRED_VQ_* */
+	__TCA_GRED_VQ_ENTRY_MAX,
+};
+#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
+
+enum {
+	TCA_GRED_VQ_UNSPEC,
+	TCA_GRED_VQ_PAD,
+	TCA_GRED_VQ_DP,			/* u32 */
+	TCA_GRED_VQ_STAT_BYTES,		/* u64 */
+	TCA_GRED_VQ_STAT_PACKETS,	/* u32 */
+	TCA_GRED_VQ_STAT_BACKLOG,	/* u32 */
+	TCA_GRED_VQ_STAT_PROB_DROP,	/* u32 */
+	TCA_GRED_VQ_STAT_PROB_MARK,	/* u32 */
+	TCA_GRED_VQ_STAT_FORCED_DROP,	/* u32 */
+	TCA_GRED_VQ_STAT_FORCED_MARK,	/* u32 */
+	TCA_GRED_VQ_STAT_PDROP,		/* u32 */
+	TCA_GRED_VQ_STAT_OTHER,		/* u32 */
+	TCA_GRED_VQ_FLAGS,		/* u32 */
+	__TCA_GRED_VQ_MAX
+};
+
+#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
+
 struct tc_gred_qopt {
 	__u32		limit;        /* HARD maximal queue length (bytes)    */
 	__u32		qth_min;      /* Min average length threshold (bytes) */
@@ -387,6 +434,7 @@
 	TCA_HTB_RATE64,
 	TCA_HTB_CEIL64,
 	TCA_HTB_PAD,
+	TCA_HTB_OFFLOAD,
 	__TCA_HTB_MAX,
 };
 
@@ -395,9 +443,9 @@
 struct tc_htb_xstats {
 	__u32 lends;
 	__u32 borrows;
-	__u32 giants;	/* too big packets (rate will not be accurate) */
-	__u32 tokens;
-	__u32 ctokens;
+	__u32 giants;	/* unused since 'Make HTB scheduler work with TSO.' */
+	__s32 tokens;
+	__s32 ctokens;
 };
 
 /* HFSC section */
@@ -671,6 +719,11 @@
 
 #define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
 
+enum {
+	TC_FP_EXPRESS = 1,
+	TC_FP_PREEMPTIBLE = 2,
+};
+
 struct tc_mqprio_qopt {
 	__u8	num_tc;
 	__u8	prio_tc_map[TC_QOPT_BITMASK + 1];
@@ -685,11 +738,22 @@
 #define TC_MQPRIO_F_MAX_RATE		0x8
 
 enum {
+	TCA_MQPRIO_TC_ENTRY_UNSPEC,
+	TCA_MQPRIO_TC_ENTRY_INDEX,		/* u32 */
+	TCA_MQPRIO_TC_ENTRY_FP,			/* u32 */
+
+	/* add new constants above here */
+	__TCA_MQPRIO_TC_ENTRY_CNT,
+	TCA_MQPRIO_TC_ENTRY_MAX = (__TCA_MQPRIO_TC_ENTRY_CNT - 1)
+};
+
+enum {
 	TCA_MQPRIO_UNSPEC,
 	TCA_MQPRIO_MODE,
 	TCA_MQPRIO_SHAPER,
 	TCA_MQPRIO_MIN_RATE64,
 	TCA_MQPRIO_MAX_RATE64,
+	TCA_MQPRIO_TC_ENTRY,
 	__TCA_MQPRIO_MAX,
 };
 
@@ -779,6 +843,8 @@
 
 /* FQ_CODEL */
 
+#define FQ_CODEL_QUANTUM_MAX (1 << 20)
+
 enum {
 	TCA_FQ_CODEL_UNSPEC,
 	TCA_FQ_CODEL_TARGET,
@@ -790,6 +856,8 @@
 	TCA_FQ_CODEL_CE_THRESHOLD,
 	TCA_FQ_CODEL_DROP_BATCH_SIZE,
 	TCA_FQ_CODEL_MEMORY_LIMIT,
+	TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR,
+	TCA_FQ_CODEL_CE_THRESHOLD_MASK,
 	__TCA_FQ_CODEL_MAX
 };
 
@@ -864,6 +932,14 @@
 
 	TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */
 
+	TCA_FQ_CE_THRESHOLD,	/* DCTCP-like CE-marking threshold */
+
+	TCA_FQ_TIMER_SLACK,	/* timer slack */
+
+	TCA_FQ_HORIZON,		/* time horizon in us */
+
+	TCA_FQ_HORIZON_DROP,	/* drop packets beyond horizon, or cap their EDT */
+
 	__TCA_FQ_MAX
 };
 
@@ -882,6 +958,9 @@
 	__u32	inactive_flows;
 	__u32	throttled_flows;
 	__u32	unthrottle_latency_ns;
+	__u64	ce_mark;		/* packets above ce_threshold */
+	__u64	horizon_drops;
+	__u64	horizon_caps;
 };
 
 /* Heavy-Hitter Filter */
@@ -919,19 +998,56 @@
 	TCA_PIE_BETA,
 	TCA_PIE_ECN,
 	TCA_PIE_BYTEMODE,
+	TCA_PIE_DQ_RATE_ESTIMATOR,
 	__TCA_PIE_MAX
 };
 #define TCA_PIE_MAX   (__TCA_PIE_MAX - 1)
 
 struct tc_pie_xstats {
-	__u32 prob;             /* current probability */
-	__u32 delay;            /* current delay in ms */
-	__u32 avg_dq_rate;      /* current average dq_rate in bits/pie_time */
-	__u32 packets_in;       /* total number of packets enqueued */
-	__u32 dropped;          /* packets dropped due to pie_action */
-	__u32 overlimit;        /* dropped due to lack of space in queue */
-	__u32 maxq;             /* maximum queue size */
-	__u32 ecn_mark;         /* packets marked with ecn*/
+	__u64 prob;			/* current probability */
+	__u32 delay;			/* current delay in ms */
+	__u32 avg_dq_rate;		/* current average dq_rate in
+					 * bits/pie_time
+					 */
+	__u32 dq_rate_estimating;	/* is avg_dq_rate being calculated? */
+	__u32 packets_in;		/* total number of packets enqueued */
+	__u32 dropped;			/* packets dropped due to pie_action */
+	__u32 overlimit;		/* dropped due to lack of space
+					 * in queue
+					 */
+	__u32 maxq;			/* maximum queue size */
+	__u32 ecn_mark;			/* packets marked with ecn*/
+};
+
+/* FQ PIE */
+enum {
+	TCA_FQ_PIE_UNSPEC,
+	TCA_FQ_PIE_LIMIT,
+	TCA_FQ_PIE_FLOWS,
+	TCA_FQ_PIE_TARGET,
+	TCA_FQ_PIE_TUPDATE,
+	TCA_FQ_PIE_ALPHA,
+	TCA_FQ_PIE_BETA,
+	TCA_FQ_PIE_QUANTUM,
+	TCA_FQ_PIE_MEMORY_LIMIT,
+	TCA_FQ_PIE_ECN_PROB,
+	TCA_FQ_PIE_ECN,
+	TCA_FQ_PIE_BYTEMODE,
+	TCA_FQ_PIE_DQ_RATE_ESTIMATOR,
+	__TCA_FQ_PIE_MAX
+};
+#define TCA_FQ_PIE_MAX   (__TCA_FQ_PIE_MAX - 1)
+
+struct tc_fq_pie_xstats {
+	__u32 packets_in;	/* total number of packets enqueued */
+	__u32 dropped;		/* packets dropped due to fq_pie_action */
+	__u32 overlimit;	/* dropped due to lack of space in queue */
+	__u32 overmemory;	/* dropped due to lack of memory in queue */
+	__u32 ecn_mark;		/* packets marked with ecn */
+	__u32 new_flow_count;	/* count of new flows created by packets */
+	__u32 new_flows_len;	/* count of flows in new list */
+	__u32 old_flows_len;	/* count of flows in old list */
+	__u32 memory_usage;	/* total memory across all queues */
 };
 
 /* CBS */
@@ -958,8 +1074,9 @@
 	__s32 delta;
 	__s32 clockid;
 	__u32 flags;
-#define TC_ETF_DEADLINE_MODE_ON	BIT(0)
-#define TC_ETF_OFFLOAD_ON	BIT(1)
+#define TC_ETF_DEADLINE_MODE_ON	_BITUL(0)
+#define TC_ETF_OFFLOAD_ON	_BITUL(1)
+#define TC_ETF_SKIP_SOCK_CHECK	_BITUL(2)
 };
 
 enum {
@@ -991,6 +1108,7 @@
 	TCA_CAKE_INGRESS,
 	TCA_CAKE_ACK_FILTER,
 	TCA_CAKE_SPLIT_GSO,
+	TCA_CAKE_FWMARK,
 	__TCA_CAKE_MAX
 };
 #define TCA_CAKE_MAX	(__TCA_CAKE_MAX - 1)
@@ -1084,4 +1202,97 @@
 	CAKE_ATM_MAX
 };
 
+
+/* TAPRIO */
+enum {
+	TC_TAPRIO_CMD_SET_GATES = 0x00,
+	TC_TAPRIO_CMD_SET_AND_HOLD = 0x01,
+	TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02,
+};
+
+enum {
+	TCA_TAPRIO_SCHED_ENTRY_UNSPEC,
+	TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */
+	TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */
+	TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */
+	TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */
+	__TCA_TAPRIO_SCHED_ENTRY_MAX,
+};
+#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1)
+
+/* The format for schedule entry list is:
+ * [TCA_TAPRIO_SCHED_ENTRY_LIST]
+ *   [TCA_TAPRIO_SCHED_ENTRY]
+ *     [TCA_TAPRIO_SCHED_ENTRY_CMD]
+ *     [TCA_TAPRIO_SCHED_ENTRY_GATES]
+ *     [TCA_TAPRIO_SCHED_ENTRY_INTERVAL]
+ */
+enum {
+	TCA_TAPRIO_SCHED_UNSPEC,
+	TCA_TAPRIO_SCHED_ENTRY,
+	__TCA_TAPRIO_SCHED_MAX,
+};
+
+#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
+
+/* The format for the admin sched (dump only):
+ * [TCA_TAPRIO_SCHED_ADMIN_SCHED]
+ *   [TCA_TAPRIO_ATTR_SCHED_BASE_TIME]
+ *   [TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST]
+ *     [TCA_TAPRIO_ATTR_SCHED_ENTRY]
+ *       [TCA_TAPRIO_ATTR_SCHED_ENTRY_CMD]
+ *       [TCA_TAPRIO_ATTR_SCHED_ENTRY_GATES]
+ *       [TCA_TAPRIO_ATTR_SCHED_ENTRY_INTERVAL]
+ */
+
+#define TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST	_BITUL(0)
+#define TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD	_BITUL(1)
+
+enum {
+	TCA_TAPRIO_TC_ENTRY_UNSPEC,
+	TCA_TAPRIO_TC_ENTRY_INDEX,		/* u32 */
+	TCA_TAPRIO_TC_ENTRY_MAX_SDU,		/* u32 */
+	TCA_TAPRIO_TC_ENTRY_FP,			/* u32 */
+
+	/* add new constants above here */
+	__TCA_TAPRIO_TC_ENTRY_CNT,
+	TCA_TAPRIO_TC_ENTRY_MAX = (__TCA_TAPRIO_TC_ENTRY_CNT - 1)
+};
+
+enum {
+	TCA_TAPRIO_ATTR_UNSPEC,
+	TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
+	TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */
+	TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */
+	TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
+	TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
+	TCA_TAPRIO_PAD,
+	TCA_TAPRIO_ATTR_ADMIN_SCHED, /* The admin sched, only used in dump */
+	TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME, /* s64 */
+	TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */
+	TCA_TAPRIO_ATTR_FLAGS, /* u32 */
+	TCA_TAPRIO_ATTR_TXTIME_DELAY, /* u32 */
+	TCA_TAPRIO_ATTR_TC_ENTRY, /* nest */
+	__TCA_TAPRIO_ATTR_MAX,
+};
+
+#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
+
+/* ETS */
+
+#define TCQ_ETS_MAX_BANDS 16
+
+enum {
+	TCA_ETS_UNSPEC,
+	TCA_ETS_NBANDS,		/* u8 */
+	TCA_ETS_NSTRICT,	/* u8 */
+	TCA_ETS_QUANTA,		/* nested TCA_ETS_QUANTA_BAND */
+	TCA_ETS_QUANTA_BAND,	/* u32 */
+	TCA_ETS_PRIOMAP,	/* nested TCA_ETS_PRIOMAP_BAND */
+	TCA_ETS_PRIOMAP_BAND,	/* u8 */
+	__TCA_ETS_MAX,
+};
+
+#define TCA_ETS_MAX (__TCA_ETS_MAX - 1)
+
 #endif
diff --git a/include/linux-private/linux/posix_types.h b/include/linux-private/linux/posix_types.h
new file mode 100644
index 0000000..9a7a740
--- /dev/null
+++ b/include/linux-private/linux/posix_types.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_POSIX_TYPES_H
+#define _LINUX_POSIX_TYPES_H
+
+#include <linux/stddef.h>
+
+/*
+ * This allows for 1024 file descriptors: if NR_OPEN is ever grown
+ * beyond that you'll have to change this too. But 1024 fd's seem to be
+ * enough even for such "real" unices like OSF/1, so hopefully this is
+ * one limit that doesn't have to be changed [again].
+ *
+ * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
+ * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
+ * place for them. Solved by having dummy defines in <sys/time.h>.
+ */
+
+/*
+ * This macro may have been defined in <gnu/types.h>. But we always
+ * use the one here.
+ */
+#undef __FD_SETSIZE
+#define __FD_SETSIZE	1024
+
+typedef struct {
+	unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))];
+} __kernel_fd_set;
+
+/* Type of a signal handler.  */
+typedef void (*__kernel_sighandler_t)(int);
+
+/* Type of a SYSV IPC key.  */
+typedef int __kernel_key_t;
+typedef int __kernel_mqd_t;
+
+#include <asm/posix_types.h>
+
+#endif /* _LINUX_POSIX_TYPES_H */
diff --git a/include/linux-private/linux/rtnetlink.h b/include/linux-private/linux/rtnetlink.h
index 8c1d600..2132e94 100644
--- a/include/linux-private/linux/rtnetlink.h
+++ b/include/linux-private/linux/rtnetlink.h
@@ -146,6 +146,8 @@
 #define RTM_NEWSTATS RTM_NEWSTATS
 	RTM_GETSTATS = 94,
 #define RTM_GETSTATS RTM_GETSTATS
+	RTM_SETSTATS,
+#define RTM_SETSTATS RTM_SETSTATS
 
 	RTM_NEWCACHEREPORT = 96,
 #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
@@ -157,6 +159,41 @@
 	RTM_GETCHAIN,
 #define RTM_GETCHAIN RTM_GETCHAIN
 
+	RTM_NEWNEXTHOP = 104,
+#define RTM_NEWNEXTHOP	RTM_NEWNEXTHOP
+	RTM_DELNEXTHOP,
+#define RTM_DELNEXTHOP	RTM_DELNEXTHOP
+	RTM_GETNEXTHOP,
+#define RTM_GETNEXTHOP	RTM_GETNEXTHOP
+
+	RTM_NEWLINKPROP = 108,
+#define RTM_NEWLINKPROP	RTM_NEWLINKPROP
+	RTM_DELLINKPROP,
+#define RTM_DELLINKPROP	RTM_DELLINKPROP
+	RTM_GETLINKPROP,
+#define RTM_GETLINKPROP	RTM_GETLINKPROP
+
+	RTM_NEWVLAN = 112,
+#define RTM_NEWNVLAN	RTM_NEWVLAN
+	RTM_DELVLAN,
+#define RTM_DELVLAN	RTM_DELVLAN
+	RTM_GETVLAN,
+#define RTM_GETVLAN	RTM_GETVLAN
+
+	RTM_NEWNEXTHOPBUCKET = 116,
+#define RTM_NEWNEXTHOPBUCKET	RTM_NEWNEXTHOPBUCKET
+	RTM_DELNEXTHOPBUCKET,
+#define RTM_DELNEXTHOPBUCKET	RTM_DELNEXTHOPBUCKET
+	RTM_GETNEXTHOPBUCKET,
+#define RTM_GETNEXTHOPBUCKET	RTM_GETNEXTHOPBUCKET
+
+	RTM_NEWTUNNEL = 120,
+#define RTM_NEWTUNNEL	RTM_NEWTUNNEL
+	RTM_DELTUNNEL,
+#define RTM_DELTUNNEL	RTM_DELTUNNEL
+	RTM_GETTUNNEL,
+#define RTM_GETTUNNEL	RTM_GETTUNNEL
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -236,12 +273,12 @@
 
 /* rtm_protocol */
 
-#define RTPROT_UNSPEC	0
-#define RTPROT_REDIRECT	1	/* Route installed by ICMP redirects;
-				   not used by current IPv4 */
-#define RTPROT_KERNEL	2	/* Route installed by kernel		*/
-#define RTPROT_BOOT	3	/* Route installed during boot		*/
-#define RTPROT_STATIC	4	/* Route installed by administrator	*/
+#define RTPROT_UNSPEC		0
+#define RTPROT_REDIRECT		1	/* Route installed by ICMP redirects;
+					   not used by current IPv4 */
+#define RTPROT_KERNEL		2	/* Route installed by kernel		*/
+#define RTPROT_BOOT		3	/* Route installed during boot		*/
+#define RTPROT_STATIC		4	/* Route installed by administrator	*/
 
 /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel;
    they are just passed from user and back as is.
@@ -250,22 +287,24 @@
    avoid conflicts.
  */
 
-#define RTPROT_GATED	8	/* Apparently, GateD */
-#define RTPROT_RA	9	/* RDISC/ND router advertisements */
-#define RTPROT_MRT	10	/* Merit MRT */
-#define RTPROT_ZEBRA	11	/* Zebra */
-#define RTPROT_BIRD	12	/* BIRD */
-#define RTPROT_DNROUTED	13	/* DECnet routing daemon */
-#define RTPROT_XORP	14	/* XORP */
-#define RTPROT_NTK	15	/* Netsukuku */
-#define RTPROT_DHCP	16      /* DHCP client */
-#define RTPROT_MROUTED	17      /* Multicast daemon */
-#define RTPROT_BABEL	42      /* Babel daemon */
-#define RTPROT_BGP	186     /* BGP Routes */
-#define RTPROT_ISIS	187     /* ISIS Routes */
-#define RTPROT_OSPF	188     /* OSPF Routes */
-#define RTPROT_RIP	189     /* RIP Routes */
-#define RTPROT_EIGRP	192     /* EIGRP Routes */
+#define RTPROT_GATED		8	/* Apparently, GateD */
+#define RTPROT_RA		9	/* RDISC/ND router advertisements */
+#define RTPROT_MRT		10	/* Merit MRT */
+#define RTPROT_ZEBRA		11	/* Zebra */
+#define RTPROT_BIRD		12	/* BIRD */
+#define RTPROT_DNROUTED		13	/* DECnet routing daemon */
+#define RTPROT_XORP		14	/* XORP */
+#define RTPROT_NTK		15	/* Netsukuku */
+#define RTPROT_DHCP		16	/* DHCP client */
+#define RTPROT_MROUTED		17	/* Multicast daemon */
+#define RTPROT_KEEPALIVED	18	/* Keepalived daemon */
+#define RTPROT_BABEL		42	/* Babel daemon */
+#define RTPROT_OPENR		99	/* Open Routing (Open/R) Routes */
+#define RTPROT_BGP		186	/* BGP Routes */
+#define RTPROT_ISIS		187	/* ISIS Routes */
+#define RTPROT_OSPF		188	/* OSPF Routes */
+#define RTPROT_RIP		189	/* RIP Routes */
+#define RTPROT_EIGRP		192	/* EIGRP Routes */
 
 /* rtm_scope
 
@@ -295,6 +334,13 @@
 #define RTM_F_PREFIX		0x800	/* Prefix addresses		*/
 #define RTM_F_LOOKUP_TABLE	0x1000	/* set rtm_table to FIB lookup result */
 #define RTM_F_FIB_MATCH	        0x2000	/* return full fib lookup match */
+#define RTM_F_OFFLOAD		0x4000	/* route is offloaded */
+#define RTM_F_TRAP		0x8000	/* route is trapping packets */
+#define RTM_F_OFFLOAD_FAILED	0x20000000 /* route offload failed, this value
+					    * is chosen to avoid conflicts with
+					    * other flags defined in
+					    * include/uapi/linux/ipv6_route.h
+					    */
 
 /* Reserved table identifiers */
 
@@ -342,6 +388,7 @@
 	RTA_IP_PROTO,
 	RTA_SPORT,
 	RTA_DPORT,
+	RTA_NH_ID,
 	__RTA_MAX
 };
 
@@ -371,11 +418,13 @@
 #define RTNH_F_DEAD		1	/* Nexthop is dead (used by multipath)	*/
 #define RTNH_F_PERVASIVE	2	/* Do recursive gateway lookup	*/
 #define RTNH_F_ONLINK		4	/* Gateway is forced on link	*/
-#define RTNH_F_OFFLOAD		8	/* offloaded route */
+#define RTNH_F_OFFLOAD		8	/* Nexthop is offloaded */
 #define RTNH_F_LINKDOWN		16	/* carrier-down on nexthop */
 #define RTNH_F_UNRESOLVED	32	/* The entry is unresolved (ipmr) */
+#define RTNH_F_TRAP		64	/* Nexthop is trapping packets */
 
-#define RTNH_COMPARE_MASK	(RTNH_F_DEAD | RTNH_F_LINKDOWN | RTNH_F_OFFLOAD)
+#define RTNH_COMPARE_MASK	(RTNH_F_DEAD | RTNH_F_LINKDOWN | \
+				 RTNH_F_OFFLOAD | RTNH_F_TRAP)
 
 /* Macros to handle hexthops */
 
@@ -391,7 +440,7 @@
 /* RTA_VIA */
 struct rtvia {
 	__kernel_sa_family_t	rtvia_family;
-	__u8			rtvia_addr[0];
+	__u8			rtvia_addr[];
 };
 
 /* RTM_CACHEINFO */
@@ -585,11 +634,18 @@
 	TCA_HW_OFFLOAD,
 	TCA_INGRESS_BLOCK,
 	TCA_EGRESS_BLOCK,
+	TCA_DUMP_FLAGS,
+	TCA_EXT_WARN_MSG,
 	__TCA_MAX
 };
 
 #define TCA_MAX (__TCA_MAX - 1)
 
+#define TCA_DUMP_FLAGS_TERSE (1 << 0) /* Means that in dump user gets only basic
+				       * data necessary to identify the objects
+				       * (handle, cookie, etc.) and stats.
+				       */
+
 #define TCA_RTA(r)  ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
@@ -702,6 +758,16 @@
 #define RTNLGRP_IPV4_MROUTE_R	RTNLGRP_IPV4_MROUTE_R
 	RTNLGRP_IPV6_MROUTE_R,
 #define RTNLGRP_IPV6_MROUTE_R	RTNLGRP_IPV6_MROUTE_R
+	RTNLGRP_NEXTHOP,
+#define RTNLGRP_NEXTHOP		RTNLGRP_NEXTHOP
+	RTNLGRP_BRVLAN,
+#define RTNLGRP_BRVLAN		RTNLGRP_BRVLAN
+	RTNLGRP_MCTP_IFADDR,
+#define RTNLGRP_MCTP_IFADDR	RTNLGRP_MCTP_IFADDR
+	RTNLGRP_TUNNEL,
+#define RTNLGRP_TUNNEL		RTNLGRP_TUNNEL
+	RTNLGRP_STATS,
+#define RTNLGRP_STATS		RTNLGRP_STATS
 	__RTNLGRP_MAX
 };
 #define RTNLGRP_MAX	(__RTNLGRP_MAX - 1)
@@ -721,6 +787,7 @@
 	TCA_ROOT_FLAGS,
 	TCA_ROOT_COUNT,
 	TCA_ROOT_TIME_DELTA, /* in msecs */
+	TCA_ROOT_EXT_WARN_MSG,
 	__TCA_ROOT_MAX,
 #define	TCA_ROOT_MAX (__TCA_ROOT_MAX - 1)
 };
@@ -729,18 +796,28 @@
 #define TA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcamsg))
 /* tcamsg flags stored in attribute TCA_ROOT_FLAGS
  *
- * TCA_FLAG_LARGE_DUMP_ON user->kernel to request for larger than TCA_ACT_MAX_PRIO
- * actions in a dump. All dump responses will contain the number of actions
- * being dumped stored in for user app's consumption in TCA_ROOT_COUNT
+ * TCA_ACT_FLAG_LARGE_DUMP_ON user->kernel to request for larger than
+ * TCA_ACT_MAX_PRIO actions in a dump. All dump responses will contain the
+ * number of actions being dumped stored in for user app's consumption in
+ * TCA_ROOT_COUNT
+ *
+ * TCA_ACT_FLAG_TERSE_DUMP user->kernel to request terse (brief) dump that only
+ * includes essential action info (kind, index, etc.)
  *
  */
 #define TCA_FLAG_LARGE_DUMP_ON		(1 << 0)
+#define TCA_ACT_FLAG_LARGE_DUMP_ON	TCA_FLAG_LARGE_DUMP_ON
+#define TCA_ACT_FLAG_TERSE_DUMP		(1 << 1)
 
 /* New extended info filters for IFLA_EXT_MASK */
 #define RTEXT_FILTER_VF		(1 << 0)
 #define RTEXT_FILTER_BRVLAN	(1 << 1)
 #define RTEXT_FILTER_BRVLAN_COMPRESSED	(1 << 2)
 #define	RTEXT_FILTER_SKIP_STATS	(1 << 3)
+#define RTEXT_FILTER_MRP	(1 << 4)
+#define RTEXT_FILTER_CFM_CONFIG	(1 << 5)
+#define RTEXT_FILTER_CFM_STATUS	(1 << 6)
+#define RTEXT_FILTER_MST	(1 << 7)
 
 /* End of information exported to user level */
 
diff --git a/include/linux-private/linux/seg6.h b/include/linux-private/linux/seg6.h
new file mode 100644
index 0000000..e888b00
--- /dev/null
+++ b/include/linux-private/linux/seg6.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ *  SR-IPv6 implementation
+ *
+ *  Author:
+ *  David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ *  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.
+ */
+
+#ifndef _LINUX_SEG6_H
+#define _LINUX_SEG6_H
+
+#include <linux/types.h>
+#include <linux/in6.h>		/* For struct in6_addr. */
+
+/*
+ * SRH
+ */
+struct ipv6_sr_hdr {
+	__u8	nexthdr;
+	__u8	hdrlen;
+	__u8	type;
+	__u8	segments_left;
+	__u8	first_segment; /* Represents the last_entry field of SRH */
+	__u8	flags;
+	__u16	tag;
+
+	struct in6_addr segments[];
+};
+
+#define SR6_FLAG1_PROTECTED	(1 << 6)
+#define SR6_FLAG1_OAM		(1 << 5)
+#define SR6_FLAG1_ALERT		(1 << 4)
+#define SR6_FLAG1_HMAC		(1 << 3)
+
+#define SR6_TLV_INGRESS		1
+#define SR6_TLV_EGRESS		2
+#define SR6_TLV_OPAQUE		3
+#define SR6_TLV_PADDING		4
+#define SR6_TLV_HMAC		5
+
+#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC)
+
+struct sr6_tlv {
+	__u8 type;
+	__u8 len;
+	__u8 data[0];
+};
+
+#endif
diff --git a/include/linux-private/linux/seg6_hmac.h b/include/linux-private/linux/seg6_hmac.h
new file mode 100644
index 0000000..3fb3412
--- /dev/null
+++ b/include/linux-private/linux/seg6_hmac.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_SEG6_HMAC_H
+#define _LINUX_SEG6_HMAC_H
+
+#include <linux/types.h>
+#include <linux/seg6.h>
+
+#define SEG6_HMAC_SECRET_LEN	64
+#define SEG6_HMAC_FIELD_LEN	32
+
+struct sr6_tlv_hmac {
+	struct sr6_tlv tlvhdr;
+	__u16 reserved;
+	__be32 hmackeyid;
+	__u8 hmac[SEG6_HMAC_FIELD_LEN];
+};
+
+enum {
+	SEG6_HMAC_ALGO_SHA1 = 1,
+	SEG6_HMAC_ALGO_SHA256 = 2,
+};
+
+#endif
diff --git a/include/linux-private/linux/seg6_iptunnel.h b/include/linux-private/linux/seg6_iptunnel.h
new file mode 100644
index 0000000..e1929d2
--- /dev/null
+++ b/include/linux-private/linux/seg6_iptunnel.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ *  SR-IPv6 implementation
+ *
+ *  Author:
+ *  David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ *  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.
+ */
+
+#ifndef _LINUX_SEG6_IPTUNNEL_H
+#define _LINUX_SEG6_IPTUNNEL_H
+
+#include <linux/seg6.h>		/* For struct ipv6_sr_hdr. */
+
+enum {
+	SEG6_IPTUNNEL_UNSPEC,
+	SEG6_IPTUNNEL_SRH,
+	__SEG6_IPTUNNEL_MAX,
+};
+#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
+
+struct seg6_iptunnel_encap {
+	int mode;
+	struct ipv6_sr_hdr srh[];
+};
+
+#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))
+
+enum {
+	SEG6_IPTUN_MODE_INLINE,
+	SEG6_IPTUN_MODE_ENCAP,
+	SEG6_IPTUN_MODE_L2ENCAP,
+	SEG6_IPTUN_MODE_ENCAP_RED,
+	SEG6_IPTUN_MODE_L2ENCAP_RED,
+};
+
+#endif
diff --git a/include/linux-private/linux/seg6_local.h b/include/linux-private/linux/seg6_local.h
new file mode 100644
index 0000000..6e71d97
--- /dev/null
+++ b/include/linux-private/linux/seg6_local.h
@@ -0,0 +1,137 @@
+/*
+ *  SR-IPv6 implementation
+ *
+ *  Author:
+ *  David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ *  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.
+ */
+
+#ifndef _LINUX_SEG6_LOCAL_H
+#define _LINUX_SEG6_LOCAL_H
+
+#include <linux/seg6.h>
+
+enum {
+	SEG6_LOCAL_UNSPEC,
+	SEG6_LOCAL_ACTION,
+	SEG6_LOCAL_SRH,
+	SEG6_LOCAL_TABLE,
+	SEG6_LOCAL_NH4,
+	SEG6_LOCAL_NH6,
+	SEG6_LOCAL_IIF,
+	SEG6_LOCAL_OIF,
+	SEG6_LOCAL_BPF,
+	SEG6_LOCAL_VRFTABLE,
+	SEG6_LOCAL_COUNTERS,
+	SEG6_LOCAL_FLAVORS,
+	__SEG6_LOCAL_MAX,
+};
+#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
+
+enum {
+	SEG6_LOCAL_ACTION_UNSPEC	= 0,
+	/* node segment */
+	SEG6_LOCAL_ACTION_END		= 1,
+	/* adjacency segment (IPv6 cross-connect) */
+	SEG6_LOCAL_ACTION_END_X		= 2,
+	/* lookup of next seg NH in table */
+	SEG6_LOCAL_ACTION_END_T		= 3,
+	/* decap and L2 cross-connect */
+	SEG6_LOCAL_ACTION_END_DX2	= 4,
+	/* decap and IPv6 cross-connect */
+	SEG6_LOCAL_ACTION_END_DX6	= 5,
+	/* decap and IPv4 cross-connect */
+	SEG6_LOCAL_ACTION_END_DX4	= 6,
+	/* decap and lookup of DA in v6 table */
+	SEG6_LOCAL_ACTION_END_DT6	= 7,
+	/* decap and lookup of DA in v4 table */
+	SEG6_LOCAL_ACTION_END_DT4	= 8,
+	/* binding segment with insertion */
+	SEG6_LOCAL_ACTION_END_B6	= 9,
+	/* binding segment with encapsulation */
+	SEG6_LOCAL_ACTION_END_B6_ENCAP	= 10,
+	/* binding segment with MPLS encap */
+	SEG6_LOCAL_ACTION_END_BM	= 11,
+	/* lookup last seg in table */
+	SEG6_LOCAL_ACTION_END_S		= 12,
+	/* forward to SR-unaware VNF with static proxy */
+	SEG6_LOCAL_ACTION_END_AS	= 13,
+	/* forward to SR-unaware VNF with masquerading */
+	SEG6_LOCAL_ACTION_END_AM	= 14,
+	/* custom BPF action */
+	SEG6_LOCAL_ACTION_END_BPF	= 15,
+	/* decap and lookup of DA in v4 or v6 table */
+	SEG6_LOCAL_ACTION_END_DT46	= 16,
+
+	__SEG6_LOCAL_ACTION_MAX,
+};
+
+#define SEG6_LOCAL_ACTION_MAX (__SEG6_LOCAL_ACTION_MAX - 1)
+
+enum {
+	SEG6_LOCAL_BPF_PROG_UNSPEC,
+	SEG6_LOCAL_BPF_PROG,
+	SEG6_LOCAL_BPF_PROG_NAME,
+	__SEG6_LOCAL_BPF_PROG_MAX,
+};
+
+#define SEG6_LOCAL_BPF_PROG_MAX (__SEG6_LOCAL_BPF_PROG_MAX - 1)
+
+/* SRv6 Behavior counters are encoded as netlink attributes guaranteeing the
+ * correct alignment.
+ * Each counter is identified by a different attribute type (i.e.
+ * SEG6_LOCAL_CNT_PACKETS).
+ *
+ * - SEG6_LOCAL_CNT_PACKETS: identifies a counter that counts the number of
+ *   packets that have been CORRECTLY processed by an SRv6 Behavior instance
+ *   (i.e., packets that generate errors or are dropped are NOT counted).
+ *
+ * - SEG6_LOCAL_CNT_BYTES: identifies a counter that counts the total amount
+ *   of traffic in bytes of all packets that have been CORRECTLY processed by
+ *   an SRv6 Behavior instance (i.e., packets that generate errors or are
+ *   dropped are NOT counted).
+ *
+ * - SEG6_LOCAL_CNT_ERRORS: identifies a counter that counts the number of
+ *   packets that have NOT been properly processed by an SRv6 Behavior instance
+ *   (i.e., packets that generate errors or are dropped).
+ */
+enum {
+	SEG6_LOCAL_CNT_UNSPEC,
+	SEG6_LOCAL_CNT_PAD,		/* pad for 64 bits values */
+	SEG6_LOCAL_CNT_PACKETS,
+	SEG6_LOCAL_CNT_BYTES,
+	SEG6_LOCAL_CNT_ERRORS,
+	__SEG6_LOCAL_CNT_MAX,
+};
+
+#define SEG6_LOCAL_CNT_MAX (__SEG6_LOCAL_CNT_MAX - 1)
+
+/* SRv6 End* Flavor attributes */
+enum {
+	SEG6_LOCAL_FLV_UNSPEC,
+	SEG6_LOCAL_FLV_OPERATION,
+	SEG6_LOCAL_FLV_LCBLOCK_BITS,
+	SEG6_LOCAL_FLV_LCNODE_FN_BITS,
+	__SEG6_LOCAL_FLV_MAX,
+};
+
+#define SEG6_LOCAL_FLV_MAX (__SEG6_LOCAL_FLV_MAX - 1)
+
+/* Designed flavor operations for SRv6 End* Behavior */
+enum {
+	SEG6_LOCAL_FLV_OP_UNSPEC,
+	SEG6_LOCAL_FLV_OP_PSP,
+	SEG6_LOCAL_FLV_OP_USP,
+	SEG6_LOCAL_FLV_OP_USD,
+	SEG6_LOCAL_FLV_OP_NEXT_CSID,
+	__SEG6_LOCAL_FLV_OP_MAX
+};
+
+#define SEG6_LOCAL_FLV_OP_MAX (__SEG6_LOCAL_FLV_OP_MAX - 1)
+
+#endif
diff --git a/include/linux-private/linux/snmp.h b/include/linux-private/linux/snmp.h
index abae27c..26f33a4 100644
--- a/include/linux-private/linux/snmp.h
+++ b/include/linux-private/linux/snmp.h
@@ -95,6 +95,8 @@
 	ICMP_MIB_OUTADDRMASKS,			/* OutAddrMasks */
 	ICMP_MIB_OUTADDRMASKREPS,		/* OutAddrMaskReps */
 	ICMP_MIB_CSUMERRORS,			/* InCsumErrors */
+	ICMP_MIB_RATELIMITGLOBAL,		/* OutRateLimitGlobal */
+	ICMP_MIB_RATELIMITHOST,			/* OutRateLimitHost */
 	__ICMP_MIB_MAX
 };
 
@@ -112,6 +114,7 @@
 	ICMP6_MIB_OUTMSGS,			/* OutMsgs */
 	ICMP6_MIB_OUTERRORS,			/* OutErrors */
 	ICMP6_MIB_CSUMERRORS,			/* InCsumErrors */
+	ICMP6_MIB_RATELIMITHOST,		/* OutRateLimitHost */
 	__ICMP6_MIB_MAX
 };
 
@@ -159,6 +162,7 @@
 	UDP_MIB_SNDBUFERRORS,			/* SndbufErrors */
 	UDP_MIB_CSUMERRORS,			/* InCsumErrors */
 	UDP_MIB_IGNOREDMULTI,			/* IgnoredMulti */
+	UDP_MIB_MEMERRORS,			/* MemErrors */
 	__UDP_MIB_MAX
 };
 
@@ -243,6 +247,7 @@
 	LINUX_MIB_TCPREQQFULLDROP,		/* TCPReqQFullDrop */
 	LINUX_MIB_TCPRETRANSFAIL,		/* TCPRetransFail */
 	LINUX_MIB_TCPRCVCOALESCE,		/* TCPRcvCoalesce */
+	LINUX_MIB_TCPBACKLOGCOALESCE,		/* TCPBacklogCoalesce */
 	LINUX_MIB_TCPOFOQUEUE,			/* TCPOFOQueue */
 	LINUX_MIB_TCPOFODROP,			/* TCPOFODrop */
 	LINUX_MIB_TCPOFOMERGE,			/* TCPOFOMerge */
@@ -283,6 +288,14 @@
 	LINUX_MIB_TCPZEROWINDOWDROP,		/* TCPZeroWindowDrop */
 	LINUX_MIB_TCPRCVQDROP,			/* TCPRcvQDrop */
 	LINUX_MIB_TCPWQUEUETOOBIG,		/* TCPWqueueTooBig */
+	LINUX_MIB_TCPFASTOPENPASSIVEALTKEY,	/* TCPFastOpenPassiveAltKey */
+	LINUX_MIB_TCPTIMEOUTREHASH,		/* TCPTimeoutRehash */
+	LINUX_MIB_TCPDUPLICATEDATAREHASH,	/* TCPDuplicateDataRehash */
+	LINUX_MIB_TCPDSACKRECVSEGS,		/* TCPDSACKRecvSegs */
+	LINUX_MIB_TCPDSACKIGNOREDDUBIOUS,	/* TCPDSACKIgnoredDubious */
+	LINUX_MIB_TCPMIGRATEREQSUCCESS,		/* TCPMigrateReqSuccess */
+	LINUX_MIB_TCPMIGRATEREQFAILURE,		/* TCPMigrateReqFailure */
+	LINUX_MIB_TCPPLBREHASH,			/* TCPPLBRehash */
 	__LINUX_MIB_MAX
 };
 
@@ -321,4 +334,23 @@
 	__LINUX_MIB_XFRMMAX
 };
 
+/* linux TLS mib definitions */
+enum
+{
+	LINUX_MIB_TLSNUM = 0,
+	LINUX_MIB_TLSCURRTXSW,			/* TlsCurrTxSw */
+	LINUX_MIB_TLSCURRRXSW,			/* TlsCurrRxSw */
+	LINUX_MIB_TLSCURRTXDEVICE,		/* TlsCurrTxDevice */
+	LINUX_MIB_TLSCURRRXDEVICE,		/* TlsCurrRxDevice */
+	LINUX_MIB_TLSTXSW,			/* TlsTxSw */
+	LINUX_MIB_TLSRXSW,			/* TlsRxSw */
+	LINUX_MIB_TLSTXDEVICE,			/* TlsTxDevice */
+	LINUX_MIB_TLSRXDEVICE,			/* TlsRxDevice */
+	LINUX_MIB_TLSDECRYPTERROR,		/* TlsDecryptError */
+	LINUX_MIB_TLSRXDEVICERESYNC,		/* TlsRxDeviceResync */
+	LINUX_MIB_TLSDECRYPTRETRY,		/* TlsDecryptRetry */
+	LINUX_MIB_TLSRXNOPADVIOL,		/* TlsRxNoPadViolation */
+	__LINUX_MIB_TLSMAX
+};
+
 #endif	/* _LINUX_SNMP_H */
diff --git a/include/linux-private/linux/sock_diag.h b/include/linux-private/linux/sock_diag.h
index a69cf20..35c0ce6 100644
--- a/include/linux-private/linux/sock_diag.h
+++ b/include/linux-private/linux/sock_diag.h
@@ -36,4 +36,30 @@
 };
 #define SKNLGRP_MAX	(__SKNLGRP_MAX - 1)
 
+enum {
+	SK_DIAG_BPF_STORAGE_REQ_NONE,
+	SK_DIAG_BPF_STORAGE_REQ_MAP_FD,
+	__SK_DIAG_BPF_STORAGE_REQ_MAX,
+};
+
+#define SK_DIAG_BPF_STORAGE_REQ_MAX	(__SK_DIAG_BPF_STORAGE_REQ_MAX - 1)
+
+enum {
+	SK_DIAG_BPF_STORAGE_REP_NONE,
+	SK_DIAG_BPF_STORAGE,
+	__SK_DIAG_BPF_STORAGE_REP_MAX,
+};
+
+#define SK_DIAB_BPF_STORAGE_REP_MAX	(__SK_DIAG_BPF_STORAGE_REP_MAX - 1)
+
+enum {
+	SK_DIAG_BPF_STORAGE_NONE,
+	SK_DIAG_BPF_STORAGE_PAD,
+	SK_DIAG_BPF_STORAGE_MAP_ID,
+	SK_DIAG_BPF_STORAGE_MAP_VALUE,
+	__SK_DIAG_BPF_STORAGE_MAX,
+};
+
+#define SK_DIAG_BPF_STORAGE_MAX        (__SK_DIAG_BPF_STORAGE_MAX - 1)
+
 #endif /* __SOCK_DIAG_H__ */
diff --git a/include/linux-private/linux/socket.h b/include/linux-private/linux/socket.h
index 268b948..89c227f 100644
--- a/include/linux-private/linux/socket.h
+++ b/include/linux-private/linux/socket.h
@@ -6,17 +6,33 @@
  * Desired design of maximum size and alignment (see RFC2553)
  */
 #define _K_SS_MAXSIZE	128	/* Implementation specific max size */
-#define _K_SS_ALIGNSIZE	(__alignof__ (struct sockaddr *))
-				/* Implementation specific desired alignment */
 
 typedef unsigned short __kernel_sa_family_t;
 
+/*
+ * The definition uses anonymous union and struct in order to control the
+ * default alignment.
+ */
 struct __kernel_sockaddr_storage {
-	__kernel_sa_family_t	ss_family;		/* address family */
-	/* Following field(s) are implementation specific */
-	char		__data[_K_SS_MAXSIZE - sizeof(unsigned short)];
+	union {
+		struct {
+			__kernel_sa_family_t	ss_family; /* address family */
+			/* Following field(s) are implementation specific */
+			char __data[_K_SS_MAXSIZE - sizeof(unsigned short)];
 				/* space to achieve desired size, */
 				/* _SS_MAXSIZE value minus size of ss_family */
-} __attribute__ ((aligned(_K_SS_ALIGNSIZE)));	/* force desired alignment */
+		};
+		void *__align; /* implementation specific desired alignment */
+	};
+};
+
+#define SOCK_SNDBUF_LOCK	1
+#define SOCK_RCVBUF_LOCK	2
+
+#define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
+
+#define SOCK_TXREHASH_DEFAULT	255
+#define SOCK_TXREHASH_DISABLED	0
+#define SOCK_TXREHASH_ENABLED	1
 
 #endif /* _LINUX_SOCKET_H */
diff --git a/include/linux-private/linux/stddef.h b/include/linux-private/linux/stddef.h
new file mode 100644
index 0000000..bb6ea51
--- /dev/null
+++ b/include/linux-private/linux/stddef.h
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_STDDEF_H
+#define _LINUX_STDDEF_H
+
+
+
+#ifndef __always_inline
+#define __always_inline __inline__
+#endif
+
+/**
+ * __struct_group() - Create a mirrored named and anonyomous struct
+ *
+ * @TAG: The tag name for the named sub-struct (usually empty)
+ * @NAME: The identifier name of the mirrored sub-struct
+ * @ATTRS: Any struct attributes (usually empty)
+ * @MEMBERS: The member declarations for the mirrored structs
+ *
+ * Used to create an anonymous union of two structs with identical layout
+ * and size: one anonymous and one named. The former's members can be used
+ * normally without sub-struct naming, and the latter can be used to
+ * reason about the start, end, and size of the group of struct members.
+ * The named struct can also be explicitly tagged for layer reuse, as well
+ * as both having struct attributes appended.
+ */
+#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
+	union { \
+		struct { MEMBERS } ATTRS; \
+		struct TAG { MEMBERS } ATTRS NAME; \
+	}
+
+/**
+ * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
+ *
+ * @TYPE: The type of each flexible array element
+ * @NAME: The name of the flexible array member
+ *
+ * In order to have a flexible array member in a union or alone in a
+ * struct, it needs to be wrapped in an anonymous struct with at least 1
+ * named member, but that member can be empty.
+ */
+#define __DECLARE_FLEX_ARRAY(TYPE, NAME)	\
+	struct { \
+		struct { } __empty_ ## NAME; \
+		TYPE NAME[]; \
+	}
+#endif
diff --git a/include/linux-private/linux/swab.h b/include/linux-private/linux/swab.h
new file mode 100644
index 0000000..7e3bad5
--- /dev/null
+++ b/include/linux-private/linux/swab.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_SWAB_H
+#define _LINUX_SWAB_H
+
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <asm/bitsperlong.h>
+#include <asm/swab.h>
+
+/*
+ * casts are necessary for constants, because we never know how for sure
+ * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
+ */
+#define ___constant_swab16(x) ((__u16)(				\
+	(((__u16)(x) & (__u16)0x00ffU) << 8) |			\
+	(((__u16)(x) & (__u16)0xff00U) >> 8)))
+
+#define ___constant_swab32(x) ((__u32)(				\
+	(((__u32)(x) & (__u32)0x000000ffUL) << 24) |		\
+	(((__u32)(x) & (__u32)0x0000ff00UL) <<  8) |		\
+	(((__u32)(x) & (__u32)0x00ff0000UL) >>  8) |		\
+	(((__u32)(x) & (__u32)0xff000000UL) >> 24)))
+
+#define ___constant_swab64(x) ((__u64)(				\
+	(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) |	\
+	(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) |	\
+	(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) |	\
+	(((__u64)(x) & (__u64)0x00000000ff000000ULL) <<  8) |	\
+	(((__u64)(x) & (__u64)0x000000ff00000000ULL) >>  8) |	\
+	(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) |	\
+	(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) |	\
+	(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56)))
+
+#define ___constant_swahw32(x) ((__u32)(			\
+	(((__u32)(x) & (__u32)0x0000ffffUL) << 16) |		\
+	(((__u32)(x) & (__u32)0xffff0000UL) >> 16)))
+
+#define ___constant_swahb32(x) ((__u32)(			\
+	(((__u32)(x) & (__u32)0x00ff00ffUL) << 8) |		\
+	(((__u32)(x) & (__u32)0xff00ff00UL) >> 8)))
+
+/*
+ * Implement the following as inlines, but define the interface using
+ * macros to allow constant folding when possible:
+ * ___swab16, ___swab32, ___swab64, ___swahw32, ___swahb32
+ */
+
+static __inline__  __u16 __fswab16(__u16 val)
+{
+#if defined (__arch_swab16)
+	return __arch_swab16(val);
+#else
+	return ___constant_swab16(val);
+#endif
+}
+
+static __inline__  __u32 __fswab32(__u32 val)
+{
+#if defined(__arch_swab32)
+	return __arch_swab32(val);
+#else
+	return ___constant_swab32(val);
+#endif
+}
+
+static __inline__  __u64 __fswab64(__u64 val)
+{
+#if defined (__arch_swab64)
+	return __arch_swab64(val);
+#elif defined(__SWAB_64_THRU_32__)
+	__u32 h = val >> 32;
+	__u32 l = val & ((1ULL << 32) - 1);
+	return (((__u64)__fswab32(l)) << 32) | ((__u64)(__fswab32(h)));
+#else
+	return ___constant_swab64(val);
+#endif
+}
+
+static __inline__  __u32 __fswahw32(__u32 val)
+{
+#ifdef __arch_swahw32
+	return __arch_swahw32(val);
+#else
+	return ___constant_swahw32(val);
+#endif
+}
+
+static __inline__  __u32 __fswahb32(__u32 val)
+{
+#ifdef __arch_swahb32
+	return __arch_swahb32(val);
+#else
+	return ___constant_swahb32(val);
+#endif
+}
+
+/**
+ * __swab16 - return a byteswapped 16-bit value
+ * @x: value to byteswap
+ */
+#ifdef __HAVE_BUILTIN_BSWAP16__
+#define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
+#else
+#define __swab16(x)				\
+	(__u16)(__builtin_constant_p(x) ?	\
+	___constant_swab16(x) :			\
+	__fswab16(x))
+#endif
+
+/**
+ * __swab32 - return a byteswapped 32-bit value
+ * @x: value to byteswap
+ */
+#ifdef __HAVE_BUILTIN_BSWAP32__
+#define __swab32(x) (__u32)__builtin_bswap32((__u32)(x))
+#else
+#define __swab32(x)				\
+	(__u32)(__builtin_constant_p(x) ?	\
+	___constant_swab32(x) :			\
+	__fswab32(x))
+#endif
+
+/**
+ * __swab64 - return a byteswapped 64-bit value
+ * @x: value to byteswap
+ */
+#ifdef __HAVE_BUILTIN_BSWAP64__
+#define __swab64(x) (__u64)__builtin_bswap64((__u64)(x))
+#else
+#define __swab64(x)				\
+	(__u64)(__builtin_constant_p(x) ?	\
+	___constant_swab64(x) :			\
+	__fswab64(x))
+#endif
+
+static __always_inline unsigned long __swab(const unsigned long y)
+{
+#if __BITS_PER_LONG == 64
+	return __swab64(y);
+#else /* __BITS_PER_LONG == 32 */
+	return __swab32(y);
+#endif
+}
+
+/**
+ * __swahw32 - return a word-swapped 32-bit value
+ * @x: value to wordswap
+ *
+ * __swahw32(0x12340000) is 0x00001234
+ */
+#define __swahw32(x)				\
+	(__builtin_constant_p((__u32)(x)) ?	\
+	___constant_swahw32(x) :		\
+	__fswahw32(x))
+
+/**
+ * __swahb32 - return a high and low byte-swapped 32-bit value
+ * @x: value to byteswap
+ *
+ * __swahb32(0x12345678) is 0x34127856
+ */
+#define __swahb32(x)				\
+	(__builtin_constant_p((__u32)(x)) ?	\
+	___constant_swahb32(x) :		\
+	__fswahb32(x))
+
+/**
+ * __swab16p - return a byteswapped 16-bit value from a pointer
+ * @p: pointer to a naturally-aligned 16-bit value
+ */
+static __always_inline __u16 __swab16p(const __u16 *p)
+{
+#ifdef __arch_swab16p
+	return __arch_swab16p(p);
+#else
+	return __swab16(*p);
+#endif
+}
+
+/**
+ * __swab32p - return a byteswapped 32-bit value from a pointer
+ * @p: pointer to a naturally-aligned 32-bit value
+ */
+static __always_inline __u32 __swab32p(const __u32 *p)
+{
+#ifdef __arch_swab32p
+	return __arch_swab32p(p);
+#else
+	return __swab32(*p);
+#endif
+}
+
+/**
+ * __swab64p - return a byteswapped 64-bit value from a pointer
+ * @p: pointer to a naturally-aligned 64-bit value
+ */
+static __always_inline __u64 __swab64p(const __u64 *p)
+{
+#ifdef __arch_swab64p
+	return __arch_swab64p(p);
+#else
+	return __swab64(*p);
+#endif
+}
+
+/**
+ * __swahw32p - return a wordswapped 32-bit value from a pointer
+ * @p: pointer to a naturally-aligned 32-bit value
+ *
+ * See __swahw32() for details of wordswapping.
+ */
+static __inline__ __u32 __swahw32p(const __u32 *p)
+{
+#ifdef __arch_swahw32p
+	return __arch_swahw32p(p);
+#else
+	return __swahw32(*p);
+#endif
+}
+
+/**
+ * __swahb32p - return a high and low byteswapped 32-bit value from a pointer
+ * @p: pointer to a naturally-aligned 32-bit value
+ *
+ * See __swahb32() for details of high/low byteswapping.
+ */
+static __inline__ __u32 __swahb32p(const __u32 *p)
+{
+#ifdef __arch_swahb32p
+	return __arch_swahb32p(p);
+#else
+	return __swahb32(*p);
+#endif
+}
+
+/**
+ * __swab16s - byteswap a 16-bit value in-place
+ * @p: pointer to a naturally-aligned 16-bit value
+ */
+static __inline__ void __swab16s(__u16 *p)
+{
+#ifdef __arch_swab16s
+	__arch_swab16s(p);
+#else
+	*p = __swab16p(p);
+#endif
+}
+/**
+ * __swab32s - byteswap a 32-bit value in-place
+ * @p: pointer to a naturally-aligned 32-bit value
+ */
+static __always_inline void __swab32s(__u32 *p)
+{
+#ifdef __arch_swab32s
+	__arch_swab32s(p);
+#else
+	*p = __swab32p(p);
+#endif
+}
+
+/**
+ * __swab64s - byteswap a 64-bit value in-place
+ * @p: pointer to a naturally-aligned 64-bit value
+ */
+static __always_inline void __swab64s(__u64 *p)
+{
+#ifdef __arch_swab64s
+	__arch_swab64s(p);
+#else
+	*p = __swab64p(p);
+#endif
+}
+
+/**
+ * __swahw32s - wordswap a 32-bit value in-place
+ * @p: pointer to a naturally-aligned 32-bit value
+ *
+ * See __swahw32() for details of wordswapping
+ */
+static __inline__ void __swahw32s(__u32 *p)
+{
+#ifdef __arch_swahw32s
+	__arch_swahw32s(p);
+#else
+	*p = __swahw32p(p);
+#endif
+}
+
+/**
+ * __swahb32s - high and low byteswap a 32-bit value in-place
+ * @p: pointer to a naturally-aligned 32-bit value
+ *
+ * See __swahb32() for details of high and low byte swapping
+ */
+static __inline__ void __swahb32s(__u32 *p)
+{
+#ifdef __arch_swahb32s
+	__arch_swahb32s(p);
+#else
+	*p = __swahb32p(p);
+#endif
+}
+
+
+#endif /* _LINUX_SWAB_H */
diff --git a/include/linux-private/linux/taskstats.h b/include/linux-private/linux/taskstats.h
new file mode 100644
index 0000000..b50b2eb
--- /dev/null
+++ b/include/linux-private/linux/taskstats.h
@@ -0,0 +1,252 @@
+/* SPDX-License-Identifier: LGPL-2.1 WITH Linux-syscall-note */
+/* taskstats.h - exporting per-task statistics
+ *
+ * Copyright (C) Shailabh Nagar, IBM Corp. 2006
+ *           (C) Balbir Singh,   IBM Corp. 2006
+ *           (C) Jay Lan,        SGI, 2006
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _LINUX_TASKSTATS_H
+#define _LINUX_TASKSTATS_H
+
+#include <linux/types.h>
+
+/* Format for per-task data returned to userland when
+ *	- a task exits
+ *	- listener requests stats for a task
+ *
+ * The struct is versioned. Newer versions should only add fields to
+ * the bottom of the struct to maintain backward compatibility.
+ *
+ *
+ * To add new fields
+ *	a) bump up TASKSTATS_VERSION
+ *	b) add comment indicating new version number at end of struct
+ *	c) add new fields after version comment; maintain 64-bit alignment
+ */
+
+
+#define TASKSTATS_VERSION	14
+#define TS_COMM_LEN		32	/* should be >= TASK_COMM_LEN
+					 * in linux/sched.h */
+
+struct taskstats {
+
+	/* The version number of this struct. This field is always set to
+	 * TAKSTATS_VERSION, which is defined in <linux/taskstats.h>.
+	 * Each time the struct is changed, the value should be incremented.
+	 */
+	__u16	version;
+	__u32	ac_exitcode;		/* Exit status */
+
+	/* The accounting flags of a task as defined in <linux/acct.h>
+	 * Defined values are AFORK, ASU, ACOMPAT, ACORE, AXSIG, and AGROUP.
+	 * (AGROUP since version 12).
+	 */
+	__u8	ac_flag;		/* Record flags */
+	__u8	ac_nice;		/* task_nice */
+
+	/* Delay accounting fields start
+	 *
+	 * All values, until comment "Delay accounting fields end" are
+	 * available only if delay accounting is enabled, even though the last
+	 * few fields are not delays
+	 *
+	 * xxx_count is the number of delay values recorded
+	 * xxx_delay_total is the corresponding cumulative delay in nanoseconds
+	 *
+	 * xxx_delay_total wraps around to zero on overflow
+	 * xxx_count incremented regardless of overflow
+	 */
+
+	/* Delay waiting for cpu, while runnable
+	 * count, delay_total NOT updated atomically
+	 */
+	__u64	cpu_count __attribute__((aligned(8)));
+	__u64	cpu_delay_total;
+
+	/* Following four fields atomically updated using task->delays->lock */
+
+	/* Delay waiting for synchronous block I/O to complete
+	 * does not account for delays in I/O submission
+	 */
+	__u64	blkio_count;
+	__u64	blkio_delay_total;
+
+	/* Delay waiting for page fault I/O (swap in only) */
+	__u64	swapin_count;
+	__u64	swapin_delay_total;
+
+	/* cpu "wall-clock" running time
+	 * On some architectures, value will adjust for cpu time stolen
+	 * from the kernel in involuntary waits due to virtualization.
+	 * Value is cumulative, in nanoseconds, without a corresponding count
+	 * and wraps around to zero silently on overflow
+	 */
+	__u64	cpu_run_real_total;
+
+	/* cpu "virtual" running time
+	 * Uses time intervals seen by the kernel i.e. no adjustment
+	 * for kernel's involuntary waits due to virtualization.
+	 * Value is cumulative, in nanoseconds, without a corresponding count
+	 * and wraps around to zero silently on overflow
+	 */
+	__u64	cpu_run_virtual_total;
+	/* Delay accounting fields end */
+	/* version 1 ends here */
+
+	/* Basic Accounting Fields start */
+	char	ac_comm[TS_COMM_LEN];	/* Command name */
+	__u8	ac_sched __attribute__((aligned(8)));
+					/* Scheduling discipline */
+	__u8	ac_pad[3];
+	__u32	ac_uid __attribute__((aligned(8)));
+					/* User ID */
+	__u32	ac_gid;			/* Group ID */
+	__u32	ac_pid;			/* Process ID */
+	__u32	ac_ppid;		/* Parent process ID */
+	/* __u32 range means times from 1970 to 2106 */
+	__u32	ac_btime;		/* Begin time [sec since 1970] */
+	__u64	ac_etime __attribute__((aligned(8)));
+					/* Elapsed time [usec] */
+	__u64	ac_utime;		/* User CPU time [usec] */
+	__u64	ac_stime;		/* SYstem CPU time [usec] */
+	__u64	ac_minflt;		/* Minor Page Fault Count */
+	__u64	ac_majflt;		/* Major Page Fault Count */
+	/* Basic Accounting Fields end */
+
+	/* Extended accounting fields start */
+	/* Accumulated RSS usage in duration of a task, in MBytes-usecs.
+	 * The current rss usage is added to this counter every time
+	 * a tick is charged to a task's system time. So, at the end we
+	 * will have memory usage multiplied by system time. Thus an
+	 * average usage per system time unit can be calculated.
+	 */
+	__u64	coremem;		/* accumulated RSS usage in MB-usec */
+	/* Accumulated virtual memory usage in duration of a task.
+	 * Same as acct_rss_mem1 above except that we keep track of VM usage.
+	 */
+	__u64	virtmem;		/* accumulated VM  usage in MB-usec */
+
+	/* High watermark of RSS and virtual memory usage in duration of
+	 * a task, in KBytes.
+	 */
+	__u64	hiwater_rss;		/* High-watermark of RSS usage, in KB */
+	__u64	hiwater_vm;		/* High-water VM usage, in KB */
+
+	/* The following four fields are I/O statistics of a task. */
+	__u64	read_char;		/* bytes read */
+	__u64	write_char;		/* bytes written */
+	__u64	read_syscalls;		/* read syscalls */
+	__u64	write_syscalls;		/* write syscalls */
+	/* Extended accounting fields end */
+
+#define TASKSTATS_HAS_IO_ACCOUNTING
+	/* Per-task storage I/O accounting starts */
+	__u64	read_bytes;		/* bytes of read I/O */
+	__u64	write_bytes;		/* bytes of write I/O */
+	__u64	cancelled_write_bytes;	/* bytes of cancelled write I/O */
+
+	__u64  nvcsw;			/* voluntary_ctxt_switches */
+	__u64  nivcsw;			/* nonvoluntary_ctxt_switches */
+
+	/* time accounting for SMT machines */
+	__u64	ac_utimescaled;		/* utime scaled on frequency etc */
+	__u64	ac_stimescaled;		/* stime scaled on frequency etc */
+	__u64	cpu_scaled_run_real_total; /* scaled cpu_run_real_total */
+
+	/* Delay waiting for memory reclaim */
+	__u64	freepages_count;
+	__u64	freepages_delay_total;
+
+	/* Delay waiting for thrashing page */
+	__u64	thrashing_count;
+	__u64	thrashing_delay_total;
+
+	/* v10: 64-bit btime to avoid overflow */
+	__u64	ac_btime64;		/* 64-bit begin time */
+
+	/* v11: Delay waiting for memory compact */
+	__u64	compact_count;
+	__u64	compact_delay_total;
+
+	/* v12 begin */
+	__u32   ac_tgid;	/* thread group ID */
+	/* Thread group walltime up to now. This is total process walltime if
+	 * AGROUP flag is set.
+	 */
+	__u64	ac_tgetime __attribute__((aligned(8)));
+	/* Lightweight information to identify process binary files.
+	 * This leaves userspace to match this to a file system path, using
+	 * MAJOR() and MINOR() macros to identify a device and mount point,
+	 * the inode to identify the executable file. This is /proc/self/exe
+	 * at the end, so matching the most recent exec(). Values are zero
+	 * for kernel threads.
+	 */
+	__u64   ac_exe_dev;     /* program binary device ID */
+	__u64   ac_exe_inode;   /* program binary inode number */
+	/* v12 end */
+
+	/* v13: Delay waiting for write-protect copy */
+	__u64    wpcopy_count;
+	__u64    wpcopy_delay_total;
+
+	/* v14: Delay waiting for IRQ/SOFTIRQ */
+	__u64    irq_count;
+	__u64    irq_delay_total;
+};
+
+
+/*
+ * Commands sent from userspace
+ * Not versioned. New commands should only be inserted at the enum's end
+ * prior to __TASKSTATS_CMD_MAX
+ */
+
+enum {
+	TASKSTATS_CMD_UNSPEC = 0,	/* Reserved */
+	TASKSTATS_CMD_GET,		/* user->kernel request/get-response */
+	TASKSTATS_CMD_NEW,		/* kernel->user event */
+	__TASKSTATS_CMD_MAX,
+};
+
+#define TASKSTATS_CMD_MAX (__TASKSTATS_CMD_MAX - 1)
+
+enum {
+	TASKSTATS_TYPE_UNSPEC = 0,	/* Reserved */
+	TASKSTATS_TYPE_PID,		/* Process id */
+	TASKSTATS_TYPE_TGID,		/* Thread group id */
+	TASKSTATS_TYPE_STATS,		/* taskstats structure */
+	TASKSTATS_TYPE_AGGR_PID,	/* contains pid + stats */
+	TASKSTATS_TYPE_AGGR_TGID,	/* contains tgid + stats */
+	TASKSTATS_TYPE_NULL,		/* contains nothing */
+	__TASKSTATS_TYPE_MAX,
+};
+
+#define TASKSTATS_TYPE_MAX (__TASKSTATS_TYPE_MAX - 1)
+
+enum {
+	TASKSTATS_CMD_ATTR_UNSPEC = 0,
+	TASKSTATS_CMD_ATTR_PID,
+	TASKSTATS_CMD_ATTR_TGID,
+	TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
+	TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
+	__TASKSTATS_CMD_ATTR_MAX,
+};
+
+#define TASKSTATS_CMD_ATTR_MAX (__TASKSTATS_CMD_ATTR_MAX - 1)
+
+/* NETLINK_GENERIC related info */
+
+#define TASKSTATS_GENL_NAME	"TASKSTATS"
+#define TASKSTATS_GENL_VERSION	0x1
+
+#endif /* _LINUX_TASKSTATS_H */
diff --git a/include/linux-private/linux/tc_act/tc_gact.h b/include/linux-private/linux/tc_act/tc_gact.h
index 94273c3..37e5392 100644
--- a/include/linux-private/linux/tc_act/tc_gact.h
+++ b/include/linux-private/linux/tc_act/tc_gact.h
@@ -5,7 +5,6 @@
 #include <linux/types.h>
 #include <linux/pkt_cls.h>
 
-#define TCA_ACT_GACT 5
 struct tc_gact {
 	tc_gen;
 
diff --git a/include/linux-private/linux/tc_act/tc_mirred.h b/include/linux-private/linux/tc_act/tc_mirred.h
index 5dd671c..2500a00 100644
--- a/include/linux-private/linux/tc_act/tc_mirred.h
+++ b/include/linux-private/linux/tc_act/tc_mirred.h
@@ -5,7 +5,6 @@
 #include <linux/types.h>
 #include <linux/pkt_cls.h>
 
-#define TCA_ACT_MIRRED 8
 #define TCA_EGRESS_REDIR 1  /* packet redirect to EGRESS*/
 #define TCA_EGRESS_MIRROR 2 /* mirror packet to EGRESS */
 #define TCA_INGRESS_REDIR 3  /* packet redirect to INGRESS*/
diff --git a/include/linux-private/linux/tc_act/tc_skbedit.h b/include/linux-private/linux/tc_act/tc_skbedit.h
index 6de6071..6403251 100644
--- a/include/linux-private/linux/tc_act/tc_skbedit.h
+++ b/include/linux-private/linux/tc_act/tc_skbedit.h
@@ -2,19 +2,6 @@
 /*
  * Copyright (c) 2008, Intel Corporation.
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
  * Author: Alexander Duyck <alexander.h.duyck@intel.com>
  */
 
@@ -23,14 +10,13 @@
 
 #include <linux/pkt_cls.h>
 
-#define TCA_ACT_SKBEDIT 11
-
 #define SKBEDIT_F_PRIORITY		0x1
 #define SKBEDIT_F_QUEUE_MAPPING		0x2
 #define SKBEDIT_F_MARK			0x4
 #define SKBEDIT_F_PTYPE			0x8
 #define SKBEDIT_F_MASK			0x10
 #define SKBEDIT_F_INHERITDSFIELD	0x20
+#define SKBEDIT_F_TXQ_SKBHASH		0x40
 
 struct tc_skbedit {
 	tc_gen;
@@ -47,6 +33,7 @@
 	TCA_SKBEDIT_PTYPE,
 	TCA_SKBEDIT_MASK,
 	TCA_SKBEDIT_FLAGS,
+	TCA_SKBEDIT_QUEUE_MAPPING_MAX,
 	__TCA_SKBEDIT_MAX
 };
 #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
diff --git a/include/linux-private/linux/tc_act/tc_vlan.h b/include/linux-private/linux/tc_act/tc_vlan.h
index 0d7b5fd..3e1f8e5 100644
--- a/include/linux-private/linux/tc_act/tc_vlan.h
+++ b/include/linux-private/linux/tc_act/tc_vlan.h
@@ -1,11 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
 /*
  * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
- *
- * 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.
  */
 
 #ifndef __LINUX_TC_VLAN_H
@@ -13,11 +8,11 @@
 
 #include <linux/pkt_cls.h>
 
-#define TCA_ACT_VLAN 12
-
 #define TCA_VLAN_ACT_POP	1
 #define TCA_VLAN_ACT_PUSH	2
 #define TCA_VLAN_ACT_MODIFY	3
+#define TCA_VLAN_ACT_POP_ETH	4
+#define TCA_VLAN_ACT_PUSH_ETH	5
 
 struct tc_vlan {
 	tc_gen;
@@ -32,6 +27,8 @@
 	TCA_VLAN_PUSH_VLAN_PROTOCOL,
 	TCA_VLAN_PAD,
 	TCA_VLAN_PUSH_VLAN_PRIORITY,
+	TCA_VLAN_PUSH_ETH_DST,
+	TCA_VLAN_PUSH_ETH_SRC,
 	__TCA_VLAN_MAX,
 };
 #define TCA_VLAN_MAX (__TCA_VLAN_MAX - 1)
diff --git a/include/linux-private/linux/tc_ematch/tc_em_cmp.h b/include/linux-private/linux/tc_ematch/tc_em_cmp.h
new file mode 100644
index 0000000..2549d9d
--- /dev/null
+++ b/include/linux-private/linux/tc_ematch/tc_em_cmp.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_TC_EM_CMP_H
+#define __LINUX_TC_EM_CMP_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+struct tcf_em_cmp {
+	__u32		val;
+	__u32		mask;
+	__u16		off;
+	__u8		align:4;
+	__u8		flags:4;
+	__u8		layer:4;
+	__u8		opnd:4;
+};
+
+enum {
+	TCF_EM_ALIGN_U8  = 1,
+	TCF_EM_ALIGN_U16 = 2,
+	TCF_EM_ALIGN_U32 = 4
+};
+
+#define TCF_EM_CMP_TRANS	1
+
+#endif
diff --git a/include/linux-private/linux/tc_ematch/tc_em_nbyte.h b/include/linux-private/linux/tc_ematch/tc_em_nbyte.h
new file mode 100644
index 0000000..c76333f
--- /dev/null
+++ b/include/linux-private/linux/tc_ematch/tc_em_nbyte.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_TC_EM_NBYTE_H
+#define __LINUX_TC_EM_NBYTE_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+struct tcf_em_nbyte {
+	__u16		off;
+	__u16		len:12;
+	__u8		layer:4;
+};
+
+#endif
diff --git a/include/linux-private/linux/tc_ematch/tc_em_text.h b/include/linux-private/linux/tc_ematch/tc_em_text.h
new file mode 100644
index 0000000..b0a9225
--- /dev/null
+++ b/include/linux-private/linux/tc_ematch/tc_em_text.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_TC_EM_TEXT_H
+#define __LINUX_TC_EM_TEXT_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+#define TC_EM_TEXT_ALGOSIZ	16
+
+struct tcf_em_text {
+	char		algo[TC_EM_TEXT_ALGOSIZ];
+	__u16		from_offset;
+	__u16		to_offset;
+	__u16		pattern_len;
+	__u8		from_layer:4;
+	__u8		to_layer:4;
+	__u8		pad;
+};
+
+#endif
diff --git a/include/linux-private/linux/types.h b/include/linux-private/linux/types.h
new file mode 100644
index 0000000..6546100
--- /dev/null
+++ b/include/linux-private/linux/types.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _LINUX_TYPES_H
+#define _LINUX_TYPES_H
+
+#include <asm/types.h>
+
+#ifndef __ASSEMBLY__
+
+#include <linux/posix_types.h>
+
+
+/*
+ * Below are truly Linux-specific types that should never collide with
+ * any application/library that wants linux/types.h.
+ */
+
+/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */
+#ifdef __CHECKER__
+#define __bitwise	__attribute__((bitwise))
+#else
+#define __bitwise
+#endif
+
+/* The kernel doesn't use this legacy form, but user space does */
+#define __bitwise__ __bitwise
+
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architectures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
+typedef unsigned __bitwise __poll_t;
+
+#endif /*  __ASSEMBLY__ */
+#endif /* _LINUX_TYPES_H */
diff --git a/include/linux-private/linux/version.h b/include/linux-private/linux/version.h
new file mode 100644
index 0000000..4ae7bc0
--- /dev/null
+++ b/include/linux-private/linux/version.h
@@ -0,0 +1,5 @@
+#define LINUX_VERSION_CODE 394240
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + ((c) > 255 ? 255 : (c)))
+#define LINUX_VERSION_MAJOR 6
+#define LINUX_VERSION_PATCHLEVEL 4
+#define LINUX_VERSION_SUBLEVEL 0
diff --git a/include/linux-private/linux/xfrm.h b/include/linux-private/linux/xfrm.h
index 5cdda9d..10bdef8 100644
--- a/include/linux-private/linux/xfrm.h
+++ b/include/linux-private/linux/xfrm.h
@@ -33,7 +33,7 @@
 	__u8	ctx_alg;
 	__u16	ctx_len;
 	__u32	ctx_sid;
-	char	ctx_str[0];
+	char	ctx_str[];
 };
 
 /* Security Context Domains of Interpretation */
@@ -96,27 +96,27 @@
 	__u32		oseq_hi;
 	__u32		seq_hi;
 	__u32		replay_window;
-	__u32		bmp[0];
+	__u32		bmp[];
 };
 
 struct xfrm_algo {
 	char		alg_name[64];
 	unsigned int	alg_key_len;    /* in bits */
-	char		alg_key[0];
+	char		alg_key[];
 };
 
 struct xfrm_algo_auth {
 	char		alg_name[64];
 	unsigned int	alg_key_len;    /* in bits */
 	unsigned int	alg_trunc_len;  /* in bits */
-	char		alg_key[0];
+	char		alg_key[];
 };
 
 struct xfrm_algo_aead {
 	char		alg_name[64];
 	unsigned int	alg_key_len;	/* in bits */
 	unsigned int	alg_icv_len;	/* in bits */
-	char		alg_key[0];
+	char		alg_key[];
 };
 
 struct xfrm_stats {
@@ -215,6 +215,11 @@
 
 	XFRM_MSG_MAPPING,
 #define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
+
+	XFRM_MSG_SETDEFAULT,
+#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT
+	XFRM_MSG_GETDEFAULT,
+#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT
 	__XFRM_MSG_MAX
 };
 #define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@@ -291,7 +296,7 @@
 	XFRMA_ETIMER_THRESH,
 	XFRMA_SRCADDR,		/* xfrm_address_t */
 	XFRMA_COADDR,		/* xfrm_address_t */
-	XFRMA_LASTUSED,		/* unsigned long  */
+	XFRMA_LASTUSED,		/* __u64 */
 	XFRMA_POLICY_TYPE,	/* struct xfrm_userpolicy_type */
 	XFRMA_MIGRATE,
 	XFRMA_ALG_AEAD,		/* struct xfrm_algo_aead */
@@ -304,10 +309,11 @@
 	XFRMA_PROTO,		/* __u8 */
 	XFRMA_ADDRESS_FILTER,	/* struct xfrm_address_filter */
 	XFRMA_PAD,
-	XFRMA_OFFLOAD_DEV,	/* struct xfrm_state_offload */
+	XFRMA_OFFLOAD_DEV,	/* struct xfrm_user_offload */
 	XFRMA_SET_MARK,		/* __u32 */
 	XFRMA_SET_MARK_MASK,	/* __u32 */
 	XFRMA_IF_ID,		/* __u32 */
+	XFRMA_MTIMER_THRESH,	/* __u32 in seconds for input SA */
 	__XFRMA_MAX
 
 #define XFRMA_OUTPUT_MARK XFRMA_SET_MARK	/* Compatibility */
@@ -387,6 +393,7 @@
 };
 
 #define XFRM_SA_XFLAG_DONT_ENCAP_DSCP	1
+#define XFRM_SA_XFLAG_OSEQ_MAY_WRAP	2
 
 struct xfrm_usersa_id {
 	xfrm_address_t			daddr;
@@ -504,8 +511,29 @@
 	int				ifindex;
 	__u8				flags;
 };
+/* This flag was exposed without any kernel code that supports it.
+ * Unfortunately, strongswan has the code that sets this flag,
+ * which makes it impossible to reuse this bit.
+ *
+ * So leave it here to make sure that it won't be reused by mistake.
+ */
 #define XFRM_OFFLOAD_IPV6	1
 #define XFRM_OFFLOAD_INBOUND	2
+/* Two bits above are relevant for state path only, while
+ * offload is used for both policy and state flows.
+ *
+ * In policy offload mode, they are free and can be safely reused.
+ */
+#define XFRM_OFFLOAD_PACKET	4
+
+struct xfrm_userpolicy_default {
+#define XFRM_USERPOLICY_UNSPEC	0
+#define XFRM_USERPOLICY_BLOCK	1
+#define XFRM_USERPOLICY_ACCEPT	2
+	__u8				in;
+	__u8				fwd;
+	__u8				out;
+};
 
 /* backwards compatibility for userspace */
 #define XFRMGRP_ACQUIRE		1
diff --git a/include/netlink-private/genl.h b/include/netlink-private/genl.h
deleted file mode 100644
index ac592bd..0000000
--- a/include/netlink-private/genl.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_GENL_PRIV_H_
-#define NETLINK_GENL_PRIV_H_
-
-#include <netlink-private/netlink.h>
-#include <netlink/netlink.h>
-
-#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
-
-extern int		genl_resolve_id(struct genl_ops *ops);
-
-#endif
diff --git a/include/netlink-private/netlink.h b/include/netlink-private/netlink.h
deleted file mode 100644
index d86a55d..0000000
--- a/include/netlink-private/netlink.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_LOCAL_H_
-#define NETLINK_LOCAL_H_
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <inttypes.h>
-#include <assert.h>
-#include <limits.h>
-#include <search.h>
-
-#include <arpa/inet.h>
-#include <netdb.h>
-
-#include <defs.h>
-
-#ifndef SOL_NETLINK
-#define SOL_NETLINK 270
-#endif
-
-#include <linux/types.h>
-
-/* local header copies */
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/ethtool.h>
-#include <linux/pkt_sched.h>
-#include <linux/pkt_cls.h>
-#include <linux/gen_stats.h>
-#include <linux/atm.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/snmp.h>
-#include <linux/xfrm.h>
-
-#ifndef DISABLE_PTHREADS
-#include <pthread.h>
-#endif
-
-#include <netlink/netlink.h>
-#include <netlink/handlers.h>
-#include <netlink/cache.h>
-#include <netlink/route/tc.h>
-#include <netlink-private/object-api.h>
-#include <netlink-private/cache-api.h>
-#include <netlink-private/types.h>
-#include <netlink-private/utils.h>
-
-#define NSEC_PER_SEC	1000000000L
-
-struct trans_tbl {
-	uint64_t i;
-	const char *a;
-};
-
-#define __ADD(id, name) { .i = id, .a = #name }
-
-struct trans_list {
-	int i;
-	char *a;
-	struct nl_list_head list;
-};
-
-#ifdef NL_DEBUG
-#define NL_DBG(LVL,FMT,ARG...)						\
-	do {								\
-		if (LVL <= nl_debug) {					\
-			int _errsv = errno;				\
-			fprintf(stderr,					\
-				"DBG<" #LVL ">%20s:%-4u %s: " FMT,	\
-				__FILE__, __LINE__,			\
-				__func__, ##ARG);			\
-			errno = _errsv;					\
-		}							\
-	} while (0)
-#else /* NL_DEBUG */
-#define NL_DBG(LVL,FMT,ARG...) do { } while(0)
-#endif /* NL_DEBUG */
-
-#define BUG()                            				\
-	do {                                 				\
-		fprintf(stderr, "BUG at file position %s:%d:%s\n",  	\
-			__FILE__, __LINE__, __func__); 			\
-		assert(0);						\
-	} while (0)
-
-#define BUG_ON(condition)						\
-	do {								\
-		if (condition)						\
-			BUG();						\
-	} while (0)
-
-
-#define APPBUG(msg)							\
-	do {								\
-		fprintf(stderr, "APPLICATION BUG: %s:%d:%s: %s\n",	\
-			__FILE__, __LINE__, __func__, msg);		\
-		assert(0);						\
-	} while(0)
-
-extern int __nl_read_num_str_file(const char *path,
-				  int (*cb)(long, const char *));
-
-extern int __trans_list_add(int, const char *, struct nl_list_head *);
-extern void __trans_list_clear(struct nl_list_head *);
-
-extern char *__type2str(int, char *, size_t, const struct trans_tbl *, size_t);
-extern int __str2type(const char *, const struct trans_tbl *, size_t);
-
-extern char *__list_type2str(int, char *, size_t, struct nl_list_head *);
-extern int __list_str2type(const char *, struct nl_list_head *);
-
-extern char *__flags2str(int, char *, size_t, const struct trans_tbl *, size_t);
-extern int __str2flags(const char *, const struct trans_tbl *, size_t);
-
-extern void dump_from_ops(struct nl_object *, struct nl_dump_params *);
-extern struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex);
-
-static inline int nl_cb_call(struct nl_cb *cb, enum nl_cb_type type, struct nl_msg *msg)
-{
-	int ret;
-
-	cb->cb_active = type;
-	ret = cb->cb_set[type](msg, cb->cb_args[type]);
-	cb->cb_active = __NL_CB_TYPE_MAX;
-	return ret;
-}
-
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-
-/* This is also defined in stddef.h */
-#ifndef offsetof
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-
-#define __init __attribute__ ((constructor))
-#define __exit __attribute__ ((destructor))
-#undef __deprecated
-#define __deprecated __attribute__ ((deprecated))
-
-#define min(x,y) ({ \
-	__typeof__(x) _x = (x);	\
-	__typeof__(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x < _y ? _x : _y; })
-
-#define max(x,y) ({ \
-	__typeof__(x) _x = (x);	\
-	__typeof__(y) _y = (y);	\
-	(void) (&_x == &_y);		\
-	_x > _y ? _x : _y; })
-
-#define min_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
-#define max_t(type,x,y) \
-	({ type __x = (x); type __y = (y); __x > __y ? __x: __y; })
-
-extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
-			  struct nlmsghdr *, struct nl_parser_param *);
-
-
-static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
-				      struct tc_ratespec *src)
-{
-	dst->rs_cell_log = src->cell_log;
-	dst->rs_overhead = src->overhead;
-	dst->rs_cell_align = src->cell_align;
-	dst->rs_mpu = src->mpu;
-	dst->rs_rate64 = src->rate;
-}
-
-static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
-				       struct rtnl_ratespec *src)
-{
-	dst->cell_log = src->rs_cell_log;
-	dst->overhead = src->rs_overhead;
-	dst->cell_align = src->rs_cell_align;
-	dst->mpu = src->rs_mpu;
-	dst->rate = src->rs_rate64 > 0xFFFFFFFFull ? 0xFFFFFFFFull : (uint32_t) src->rs_rate64;
-}
-
-static inline const char *nl_cache_name(struct nl_cache *cache)
-{
-	return cache->c_ops ? cache->c_ops->co_name : "unknown";
-}
-
-#define GENL_FAMILY(id, name) \
-	{ \
-		{ id, NL_ACT_UNSPEC, name }, \
-		END_OF_MSGTYPES_LIST, \
-	}
-
-static inline int wait_for_ack(struct nl_sock *sk)
-{
-	if (sk->s_flags & NL_NO_AUTO_ACK)
-		return 0;
-	else
-		return nl_wait_for_ack(sk);
-}
-
-static inline int build_sysconf_path(char **strp, const char *filename)
-{
-	char *sysconfdir;
-
-	sysconfdir = getenv("NLSYSCONFDIR");
-
-	if (!sysconfdir)
-		sysconfdir = SYSCONFDIR;
-
-	return asprintf(strp, "%s/%s", sysconfdir, filename);
-}
-
-#ifndef DISABLE_PTHREADS
-#define NL_LOCK(NAME) pthread_mutex_t (NAME) = PTHREAD_MUTEX_INITIALIZER
-#define NL_RW_LOCK(NAME) pthread_rwlock_t (NAME) = PTHREAD_RWLOCK_INITIALIZER
-
-static inline void nl_lock(pthread_mutex_t *lock)
-{
-	pthread_mutex_lock(lock);
-}
-
-static inline void nl_unlock(pthread_mutex_t *lock)
-{
-	pthread_mutex_unlock(lock);
-}
-
-static inline void nl_read_lock(pthread_rwlock_t *lock)
-{
-	pthread_rwlock_rdlock(lock);
-}
-
-static inline void nl_read_unlock(pthread_rwlock_t *lock)
-{
-	pthread_rwlock_unlock(lock);
-}
-
-static inline void nl_write_lock(pthread_rwlock_t *lock)
-{
-	pthread_rwlock_wrlock(lock);
-}
-
-static inline void nl_write_unlock(pthread_rwlock_t *lock)
-{
-	pthread_rwlock_unlock(lock);
-}
-
-#else
-#define NL_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused))
-#define NL_RW_LOCK(NAME) int __unused_lock_ ##NAME __attribute__((unused))
-
-#define nl_lock(LOCK) do { } while(0)
-#define nl_unlock(LOCK) do { } while(0)
-#define nl_read_lock(LOCK) do { } while(0)
-#define nl_read_unlock(LOCK) do { } while(0)
-#define nl_write_lock(LOCK) do { } while(0)
-#define nl_write_unlock(LOCK) do { } while(0)
-#endif
-
-static inline int rtnl_tc_calc_txtime64(int bufsize, uint64_t rate)
-{
-	return ((double) bufsize / (double) rate) * 1000000.0;
-}
-
-static inline int rtnl_tc_calc_bufsize64(int txtime, uint64_t rate)
-{
-	return ((double) txtime * (double) rate) / 1000000.0;
-}
-
-#endif
diff --git a/include/netlink-private/nl-auto.h b/include/netlink-private/nl-auto.h
deleted file mode 100644
index 4092782..0000000
--- a/include/netlink-private/nl-auto.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-
-#ifndef NETLINK_NL_AUTO_H_
-#define NETLINK_NL_AUTO_H_
-
-#include <stdlib.h>
-
-#define _nl_auto(fcn)               __attribute__ ((__cleanup__(fcn)))
-
-#define _NL_AUTO_DEFINE_FCN_VOID0(CastType, name, func) \
-static inline void name(void *v) \
-{ \
-	if (*((CastType *) v)) \
-		func(*((CastType *) v)); \
-} \
-struct _nl_dummy_for_tailing_semicolon
-
-#define _NL_AUTO_DEFINE_FCN_STRUCT(CastType, name, func) \
-static inline void name(CastType *v) \
-{ \
-	if (v) \
-		func(v); \
-} \
-struct _nl_dummy_for_tailing_semicolon
-
-#define _NL_AUTO_DEFINE_FCN_TYPED0(CastType, name, func) \
-static inline void name(CastType *v) \
-{ \
-	if (*v) \
-		func(*v); \
-} \
-struct _nl_dummy_for_tailing_semicolon
-
-#define _nl_auto_free _nl_auto(_nl_auto_free_fcn)
-_NL_AUTO_DEFINE_FCN_VOID0(void *, _nl_auto_free_fcn, free);
-
-struct nl_addr;
-void nl_addr_put(struct nl_addr *);
-#define _nl_auto_nl_addr _nl_auto(_nl_auto_nl_addr_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_addr *, _nl_auto_nl_addr_fcn, nl_addr_put);
-
-struct nl_data;
-void nl_data_free(struct nl_data *data);
-#define _nl_auto_nl_data _nl_auto(_nl_auto_nl_data_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_data *, _nl_auto_nl_data_fcn, nl_data_free);
-
-struct nl_msg;
-void nlmsg_free(struct nl_msg *);
-#define _nl_auto_nl_msg _nl_auto(_nl_auto_nl_msg_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_msg *, _nl_auto_nl_msg_fcn, nlmsg_free);
-
-struct rtnl_link;
-void rtnl_link_put(struct rtnl_link *);
-#define _nl_auto_rtnl_link _nl_auto(_nl_auto_rtnl_link_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link *, _nl_auto_rtnl_link_fcn, rtnl_link_put);
-
-struct rtnl_route;
-void rtnl_route_put(struct rtnl_route *);
-#define _nl_auto_rtnl_route _nl_auto(_nl_auto_rtnl_route_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_route *, _nl_auto_rtnl_route_fcn, rtnl_route_put);
-
-struct rtnl_mdb;
-void rtnl_mdb_put(struct rtnl_mdb *);
-#define _nl_auto_rtnl_mdb _nl_auto(_nl_auto_rtnl_mdb_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_mdb *, _nl_auto_rtnl_mdb_fcn, rtnl_mdb_put);
-
-struct rtnl_nexthop;
-void rtnl_route_nh_free(struct rtnl_nexthop *);
-#define _nl_auto_rtnl_nexthop _nl_auto(_nl_auto_rtnl_nexthop_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_nexthop *, _nl_auto_rtnl_nexthop_fcn, rtnl_route_nh_free);
-
-struct nl_cache;
-void nl_cache_put(struct nl_cache *);
-#define _nl_auto_nl_cache _nl_auto(_nl_auto_nl_cache_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_cache *, _nl_auto_nl_cache_fcn, nl_cache_put);
-
-struct rtnl_link_af_ops;
-void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
-#define _nl_auto_rtnl_link_af_ops _nl_auto(_nl_auto_rtnl_link_af_ops_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link_af_ops *, _nl_auto_rtnl_link_af_ops_fcn, rtnl_link_af_ops_put);
-
-struct rtnl_act;
-void rtnl_act_put(struct rtnl_act *);
-#define _nl_auto_rtnl_act _nl_auto(_nl_auto_rtnl_act_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_act *, _nl_auto_rtnl_act_fcn, rtnl_act_put);
-
-struct rtnl_ematch_tree;
-void rtnl_ematch_tree_free(struct rtnl_ematch_tree *);
-#define _nl_auto_rtnl_ematch_tree _nl_auto(_nl_auto_rtnl_ematch_tree_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_ematch_tree *, _nl_auto_rtnl_ematch_tree_fcn, rtnl_ematch_tree_free);
-
-struct rtnl_cls;
-void rtnl_cls_put(struct rtnl_cls *);
-#define _nl_auto_rtnl_cls _nl_auto(_nl_auto_rtnl_cls_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_cls *, _nl_auto_rtnl_cls_fcn, rtnl_cls_put);
-
-struct nl_sock;
-void nl_socket_free(struct nl_sock *);
-#define _nl_auto_nl_socket _nl_auto(_nl_auto_nl_socket_fcn)
-_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_sock *, _nl_auto_nl_socket_fcn, nl_socket_free);
-
-#endif /* NETLINK_NL_AUTO_H_ */
diff --git a/include/netlink-private/route/tc-api.h b/include/netlink-private/route/tc-api.h
deleted file mode 100644
index 1eb27dc..0000000
--- a/include/netlink-private/route/tc-api.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2011-2013 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_TC_API_H_
-#define NETLINK_TC_API_H_
-
-#include <netlink/netlink.h>
-#include <netlink/msg.h>
-#include <netlink/route/tc.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Traffic control object operations
- * @ingroup tc
- *
- * This structure holds function pointers and settings implementing
- * the features of each traffic control object implementation.
- */
-struct rtnl_tc_ops
-{
-	/**
-	 * Name of traffic control module
-	 */
-	char *to_kind;
-
-	/**
-	 * Type of traffic control object
-	 */
-	enum rtnl_tc_type to_type;
-
-
-	/**
-	 * Size of private data
-	 */
-	size_t to_size;
-
-	/**
-	 * Dump callbacks
-	 */
-	void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *,
-				       struct nl_dump_params *);
-	/**
-	 * Used to fill the contents of TCA_OPTIONS
-	 */
-	int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *);
-
-	/**
-	 * Uesd to to fill tc related messages, unlike with to_msg_fill,
-	 * the contents is not encapsulated with a TCA_OPTIONS nested
-	 * attribute.
-	 */
-	int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *);
-
-	/**
-	 * TCA_OPTIONS message parser
-	 */
-	int (*to_msg_parser)(struct rtnl_tc *, void *);
-
-	/**
-	 * Called before a tc object is destroyed
-	 */
-	void (*to_free_data)(struct rtnl_tc *, void *);
-
-	/**
-	 * Called whenever a classifier object needs to be cloned
-	 */
-	int (*to_clone)(void *, void *);
-
-	/**
-	 * Internal, don't touch
-	 */
-	struct nl_list_head to_list;
-};
-
-struct rtnl_tc_type_ops
-{
-	enum rtnl_tc_type tt_type;
-
-	char *tt_dump_prefix;
-
-	/**
-	 * Dump callbacks
-	 */
-	void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *,
-				        struct nl_dump_params *);
-};
-
-extern int			rtnl_tc_msg_parse(struct nlmsghdr *,
-						  struct rtnl_tc *);
-extern int			rtnl_tc_msg_build(struct rtnl_tc *, int,
-						  int, struct nl_msg **);
-
-extern void			rtnl_tc_free_data(struct nl_object *);
-extern int			rtnl_tc_clone(struct nl_object *,
-					      struct nl_object *);
-extern void			rtnl_tc_dump_line(struct nl_object *,
-						  struct nl_dump_params *);
-extern void			rtnl_tc_dump_details(struct nl_object *,
-						     struct nl_dump_params *);
-extern void			rtnl_tc_dump_stats(struct nl_object *,
-						   struct nl_dump_params *);
-extern uint64_t			rtnl_tc_compare(struct nl_object *,
-						struct nl_object *,
-						uint64_t, int);
-
-void *                          rtnl_tc_data_peek(struct rtnl_tc *tc);
-extern void *			rtnl_tc_data(struct rtnl_tc *);
-extern void *			rtnl_tc_data_check(struct rtnl_tc *,
-						   struct rtnl_tc_ops *, int *);
-
-extern struct rtnl_tc_ops *	rtnl_tc_lookup_ops(enum rtnl_tc_type,
-						   const char *);
-extern struct rtnl_tc_ops *	rtnl_tc_get_ops(struct rtnl_tc *);
-extern int 			rtnl_tc_register(struct rtnl_tc_ops *);
-extern void 			rtnl_tc_unregister(struct rtnl_tc_ops *);
-
-extern void			rtnl_tc_type_register(struct rtnl_tc_type_ops *);
-extern void			rtnl_tc_type_unregister(struct rtnl_tc_type_ops *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink-private/socket.h b/include/netlink-private/socket.h
deleted file mode 100644
index 5fe77fa..0000000
--- a/include/netlink-private/socket.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2014 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_SOCKET_PRIV_H_
-#define NETLINK_SOCKET_PRIV_H_
-
-#include <netlink-private/netlink.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int _nl_socket_is_local_port_unspecified (struct nl_sock *sk);
-uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other);
-
-void _nl_socket_used_ports_release_all(const uint32_t *used_ports);
-void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink-private/tc.h b/include/netlink-private/tc.h
deleted file mode 100644
index 5f5d1ff..0000000
--- a/include/netlink-private/tc.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_TC_PRIV_H_
-#define NETLINK_TC_PRIV_H_
-
-#include <netlink-private/netlink.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define TCA_ATTR_HANDLE		0x0001
-#define TCA_ATTR_PARENT		0x0002
-#define TCA_ATTR_IFINDEX	0x0004
-#define TCA_ATTR_KIND		0x0008
-#define TCA_ATTR_FAMILY		0x0010
-#define TCA_ATTR_INFO		0x0020
-#define TCA_ATTR_OPTS		0x0040
-#define TCA_ATTR_STATS		0x0080
-#define TCA_ATTR_XSTATS		0x0100
-#define TCA_ATTR_LINK		0x0200
-#define TCA_ATTR_MTU		0x0400
-#define TCA_ATTR_MPU		0x0800
-#define TCA_ATTR_OVERHEAD	0x1000
-#define TCA_ATTR_LINKTYPE	0x2000
-#define TCA_ATTR_CHAIN          0x4000
-#define TCA_ATTR_MAX            TCA_ATTR_CHAIN
-
-extern int tca_parse(struct nlattr **, int, struct rtnl_tc *,
-                     const struct nla_policy *);
-
-#define RTNL_TC_RTABLE_SIZE	256
-
-extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *,
-				    uint32_t *);
-
-
-static inline void *tca_xstats(struct rtnl_tc *tca)
-{
-	return tca->tc_xstats->d_data;
-}
-
-extern struct nl_af_group tc_groups[];
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
deleted file mode 100644
index b8f785a..0000000
--- a/include/netlink-private/types.h
+++ /dev/null
@@ -1,1388 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
- * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
- */
-
-#ifndef NETLINK_LOCAL_TYPES_H_
-#define NETLINK_LOCAL_TYPES_H_
-
-#include <netlink/list.h>
-#include <netlink/route/link.h>
-#include <netlink/route/qdisc.h>
-#include <netlink/route/rtnl.h>
-#include <netlink/route/route.h>
-#include <netlink/idiag/idiagnl.h>
-#include <netlink/netfilter/ct.h>
-#include <netlink-private/object-api.h>
-#include <netlink-private/route/tc-api.h>
-#include <netlink-private/route/link/sriov.h>
-#include <netlink-private/route/nexthop-encap.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/genetlink.h>
-#include <linux/tc_act/tc_mirred.h>
-#include <linux/tc_act/tc_skbedit.h>
-#include <linux/tc_act/tc_gact.h>
-#include <linux/tc_act/tc_vlan.h>
-#include <linux/sock_diag.h>
-#include <linux/fib_rules.h>
-#include <linux/if_ether.h>
-
-#include <netinet/in.h>
-
-#define NL_SOCK_PASSCRED	(1<<1)
-#define NL_OWN_PORT		(1<<2)
-#define NL_MSG_PEEK		(1<<3)
-#define NL_MSG_PEEK_EXPLICIT	(1<<4)
-#define NL_NO_AUTO_ACK		(1<<5)
-
-#define NL_MSG_CRED_PRESENT 1
-
-struct nl_cache_ops;
-struct nl_sock;
-struct nl_object;
-struct nl_hash_table;
-struct nl_vf_vlans;
-
-struct nl_cb
-{
-	nl_recvmsg_msg_cb_t	cb_set[NL_CB_TYPE_MAX+1];
-	void *			cb_args[NL_CB_TYPE_MAX+1];
-
-	nl_recvmsg_err_cb_t	cb_err;
-	void *			cb_err_arg;
-
-	/** May be used to replace nl_recvmsgs with your own implementation
-	 * in all internal calls to nl_recvmsgs. */
-	int			(*cb_recvmsgs_ow)(struct nl_sock *,
-						  struct nl_cb *);
-
-	/** Overwrite internal calls to nl_recv, must return the number of
-	 * octets read and allocate a buffer for the received data. */
-	int			(*cb_recv_ow)(struct nl_sock *,
-					      struct sockaddr_nl *,
-					      unsigned char **,
-					      struct ucred **);
-
-	/** Overwrites internal calls to nl_send, must send the netlink
-	 * message. */
-	int			(*cb_send_ow)(struct nl_sock *,
-					      struct nl_msg *);
-
-	int			cb_refcnt;
-	/** indicates the callback that is currently active */
-	enum nl_cb_type		cb_active;
-};
-
-struct nl_sock
-{
-	struct sockaddr_nl	s_local;
-	struct sockaddr_nl	s_peer;
-	int			s_fd;
-	int			s_proto;
-	unsigned int		s_seq_next;
-	unsigned int		s_seq_expect;
-	int			s_flags;
-	struct nl_cb *		s_cb;
-	size_t			s_bufsize;
-};
-
-struct nl_cache
-{
-	struct nl_list_head	c_items;
-	int			c_nitems;
-	int                     c_iarg1;
-	int                     c_iarg2;
-	int			c_refcnt;
-	unsigned int		c_flags;
-	struct nl_hash_table *	hashtable;
-	struct nl_cache_ops *   c_ops;
-};
-
-struct nl_cache_assoc
-{
-	struct nl_cache *	ca_cache;
-	change_func_t		ca_change;
-	change_func_v2_t	ca_change_v2;
-	void *			ca_change_data;
-};
-
-struct nl_cache_mngr
-{
-	int			cm_protocol;
-	int			cm_flags;
-	int			cm_nassocs;
-	struct nl_sock *	cm_sock;
-	struct nl_sock *	cm_sync_sock;
-	struct nl_cache_assoc *	cm_assocs;
-};
-
-struct nl_parser_param;
-
-#define LOOSE_COMPARISON	1
-#define ID_COMPARISON           2
-
-#define NL_OBJ_MARK		1
-
-struct nl_data
-{
-	size_t			d_size;
-	void *			d_data;
-};
-
-struct nl_addr
-{
-	int			a_family;
-	unsigned int		a_maxsize;
-	unsigned int		a_len;
-	int			a_prefixlen;
-	int			a_refcnt;
-	char			a_addr[0];
-};
-
-struct nl_msg
-{
-	int			nm_protocol;
-	int			nm_flags;
-	struct sockaddr_nl	nm_src;
-	struct sockaddr_nl	nm_dst;
-	struct ucred		nm_creds;
-	struct nlmsghdr *	nm_nlh;
-	size_t			nm_size;
-	int			nm_refcnt;
-};
-
-struct rtnl_link_map
-{
-	uint64_t lm_mem_start;
-	uint64_t lm_mem_end;
-	uint64_t lm_base_addr;
-	uint16_t lm_irq;
-	uint8_t  lm_dma;
-	uint8_t  lm_port;
-};
-
-struct rtnl_link_vf
-{
-	struct nl_list_head	vf_list;
-	int			ce_refcnt;
-	uint32_t		ce_mask;
-	uint32_t		vf_index;
-	uint64_t		vf_guid_node;
-	uint64_t		vf_guid_port;
-	uint32_t		vf_linkstate;
-	struct nl_addr *	vf_lladdr;
-	uint32_t		vf_max_tx_rate;
-	uint32_t		vf_min_tx_rate;
-	uint32_t		vf_rate;
-	uint32_t		vf_rss_query_en;
-	uint32_t		vf_spoofchk;
-	uint64_t		vf_stats[RTNL_LINK_VF_STATS_MAX+1];
-	uint32_t		vf_trust;
-	struct nl_vf_vlans *	vf_vlans;
-};
-
-#define IFQDISCSIZ	32
-
-struct rtnl_link
-{
-	NLHDR_COMMON
-
-	char				l_name[IFNAMSIZ];
-	uint32_t			l_family;
-	uint32_t			l_arptype;
-	uint32_t			l_index;
-	uint32_t			l_flags;
-	uint32_t			l_change;
-	uint32_t			l_mtu;
-	uint32_t			l_link;
-	int32_t                         l_link_netnsid;
-	uint32_t			l_txqlen;
-	uint32_t			l_weight;
-	uint32_t			l_master;
-	struct nl_addr *		l_addr;
-	struct nl_addr *		l_bcast;
-	char				l_qdisc[IFQDISCSIZ];
-	struct rtnl_link_map		l_map;
-	uint64_t			l_stats[RTNL_LINK_STATS_MAX+1];
-	uint32_t			l_flag_mask;
-	uint32_t			l_num_vf;
-	uint8_t				l_operstate;
-	uint8_t				l_linkmode;
-	/* 2 byte hole */
-	char *				l_info_kind;
-	char *				l_info_slave_kind;
-	struct rtnl_link_info_ops *	l_info_ops;
-	void *				l_af_data[AF_MAX];
-	void *				l_info;
-	char *				l_ifalias;
-	uint32_t			l_promiscuity;
-	uint32_t			l_num_tx_queues;
-	uint32_t			l_num_rx_queues;
-	uint32_t			l_gso_max_segs;
-	uint32_t			l_gso_max_size;
-	uint32_t			l_group;
-	uint8_t				l_carrier;
-	/* 3 byte hole */
-	uint32_t			l_carrier_changes;
-	struct rtnl_link_af_ops *	l_af_ops;
-	struct nl_data *		l_phys_port_id;
-	char				l_phys_port_name[IFNAMSIZ];
-	struct nl_data *		l_phys_switch_id;
-	int				l_ns_fd;
-	pid_t				l_ns_pid;
-	struct rtnl_link_vf *		l_vf_list;
-};
-
-struct rtnl_ncacheinfo
-{
-	uint32_t nci_confirmed;	/**< Time since neighbour validty was last confirmed */
-	uint32_t nci_used;	/**< Time since neighbour entry was last ued */
-	uint32_t nci_updated;	/**< Time since last update */
-	uint32_t nci_refcnt;	/**< Reference counter */
-};
-
-
-struct rtnl_neigh
-{
-	NLHDR_COMMON
-	uint32_t	n_family;
-	uint32_t	n_ifindex;
-	uint16_t	n_state;
-	uint8_t		n_flags;
-	uint8_t		n_type;
-	struct nl_addr *n_lladdr;
-	struct nl_addr *n_dst;
-	uint32_t	n_probes;
-	struct rtnl_ncacheinfo n_cacheinfo;
-	uint32_t                n_state_mask;
-	uint32_t                n_flag_mask;
-	uint32_t		n_master;
-	uint16_t	n_vlan;
-};
-
-
-struct rtnl_addr_cacheinfo
-{
-	/* Preferred lifetime in seconds, ticking from when the message gets constructed */
-	uint32_t aci_prefered;
-
-	/* Valid lifetime in seconds, ticking from when the message gets constructed */
-	uint32_t aci_valid;
-
-	/* Timestamp of creation in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
-	uint32_t aci_cstamp;
-
-	/* Timestamp of last update in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
-	uint32_t aci_tstamp;
-};
-
-struct rtnl_addr
-{
-	NLHDR_COMMON
-
-	uint8_t		a_family;
-	uint8_t		a_prefixlen;
-	uint8_t		a_scope;
-	uint32_t	a_flags;
-	uint32_t	a_ifindex;
-
-	struct nl_addr *a_peer;
-	struct nl_addr *a_local;
-	struct nl_addr *a_bcast;
-	struct nl_addr *a_anycast;
-	struct nl_addr *a_multicast;
-
-	struct rtnl_addr_cacheinfo a_cacheinfo;
-
-	char a_label[IFNAMSIZ];
-	uint32_t a_flag_mask;
-	struct rtnl_link *a_link;
-};
-
-struct rtnl_nh_encap
-{
-	struct nh_encap_ops *ops;
-	void *priv;    /* private data for encap type */
-};
-
-struct rtnl_nexthop
-{
-	uint8_t			rtnh_flags;
-	uint8_t			rtnh_flag_mask;
-	uint8_t			rtnh_weight;
-	/* 1 byte spare */
-	uint32_t		rtnh_ifindex;
-	struct nl_addr *	rtnh_gateway;
-	uint32_t		ce_mask; /* HACK to support attr macros */
-	struct nl_list_head	rtnh_list;
-	uint32_t		rtnh_realms;
-	struct nl_addr *	rtnh_newdst;
-	struct nl_addr *	rtnh_via;
-	struct rtnl_nh_encap *	rtnh_encap;
-};
-
-struct rtnl_route
-{
-	NLHDR_COMMON
-
-	uint8_t			rt_family;
-	uint8_t			rt_dst_len;
-	uint8_t			rt_src_len;
-	uint8_t			rt_tos;
-	uint8_t			rt_protocol;
-	uint8_t			rt_scope;
-	uint8_t			rt_type;
-	uint8_t			rt_nmetrics;
-	uint8_t			rt_ttl_propagate;
-	uint32_t		rt_flags;
-	struct nl_addr *	rt_dst;
-	struct nl_addr *	rt_src;
-	uint32_t		rt_table;
-	uint32_t		rt_iif;
-	uint32_t		rt_prio;
-	uint32_t		rt_metrics[RTAX_MAX];
-	uint32_t		rt_metrics_mask;
-	uint32_t		rt_nr_nh;
-	struct nl_addr *	rt_pref_src;
-	struct nl_list_head	rt_nexthops;
-	struct rtnl_rtcacheinfo	rt_cacheinfo;
-	uint32_t		rt_flag_mask;
-};
-
-struct rtnl_rule
-{
-	NLHDR_COMMON
-	uint8_t		r_family;
-	uint8_t		r_action;
-	uint8_t		r_dsfield; /* ipv4 only */
-	uint8_t		r_l3mdev;
-	uint8_t		r_protocol; /* protocol that installed rule */
-	uint8_t		r_ip_proto; /* IP/IPv6 protocol */
-	uint32_t	r_table;
-	uint32_t	r_flags;
-	uint32_t	r_prio;
-	uint32_t	r_mark;
-	uint32_t	r_mask;
-	uint32_t	r_goto;
-	uint32_t	r_flow; /* ipv4 only */
-	struct nl_addr *r_src;
-	struct nl_addr *r_dst;
-	char		r_iifname[IFNAMSIZ];
-	char		r_oifname[IFNAMSIZ];
-
-	struct fib_rule_port_range	r_sport;
-	struct fib_rule_port_range	r_dport;
-};
-
-struct rtnl_neightbl_parms
-{
-	/**
-	 * Interface index of the device this parameter set is assigned
-	 * to or 0 for the default set.
-	 */
-	uint32_t		ntp_ifindex;
-
-	/**
-	 * Number of references to this parameter set.
-	 */
-	uint32_t		ntp_refcnt;
-
-	/**
-	 * Queue length for pending arp requests, i.e. the number of
-	 * packets which are accepted from other layers while the
-	 * neighbour address is still being resolved
-	 */
-	uint32_t		ntp_queue_len;
-
-	/**
-	 * Number of requests to send to the user level ARP daemon.
-	 * Specify 0 to disable.
-	 */
-	uint32_t		ntp_app_probes;
-
-	/**
-	 * Maximum number of retries for unicast solicitation.
-	 */
-	uint32_t		ntp_ucast_probes;
-
-	/**
-	 * Maximum number of retries for multicast solicitation.
-	 */
-	uint32_t		ntp_mcast_probes;
-
-	/**
-	 * Base value in milliseconds to ompute reachable time, see RFC2461.
-	 */
-	uint64_t		ntp_base_reachable_time;
-
-	/**
-	 * Actual reachable time (read-only)
-	 */
-	uint64_t		ntp_reachable_time;	/* secs */
-
-	/**
-	 * The time in milliseconds between retransmitted Neighbor
-	 * Solicitation messages.
-	 */
-	uint64_t		ntp_retrans_time;
-
-	/**
-	 * Interval in milliseconds to check for stale neighbour
-	 * entries.
-	 */
-	uint64_t		ntp_gc_stale_time;	/* secs */
-
-	/**
-	 * Delay in milliseconds for the first time probe if
-	 * the neighbour is reachable.
-	 */
-	uint64_t		ntp_probe_delay;	/* secs */
-
-	/**
-	 * Maximum delay in milliseconds of an answer to a neighbour
-	 * solicitation message.
-	 */
-	uint64_t		ntp_anycast_delay;
-
-	/**
-	 * Minimum age in milliseconds before a neighbour entry
-	 * may be replaced.
-	 */
-	uint64_t		ntp_locktime;
-
-	/**
-	 * Delay in milliseconds before answering to an ARP request
-	 * for which a proxy ARP entry exists.
-	 */
-	uint64_t		ntp_proxy_delay;
-
-	/**
-	 * Queue length for the delayed proxy arp requests.
-	 */
-	uint32_t		ntp_proxy_qlen;
-
-	/**
-	 * Mask of available parameter attributes
-	 */
-	uint32_t		ntp_mask;
-};
-
-#define NTBLNAMSIZ	32
-
-/**
- * Neighbour table
- * @ingroup neightbl
- */
-struct rtnl_neightbl
-{
-	NLHDR_COMMON
-
-	char			nt_name[NTBLNAMSIZ];
-	uint32_t		nt_family;
-	uint32_t		nt_gc_thresh1;
-	uint32_t		nt_gc_thresh2;
-	uint32_t		nt_gc_thresh3;
-	uint64_t		nt_gc_interval;
-	struct ndt_config	nt_config;
-	struct rtnl_neightbl_parms nt_parms;
-	struct ndt_stats	nt_stats;
-};
-
-struct rtnl_ratespec
-{
-	uint64_t		rs_rate64;
-	uint16_t		rs_overhead;
-	int16_t			rs_cell_align;
-	uint16_t		rs_mpu;
-	uint8_t			rs_cell_log;
-};
-
-struct rtnl_tstats
-{
-	struct {
-		uint64_t            bytes;
-		uint64_t            packets;
-	} tcs_basic;
-
-	struct {
-		uint32_t            bps;
-		uint32_t            pps;
-	} tcs_rate_est;
-
-	struct {
-		uint32_t            qlen;
-		uint32_t            backlog;
-		uint32_t            drops;
-		uint32_t            requeues;
-		uint32_t            overlimits;
-	} tcs_queue;
-};
-
-#define TCKINDSIZ	32
-
-#define NL_TC_GENERIC(pre)				\
-	NLHDR_COMMON					\
-	uint32_t		pre ##_family;		\
-	uint32_t		pre ##_ifindex;		\
-	uint32_t		pre ##_handle;		\
-	uint32_t		pre ##_parent;		\
-	uint32_t		pre ##_info;		\
-	uint32_t		pre ##_mtu;		\
-	uint32_t		pre ##_mpu;		\
-	uint32_t		pre ##_overhead;	\
-	uint32_t		pre ##_linktype;	\
-	char			pre ##_kind[TCKINDSIZ];	\
-	struct nl_data *	pre ##_opts;		\
-	uint64_t		pre ##_stats[RTNL_TC_STATS_MAX+1]; \
-	struct nl_data *	pre ##_xstats;		\
-	struct nl_data *	pre ##_subdata;		\
-	struct rtnl_link *	pre ##_link;		\
-	struct rtnl_tc_ops *	pre ##_ops;		\
-	enum rtnl_tc_type	pre ##_type;		\
-	uint32_t		pre ##_chain
-
-struct rtnl_tc
-{
-	NL_TC_GENERIC(tc);
-};
-
-struct rtnl_qdisc
-{
-	NL_TC_GENERIC(q);
-};
-
-struct rtnl_class
-{
-	NL_TC_GENERIC(c);
-};
-
-struct rtnl_cls
-{
-	NL_TC_GENERIC(c);
-	uint16_t		c_prio;
-	uint16_t		c_protocol;
-};
-
-struct rtnl_act
-{
-	NL_TC_GENERIC(c);
-	struct rtnl_act *	a_next;
-};
-
-struct rtnl_mirred
-{
-	struct tc_mirred m_parm;
-};
-
-struct rtnl_skbedit
-{
-	struct tc_skbedit s_parm;
-	uint32_t	  s_flags;
-	uint32_t	  s_mark;
-	uint32_t	  s_prio;
-	uint16_t	  s_queue_mapping;
-};
-
-struct rtnl_gact
-{
-	struct tc_gact g_parm;
-};
-
-struct rtnl_u32
-{
-	uint32_t		cu_divisor;
-	uint32_t		cu_hash;
-	uint32_t		cu_classid;
-	uint32_t		cu_link;
-	struct nl_data *	cu_pcnt;
-	struct nl_data *	cu_selector;
-	struct nl_data *	cu_mark;
-	struct rtnl_act*	cu_act;
-	struct nl_data *	cu_police;
-	char			cu_indev[IFNAMSIZ];
-	int			cu_mask;
-};
-
-struct rtnl_mall
-{
-	uint32_t         m_classid;
-	uint32_t         m_flags;
-	struct rtnl_act *m_act;
-	int              m_mask;
-};
-
-struct rtnl_flower
-{
-	struct rtnl_act *cf_act;
-	int              cf_mask;
-	uint32_t         cf_flags;
-	uint16_t         cf_proto;
-	uint16_t         cf_vlan_id;
-	uint16_t         cf_vlan_ethtype;
-	uint8_t          cf_vlan_prio;
-	uint8_t          cf_src_mac[ETH_ALEN];
-	uint8_t          cf_src_mac_mask[ETH_ALEN];
-	uint8_t          cf_dst_mac[ETH_ALEN];
-	uint8_t          cf_dst_mac_mask[ETH_ALEN];
-	in_addr_t        cf_ipv4_src;
-	in_addr_t        cf_ipv4_src_mask;
-	in_addr_t        cf_ipv4_dst;
-	in_addr_t        cf_ipv4_dst_mask;
-	uint8_t          cf_ip_dscp;
-	uint8_t          cf_ip_dscp_mask;
-};
-
-struct rtnl_cgroup
-{
-	struct rtnl_ematch_tree *cg_ematch;
-	int			cg_mask;
-};
-
-struct rtnl_fw
-{
-	uint32_t		cf_classid;
-	struct nl_data *	cf_act;
-	struct nl_data *	cf_police;
-	char			cf_indev[IFNAMSIZ];
-	uint32_t		cf_fwmask;
-	int			cf_mask;
-};
-
-struct rtnl_ematch
-{
-	uint16_t		e_id;
-	uint16_t		e_kind;
-	uint16_t		e_flags;
-	uint16_t		e_index;
-	size_t			e_datalen;
-
-	struct nl_list_head	e_childs;
-	struct nl_list_head	e_list;
-	struct rtnl_ematch_ops *e_ops;
-
-	void *			e_data;
-};
-
-struct rtnl_ematch_tree
-{
-	uint16_t		et_progid;
-	struct nl_list_head	et_list;
-
-};
-
-struct rtnl_dsmark_qdisc
-{
-	uint16_t	qdm_indices;
-	uint16_t	qdm_default_index;
-	uint32_t	qdm_set_tc_index;
-	uint32_t	qdm_mask;
-};
-
-struct rtnl_dsmark_class
-{
-	uint8_t		cdm_bmask;
-	uint8_t		cdm_value;
-	uint32_t	cdm_mask;
-};
-
-struct rtnl_fifo
-{
-	uint32_t	qf_limit;
-	uint32_t	qf_mask;
-};
-
-struct rtnl_prio
-{
-	uint32_t	qp_bands;
-	uint8_t		qp_priomap[TC_PRIO_MAX+1];
-	uint32_t	qp_mask;
-};
-
-struct rtnl_mqprio
-{
-        uint8_t         qm_num_tc;
-        uint8_t         qm_prio_map[TC_QOPT_BITMASK + 1];
-        uint8_t         qm_hw;
-        uint16_t        qm_count[TC_QOPT_MAX_QUEUE];
-        uint16_t        qm_offset[TC_QOPT_MAX_QUEUE];
-        uint16_t        qm_mode;
-        uint16_t        qm_shaper;
-        uint64_t        qm_min_rate[TC_QOPT_MAX_QUEUE];
-        uint64_t        qm_max_rate[TC_QOPT_MAX_QUEUE];
-        uint32_t        qm_mask;
-};
-
-struct rtnl_tbf
-{
-	uint32_t		qt_limit;
-	struct rtnl_ratespec	qt_rate;
-	uint32_t		qt_rate_bucket;
-	uint32_t		qt_rate_txtime;
-	struct rtnl_ratespec	qt_peakrate;
-	uint32_t		qt_peakrate_bucket;
-	uint32_t		qt_peakrate_txtime;
-	uint32_t		qt_mask;
-};
-
-struct rtnl_sfq
-{
-	uint32_t	qs_quantum;
-	uint32_t	qs_perturb;
-	uint32_t	qs_limit;
-	uint32_t	qs_divisor;
-	uint32_t	qs_flows;
-	uint32_t	qs_mask;
-};
-
-struct rtnl_netem_corr
-{
-	uint32_t	nmc_delay;
-	uint32_t	nmc_loss;
-	uint32_t	nmc_duplicate;
-};
-
-struct rtnl_netem_reo
-{
-	uint32_t	nmro_probability;
-	uint32_t	nmro_correlation;
-};
-
-struct rtnl_netem_crpt
-{
-	uint32_t	nmcr_probability;
-	uint32_t	nmcr_correlation;
-};
-
-struct rtnl_netem_dist
-{
-	int16_t	*	dist_data;
-	size_t		dist_size;
-};
-
-struct rtnl_netem
-{
-	uint32_t		qnm_latency;
-	uint32_t		qnm_limit;
-	uint32_t		qnm_loss;
-	uint32_t		qnm_gap;
-	uint32_t		qnm_duplicate;
-	uint32_t		qnm_jitter;
-	uint32_t		qnm_mask;
-	struct rtnl_netem_corr	qnm_corr;
-	struct rtnl_netem_reo	qnm_ro;
-	struct rtnl_netem_crpt	qnm_crpt;
-	struct rtnl_netem_dist  qnm_dist;
-};
-
-struct rtnl_htb_qdisc
-{
-	uint32_t		qh_rate2quantum;
-	uint32_t		qh_defcls;
-	uint32_t		qh_mask;
-	uint32_t		qh_direct_pkts;
-};
-
-struct rtnl_htb_class
-{
-	uint32_t		ch_prio;
-	struct rtnl_ratespec	ch_rate;
-	struct rtnl_ratespec	ch_ceil;
-	uint32_t		ch_rbuffer;
-	uint32_t		ch_cbuffer;
-	uint32_t		ch_quantum;
-	uint32_t		ch_mask;
-	uint32_t		ch_level;
-};
-
-struct rtnl_cbq
-{
-	struct tc_cbq_lssopt    cbq_lss;
-	struct tc_ratespec      cbq_rate;
-	struct tc_cbq_wrropt    cbq_wrr;
-	struct tc_cbq_ovl       cbq_ovl;
-	struct tc_cbq_fopt      cbq_fopt;
-	struct tc_cbq_police    cbq_police;
-};
-
-struct rtnl_red
-{
-	uint32_t	qr_limit;
-	uint32_t	qr_qth_min;
-	uint32_t	qr_qth_max;
-	uint8_t		qr_flags;
-	uint8_t		qr_wlog;
-	uint8_t		qr_plog;
-	uint8_t		qr_scell_log;
-	uint32_t	qr_mask;
-};
-
-struct rtnl_plug
-{
-	int             action;
-	uint32_t        limit;
-};
-
-struct rtnl_fq_codel
-{
-	int		fq_limit;
-	uint32_t	fq_target;
-	uint32_t	fq_interval;
-	int		fq_flows;
-	uint32_t	fq_quantum;
-	int		fq_ecn;
-	uint32_t	fq_mask;
-};
-
-struct rtnl_hfsc_qdisc
-{
-	uint32_t		qh_defcls;
-	uint32_t		qh_mask;
-};
-
-struct rtnl_hfsc_class
-{
-	struct tc_service_curve ch_rsc;
-	struct tc_service_curve ch_fsc;
-	struct tc_service_curve ch_usc;
-	uint32_t		ch_mask;
-};
-
-struct flnl_request
-{
-	NLHDR_COMMON
-
-	struct nl_addr *	lr_addr;
-	uint32_t		lr_fwmark;
-	uint8_t			lr_tos;
-	uint8_t			lr_scope;
-	uint8_t			lr_table;
-};
-
-
-struct flnl_result
-{
-	NLHDR_COMMON
-
-	struct flnl_request *	fr_req;
-	uint8_t			fr_table_id;
-	uint8_t			fr_prefixlen;
-	uint8_t			fr_nh_sel;
-	uint8_t			fr_type;
-	uint8_t			fr_scope;
-	uint32_t		fr_error;
-};
-
-#define GENL_OP_HAS_POLICY	1
-#define GENL_OP_HAS_DOIT	2
-#define GENL_OP_HAS_DUMPIT	4
-
-struct genl_family_op
-{
-	uint32_t		o_id;
-	uint32_t		o_flags;
-
-	struct nl_list_head	o_list;
-};
-
-struct genl_family_grp {
-        struct genl_family      *family;        /* private */
-        struct nl_list_head     list;           /* private */
-        char                    name[GENL_NAMSIZ];
-        u_int32_t               id;
-};
-
-struct genl_family
-{
-	NLHDR_COMMON
-
-	uint16_t		gf_id;
-	char 			gf_name[GENL_NAMSIZ];
-	uint32_t		gf_version;
-	uint32_t		gf_hdrsize;
-	uint32_t		gf_maxattr;
-
-	struct nl_list_head	gf_ops;
-	struct nl_list_head	gf_mc_grps;
-};
-
-union nfnl_ct_proto
-{
-	struct {
-		uint16_t	src;
-		uint16_t	dst;
-	} port;
-	struct {
-		uint16_t	id;
-		uint8_t		type;
-		uint8_t		code;
-	} icmp;
-};
-
-struct nfnl_ct_dir {
-	struct nl_addr *	src;
-	struct nl_addr *	dst;
-	union nfnl_ct_proto	proto;
-	uint64_t		packets;
-	uint64_t		bytes;
-};
-
-union nfnl_ct_protoinfo {
-	struct {
-		uint8_t		state;
-	} tcp;
-};
-
-struct nfnl_ct {
-	NLHDR_COMMON
-
-	uint8_t			ct_family;
-	uint8_t			ct_proto;
-	union nfnl_ct_protoinfo	ct_protoinfo;
-
-	uint32_t		ct_status;
-	uint32_t		ct_status_mask;
-	uint32_t		ct_timeout;
-	uint32_t		ct_mark;
-	uint32_t		ct_use;
-	uint32_t		ct_id;
-	uint16_t		ct_zone;
-
-	struct nfnl_ct_dir	ct_orig;
-	struct nfnl_ct_dir	ct_repl;
-
-	struct nfnl_ct_timestamp ct_tstamp;
-};
-
-union nfnl_exp_protodata {
-	struct {
-		uint16_t	src;
-		uint16_t	dst;
-	} port;
-	struct {
-		uint16_t	id;
-		uint8_t		type;
-		uint8_t		code;
-	} icmp;
-};
-
-// Allow for different master/expect l4 protocols
-struct nfnl_exp_proto
-{
-	uint8_t						l4protonum;
-	union nfnl_exp_protodata	l4protodata;
-};
-
-struct nfnl_exp_dir {
-	struct nl_addr *		src;
-	struct nl_addr *		dst;
-	struct nfnl_exp_proto	proto;
-};
-
-struct nfnl_exp {
-	NLHDR_COMMON
-
-	uint8_t			exp_family;
-	uint32_t		exp_timeout;
-	uint32_t		exp_id;
-	uint16_t		exp_zone;
-	uint32_t		exp_class;
-	uint32_t		exp_flags;
-	char *			exp_helper_name;
-	char *			exp_fn;
-	uint8_t			exp_nat_dir;
-
-	struct nfnl_exp_dir		exp_expect;
-	struct nfnl_exp_dir		exp_master;
-	struct nfnl_exp_dir		exp_mask;
-	struct nfnl_exp_dir		exp_nat;
-};
-
-struct nfnl_log {
-	NLHDR_COMMON
-
-	uint16_t		log_group;
-	uint8_t			log_copy_mode;
-	uint32_t		log_copy_range;
-	uint32_t		log_flush_timeout;
-	uint32_t		log_alloc_size;
-	uint32_t		log_queue_threshold;
-	uint32_t		log_flags;
-	uint32_t		log_flag_mask;
-};
-
-struct nfnl_log_msg {
-	NLHDR_COMMON
-
-	uint8_t			log_msg_family;
-	uint8_t			log_msg_hook;
-	uint16_t		log_msg_hwproto;
-	uint32_t		log_msg_mark;
-	struct timeval		log_msg_timestamp;
-	uint32_t		log_msg_indev;
-	uint32_t		log_msg_outdev;
-	uint32_t		log_msg_physindev;
-	uint32_t		log_msg_physoutdev;
-	uint8_t			log_msg_hwaddr[8];
-	int			log_msg_hwaddr_len;
-	void *			log_msg_payload;
-	int			log_msg_payload_len;
-	char *			log_msg_prefix;
-	uint32_t		log_msg_uid;
-	uint32_t		log_msg_gid;
-	uint32_t		log_msg_seq;
-	uint32_t		log_msg_seq_global;
-	uint16_t		log_msg_hwtype;
-	uint16_t		log_msg_hwlen;
-	void *			log_msg_hwheader;
-	int			log_msg_hwheader_len;
-	uint16_t		log_msg_vlan_tag;
-	uint16_t		log_msg_vlan_proto;
-	uint32_t		log_msg_ct_info;
-	struct nfnl_ct *	log_msg_ct;
-};
-
-struct nfnl_queue {
-	NLHDR_COMMON
-
-	uint16_t		queue_group;
-	uint32_t		queue_maxlen;
-	uint32_t		queue_copy_range;
-	uint8_t			queue_copy_mode;
-};
-
-struct nfnl_queue_msg {
-	NLHDR_COMMON
-
-	uint16_t		queue_msg_group;
-	uint8_t			queue_msg_family;
-	uint8_t			queue_msg_hook;
-	uint16_t		queue_msg_hwproto;
-	uint32_t		queue_msg_packetid;
-	uint32_t		queue_msg_mark;
-	struct timeval		queue_msg_timestamp;
-	uint32_t		queue_msg_indev;
-	uint32_t		queue_msg_outdev;
-	uint32_t		queue_msg_physindev;
-	uint32_t		queue_msg_physoutdev;
-	uint8_t			queue_msg_hwaddr[8];
-	int			queue_msg_hwaddr_len;
-	void *			queue_msg_payload;
-	int			queue_msg_payload_len;
-	uint32_t		queue_msg_verdict;
-};
-
-struct ematch_quoted {
-	char *	data;
-	size_t	len;
-	int	index;
-};
-
-struct idiagnl_meminfo {
-	NLHDR_COMMON
-
-	uint32_t idiag_rmem;
-	uint32_t idiag_wmem;
-	uint32_t idiag_fmem;
-	uint32_t idiag_tmem;
-};
-
-struct idiagnl_vegasinfo {
-	NLHDR_COMMON
-
-	uint32_t tcpv_enabled;
-	uint32_t tcpv_rttcnt;
-	uint32_t tcpv_rtt;
-	uint32_t tcpv_minrtt;
-};
-
-struct idiagnl_msg {
-	NLHDR_COMMON
-
-	uint8_t			    idiag_family;
-	uint8_t			    idiag_state;
-	uint8_t			    idiag_timer;
-	uint8_t			    idiag_retrans;
-	uint16_t		    idiag_sport;
-	uint16_t		    idiag_dport;
-	struct nl_addr *	    idiag_src;
-	struct nl_addr *	    idiag_dst;
-	uint32_t		    idiag_ifindex;
-	uint32_t		    idiag_expires;
-	uint32_t		    idiag_rqueue;
-	uint32_t		    idiag_wqueue;
-	uint32_t		    idiag_uid;
-	uint32_t		    idiag_inode;
-
-	uint8_t			    idiag_tos;
-	uint8_t			    idiag_tclass;
-	uint8_t			    idiag_shutdown;
-	char *			    idiag_cong;
-	struct idiagnl_meminfo *    idiag_meminfo;
-	struct idiagnl_vegasinfo *  idiag_vegasinfo;
-	struct tcp_info		    idiag_tcpinfo;
-	uint32_t		    idiag_skmeminfo[SK_MEMINFO_VARS];
-};
-
-struct idiagnl_req {
-	NLHDR_COMMON
-
-	uint8_t			idiag_family;
-	uint8_t			idiag_ext;
-	struct nl_addr *	idiag_src;
-	struct nl_addr *	idiag_dst;
-	uint32_t		idiag_ifindex;
-	uint32_t		idiag_states;
-	uint32_t		idiag_dbs;
-};
-
-// XFRM related definitions
-
-/* Selector, used as selector both on policy rules (SPD) and SAs. */
-struct xfrmnl_sel {
-	uint32_t        refcnt;
-	struct nl_addr* daddr;
-	struct nl_addr* saddr;
-	uint16_t        dport;
-	uint16_t        dport_mask;
-	uint16_t        sport;
-	uint16_t        sport_mask;
-	uint16_t        family;
-	uint8_t         prefixlen_d;
-	uint8_t         prefixlen_s;
-	uint8_t         proto;
-	int32_t         ifindex;
-	uint32_t        user;
-};
-
-/* Lifetime configuration, used for both policy rules (SPD) and SAs. */
-struct xfrmnl_ltime_cfg {
-	uint32_t        refcnt;
-	uint64_t        soft_byte_limit;
-	uint64_t        hard_byte_limit;
-	uint64_t        soft_packet_limit;
-	uint64_t        hard_packet_limit;
-	uint64_t        soft_add_expires_seconds;
-	uint64_t        hard_add_expires_seconds;
-	uint64_t        soft_use_expires_seconds;
-	uint64_t        hard_use_expires_seconds;
-};
-
-/* Current lifetime, used for both policy rules (SPD) and SAs. */
-struct xfrmnl_lifetime_cur {
-	uint64_t        bytes;
-	uint64_t        packets;
-	uint64_t        add_time;
-	uint64_t        use_time;
-};
-
-struct xfrmnl_replay_state {
-	uint32_t        oseq;
-	uint32_t        seq;
-	uint32_t        bitmap;
-};
-
-struct xfrmnl_replay_state_esn {
-	uint32_t        bmp_len;
-	uint32_t        oseq;
-	uint32_t        seq;
-	uint32_t        oseq_hi;
-	uint32_t        seq_hi;
-	uint32_t        replay_window;
-	uint32_t        bmp[0];
-};
-
-struct xfrmnl_mark {
-	uint32_t        v; /* value */
-	uint32_t        m; /* mask */
-};
-
-/* XFRM AE related definitions */
-
-struct xfrmnl_sa_id {
-	struct nl_addr* daddr;
-	uint32_t        spi;
-	uint16_t        family;
-	uint8_t         proto;
-};
-
-struct xfrmnl_ae {
-	NLHDR_COMMON
-
-	struct xfrmnl_sa_id             sa_id;
-	struct nl_addr*                 saddr;
-	uint32_t                        flags;
-	uint32_t                        reqid;
-	struct xfrmnl_mark              mark;
-	struct xfrmnl_lifetime_cur      lifetime_cur;
-	uint32_t                        replay_maxage;
-	uint32_t                        replay_maxdiff;
-	struct xfrmnl_replay_state      replay_state;
-	struct xfrmnl_replay_state_esn* replay_state_esn;
-};
-
-/* XFRM SA related definitions */
-
-struct xfrmnl_id {
-	struct nl_addr* daddr;
-	uint32_t        spi;
-	uint8_t         proto;
-};
-
-struct xfrmnl_stats {
-	uint32_t        replay_window;
-	uint32_t        replay;
-	uint32_t        integrity_failed;
-};
-
-struct xfrmnl_algo_aead {
-	char            alg_name[64];
-	uint32_t        alg_key_len;    /* in bits */
-	uint32_t        alg_icv_len;    /* in bits */
-	char            alg_key[0];
-};
-
-struct xfrmnl_algo_auth {
-	char            alg_name[64];
-	uint32_t        alg_key_len;    /* in bits */
-	uint32_t        alg_trunc_len;  /* in bits */
-	char            alg_key[0];
-};
-
-struct xfrmnl_algo {
-	char            alg_name[64];
-	uint32_t        alg_key_len;    /* in bits */
-	char            alg_key[0];
-};
-
-struct xfrmnl_encap_tmpl {
-	uint16_t        encap_type;
-	uint16_t        encap_sport;
-	uint16_t        encap_dport;
-	struct nl_addr* encap_oa;
-};
-
-struct xfrmnl_user_offload {
-	int             ifindex;
-	uint8_t         flags;
-};
-
-struct xfrmnl_sa {
-	NLHDR_COMMON
-
-	struct xfrmnl_sel*              sel;
-	struct xfrmnl_id                id;
-	struct nl_addr*                 saddr;
-	struct xfrmnl_ltime_cfg*        lft;
-	struct xfrmnl_lifetime_cur      curlft;
-	struct xfrmnl_stats             stats;
-	uint32_t                        seq;
-	uint32_t                        reqid;
-	uint16_t                        family;
-	uint8_t                         mode;        /* XFRM_MODE_xxx */
-	uint8_t                         replay_window;
-	uint8_t                         flags;
-	struct xfrmnl_algo_aead*        aead;
-	struct xfrmnl_algo_auth*        auth;
-	struct xfrmnl_algo*             crypt;
-	struct xfrmnl_algo*             comp;
-	struct xfrmnl_encap_tmpl*       encap;
-	uint32_t                        tfcpad;
-	struct nl_addr*                 coaddr;
-	struct xfrmnl_mark              mark;
-	struct xfrmnl_user_sec_ctx*     sec_ctx;
-	uint32_t                        replay_maxage;
-	uint32_t                        replay_maxdiff;
-	struct xfrmnl_replay_state      replay_state;
-	struct xfrmnl_replay_state_esn* replay_state_esn;
-	uint8_t                         hard;
-	struct xfrmnl_user_offload*     user_offload;
-};
-
-struct xfrmnl_usersa_flush {
-	uint8_t                         proto;
-};
-
-
-/* XFRM SP related definitions */
-
-struct xfrmnl_userpolicy_id {
-	struct xfrmnl_sel               sel;
-	uint32_t                        index;
-	uint8_t                         dir;
-};
-
-struct xfrmnl_user_sec_ctx {
-	uint16_t                        len;
-	uint16_t                        exttype;
-	uint8_t                         ctx_alg;
-	uint8_t                         ctx_doi;
-	uint16_t                        ctx_len;
-	char                            ctx[0];
-};
-
-struct xfrmnl_userpolicy_type {
-	uint8_t                         type;
-	uint16_t                        reserved1;
-	uint16_t                        reserved2;
-};
-
-struct xfrmnl_user_tmpl {
-	struct xfrmnl_id                id;
-	uint16_t                        family;
-	struct nl_addr*                 saddr;
-	uint32_t                        reqid;
-	uint8_t                         mode;
-	uint8_t                         share;
-	uint8_t                         optional;
-	uint32_t                        aalgos;
-	uint32_t                        ealgos;
-	uint32_t                        calgos;
-	struct nl_list_head             utmpl_list;
-};
-
-struct xfrmnl_sp {
-	NLHDR_COMMON
-
-	struct xfrmnl_sel*              sel;
-	struct xfrmnl_ltime_cfg*        lft;
-	struct xfrmnl_lifetime_cur      curlft;
-	uint32_t                        priority;
-	uint32_t                        index;
-	uint8_t                         dir;
-	uint8_t                         action;
-	uint8_t                         flags;
-	uint8_t                         share;
-	struct xfrmnl_user_sec_ctx*     sec_ctx;
-	struct xfrmnl_userpolicy_type   uptype;
-	uint32_t                        nr_user_tmpl;
-	struct nl_list_head             usertmpl_list;
-	struct xfrmnl_mark              mark;
-};
-
-struct rtnl_vlan
-{
-	struct tc_vlan v_parm;
-	uint16_t       v_vid;
-	uint16_t       v_proto;
-	uint8_t        v_prio;
-	uint32_t       v_flags;
-};
-
-struct rtnl_mdb {
-	NLHDR_COMMON
-	uint32_t ifindex;
-
-	struct nl_list_head mdb_entry_list;
-};
-
-struct rtnl_mdb_entry {
-	struct nl_list_head mdb_list;
-	struct nl_addr *addr;
-	uint32_t ifindex;
-	uint16_t vid;
-	uint16_t proto;
-	uint8_t state;
-};
-#endif
diff --git a/include/netlink-private/utils.h b/include/netlink-private/utils.h
deleted file mode 100644
index 93a04c9..0000000
--- a/include/netlink-private/utils.h
+++ /dev/null
@@ -1,393 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-only */
-/*
- * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_UTILS_PRIV_H_
-#define NETLINK_UTILS_PRIV_H_
-
-#include <byteswap.h>
-#include <assert.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <stdbool.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define ntohll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#define ntohll(x) bswap_64((x))
-#endif
-#define htonll(x) ntohll(x)
-
-/*****************************************************************************/
-
-#define _NL_STRINGIFY_ARG(contents)       #contents
-#define _NL_STRINGIFY(macro_or_string)    _NL_STRINGIFY_ARG (macro_or_string)
-
-/*****************************************************************************/
-
-#if defined (__GNUC__)
-#define _NL_PRAGMA_WARNING_DO(warning)       _NL_STRINGIFY(GCC diagnostic ignored warning)
-#elif defined (__clang__)
-#define _NL_PRAGMA_WARNING_DO(warning)       _NL_STRINGIFY(clang diagnostic ignored warning)
-#endif
-
-/* you can only suppress a specific warning that the compiler
- * understands. Otherwise you will get another compiler warning
- * about invalid pragma option.
- * It's not that bad however, because gcc and clang often have the
- * same name for the same warning. */
-
-#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-#define _NL_PRAGMA_WARNING_DISABLE(warning) \
-        _Pragma("GCC diagnostic push") \
-        _Pragma(_NL_PRAGMA_WARNING_DO("-Wpragmas")) \
-        _Pragma(_NL_PRAGMA_WARNING_DO(warning))
-#elif defined (__clang__)
-#define _NL_PRAGMA_WARNING_DISABLE(warning) \
-        _Pragma("clang diagnostic push") \
-        _Pragma(_NL_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \
-        _Pragma(_NL_PRAGMA_WARNING_DO(warning))
-#else
-#define _NL_PRAGMA_WARNING_DISABLE(warning)
-#endif
-
-#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
-#define _NL_PRAGMA_WARNING_REENABLE \
-    _Pragma("GCC diagnostic pop")
-#elif defined (__clang__)
-#define _NL_PRAGMA_WARNING_REENABLE \
-    _Pragma("clang diagnostic pop")
-#else
-#define _NL_PRAGMA_WARNING_REENABLE
-#endif
-
-/*****************************************************************************/
-
-#define _nl_unused                  __attribute__ ((__unused__))
-#define _nl_auto(fcn)               __attribute__ ((__cleanup__(fcn)))
-
-/*****************************************************************************/
-
-#ifdef thread_local
-#define _nl_thread_local thread_local
-/*
- * Don't break on glibc < 2.16 that doesn't define __STDC_NO_THREADS__
- * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53769
- */
-#elif __STDC_VERSION__ >= 201112L &&                                           \
-	!(defined(__STDC_NO_THREADS__) ||                                      \
-	  (defined(__GNU_LIBRARY__) && __GLIBC__ == 2 &&                       \
-	   __GLIBC_MINOR__ < 16))
-#define _nl_thread_local _Thread_local
-#else
-#define _nl_thread_local __thread
-#endif
-
-/*****************************************************************************/
-
-#define _NL_STATIC_ASSERT(cond) ((void) sizeof (char[(cond) ? 1 : -1]))
-
-/*****************************************************************************/
-
-#if defined(NL_MORE_ASSERTS) && NL_MORE_ASSERTS > 0
-#define _nl_assert(cond) assert(cond)
-#else
-#define _nl_assert(cond) do { if (0) { assert(cond); } } while (0)
-#endif
-
-#define _nl_assert_not_reached() assert(0)
-
-/*****************************************************************************/
-
-#define _nl_assert_addr_family_or_unspec(addr_family)                          \
-	do {                                                                   \
-		typeof(addr_family) _addr_family = (addr_family);              \
-                                                                               \
-		_nl_assert(_addr_family == AF_UNSPEC ||                        \
-			   _addr_family == AF_INET ||                          \
-			   _addr_family == AF_INET6);                          \
-	} while (0)
-
-#define _nl_assert_addr_family(addr_family)                                    \
-	do {                                                                   \
-		typeof(addr_family) _addr_family = (addr_family);              \
-                                                                               \
-		_nl_assert(_addr_family == AF_INET ||                          \
-			   _addr_family == AF_INET6);                          \
-	} while (0)
-
-/*****************************************************************************/
-
-#define _NL_SWAP(pa, pb)                                                       \
-	do {                                                                   \
-		typeof(*(pa)) *_pa = (pa);                                     \
-		typeof(*(pb)) *_pb = (pb);                                     \
-		typeof(*_pa) _tmp;                                             \
-                                                                               \
-		_nl_assert(_pa);                                               \
-		_nl_assert(_pb);                                               \
-		_tmp = *_pa;                                                   \
-		*_pa = *_pb;                                                   \
-		*_pb = _tmp;                                                   \
-	} while (0)
-
-/*****************************************************************************/
-
-#define _NL_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-/*****************************************************************************/
-
-extern const char *nl_strerror_l(int err);
-
-/*****************************************************************************/
-
-/* internal macro to calculate the size of a struct @type up to (and including) @field.
- * this will be used for .minlen policy fields, so that we require only a field of up
- * to the given size. */
-#define _nl_offsetofend(type, field) (offsetof (type, field) + sizeof (((type *) NULL)->field))
-
-/*****************************************************************************/
-
-#define _nl_clear_pointer(pp, destroy) \
-	({ \
-		__typeof__ (*(pp)) *_pp = (pp); \
-		__typeof__ (*_pp) _p; \
-		int _changed = 0; \
-		\
-		if (   _pp \
-			&& (_p = *_pp)) { \
-			_nl_unused const void *const _p_check_is_pointer = _p; \
-			\
-			*_pp = NULL; \
-			\
-			(destroy) (_p); \
-			\
-			_changed = 1; \
-		} \
-		_changed; \
-	})
-
-#define _nl_clear_free(pp) _nl_clear_pointer (pp, free)
-
-#define _nl_steal_pointer(pp) \
-	({ \
-		__typeof__ (*(pp)) *const _pp = (pp); \
-		__typeof__ (*_pp) _p = NULL; \
-		\
-		if (   _pp \
-		    && (_p = *_pp)) { \
-			*_pp = NULL; \
-		} \
-		\
-		_p; \
-	})
-
-/*****************************************************************************/
-
-#define _nl_malloc_maybe_a(alloca_maxlen, bytes, to_free) \
-	({ \
-		const size_t _bytes = (bytes); \
-		__typeof__ (to_free) _to_free = (to_free); \
-		__typeof__ (*_to_free) _ptr; \
-		\
-		_NL_STATIC_ASSERT ((alloca_maxlen) <= 500); \
-		_nl_assert (_to_free && !*_to_free); \
-		\
-		if (_bytes <= (alloca_maxlen)) { \
-			_ptr = alloca (_bytes); \
-		} else { \
-			_ptr = malloc (_bytes); \
-			*_to_free = _ptr; \
-		}; \
-		\
-		_ptr; \
-	})
-
-/*****************************************************************************/
-
-static inline bool _nl_streq(const char *a, const char *b)
-{
-	return !strcmp(a, b);
-}
-
-static inline bool _nl_streq0(const char *a, const char *b)
-{
-	return a == b || (a && b && _nl_streq(a, b));
-}
-
-static inline char *
-_nl_strncpy_trunc(char *dst, const char *src, size_t len)
-{
-	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
-	 * behavior of strncpy(). This is just strncpy() with gracefully handling truncation
-	 * (and disabling the "-Wstringop-truncation" warning).
-	 *
-	 * Note that truncation is silently accepted.
-	 */
-
-	_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation");
-	_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-overflow");
-
-	if (len > 0) {
-		_nl_assert(dst);
-		_nl_assert(src);
-
-		strncpy(dst, src, len);
-
-		dst[len - 1] = '\0';
-	}
-
-	_NL_PRAGMA_WARNING_REENABLE;
-	_NL_PRAGMA_WARNING_REENABLE;
-
-	return dst;
-}
-
-static inline char *
-_nl_strncpy_assert(char *dst, const char *src, size_t len)
-{
-	/* we don't use/reimplement strlcpy(), because we want the fill-all-with-NUL
-	 * behavior of strncpy(). This is just strncpy() with assertion against truncation
-	 * (and disabling the "-Wstringop-truncation" warning).
-	 *
-	 * Note that truncation is still a bug and there is an _nl_assert()
-	 * against that.
-	 */
-
-	_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-truncation");
-	_NL_PRAGMA_WARNING_DISABLE ("-Wstringop-overflow");
-
-	if (len > 0) {
-		_nl_assert(dst);
-		_nl_assert(src);
-
-		strncpy(dst, src, len);
-
-		_nl_assert (dst[len - 1] == '\0');
-
-		dst[len - 1] = '\0';
-	}
-
-	_NL_PRAGMA_WARNING_REENABLE;
-	_NL_PRAGMA_WARNING_REENABLE;
-
-	return dst;
-}
-
-#include "nl-auto.h"
-
-#define _NL_RETURN_ON_ERR(cmd) \
-	do { \
-		int _err; \
-		\
-		_err = (cmd); \
-		if (_err < 0) \
-			return _err; \
-	} while (0)
-
-#define _NL_RETURN_E_ON_ERR(e, cmd) \
-	do { \
-		int _err; \
-		\
-		_err = (cmd); \
-		if (_err < 0) { \
-			_NL_STATIC_ASSERT((e) > 0); \
-			return -(e); \
-		} \
-	} while (0)
-
-/* _NL_RETURN_ON_PUT_ERR() shall only be used with a put command (nla_put or nlmsg_append).
- * These commands can either fail with a regular error code (which gets propagated)
- * or with -NLE_NOMEM. However, they don't really try to allocate memory, so we don't
- * want to propagate -NLE_NOMEM. Instead, we coerce such failure to -NLE_MSGSIZE. */
-#define _NL_RETURN_ON_PUT_ERR(put_cmd) \
-	do { \
-		int _err; \
-		\
-		_err = (put_cmd); \
-		if (_err < 0) { \
-			if (_err == -NLE_NOMEM) { \
-				/* nla_put() returns -NLE_NOMEM in case of out of buffer size. We don't
-				 * want to propagate that error and map it to -NLE_MSGSIZE. */ \
-				return -NLE_MSGSIZE; \
-			} \
-			/* any other error can only be due to invalid parameters. Propagate the
-			 * error, however also assert that it cannot be reached. */ \
-			_nl_assert_not_reached (); \
-			return _err; \
-		} else \
-			_nl_assert (_err == 0); \
-	} while (0)
-
-static inline int
-_nl_close(int fd)
-{
-	int r;
-
-	r = close(fd);
-	_nl_assert(r == 0 || fd < 0 || errno != EBADF);
-	return r;
-}
-
-static inline void *
-_nl_memdup(const void *ptr, size_t len)
-{
-	void *p;
-
-	if (len == 0) {
-		/* malloc() leaves it implementation defined whether to return NULL.
-		 * Callers rely on returning NULL if len is zero. */
-		return NULL;
-	}
-
-	p = malloc(len);
-	if (!p)
-		return NULL;
-	memcpy(p, ptr, len);
-	return p;
-}
-
-#define _nl_memdup_ptr(ptr) ((__typeof__(ptr)) _nl_memdup((ptr), sizeof(*(ptr))))
-
-/*****************************************************************************/
-
-typedef union {
-	in_addr_t addr4;
-	struct in_addr a4;
-	struct in6_addr a6;
-} _NLIPAddr;
-
-static inline char *_nl_inet_ntop(int addr_family, const void *addr,
-				  char buf[static INET_ADDRSTRLEN])
-{
-	char *r;
-
-	_nl_assert_addr_family(addr_family);
-	_nl_assert(addr);
-
-	/* inet_ntop() is documented to fail, but if we pass a known address family
-	 * and a suitably large buffer, it cannot. Assert for that. */
-
-	r = (char *)inet_ntop(addr_family, addr, buf,
-			      (addr_family == AF_INET) ? INET_ADDRSTRLEN :
-							       INET6_ADDRSTRLEN);
-	_nl_assert(r == buf);
-	_nl_assert(strlen(r) < ((addr_family == AF_INET) ? INET_ADDRSTRLEN :
-								 INET6_ADDRSTRLEN));
-
-	return r;
-}
-
-static inline char *_nl_inet_ntop_dup(int addr_family, const void *addr)
-{
-	return (char *)_nl_inet_ntop(addr_family, addr,
-				     malloc((addr_family == AF_INET) ?
-						    INET_ADDRSTRLEN :
-							  INET6_ADDRSTRLEN));
-}
-
-#endif
diff --git a/include/netlink/cli/nh.h b/include/netlink/cli/nh.h
new file mode 100644
index 0000000..ee08c8e
--- /dev/null
+++ b/include/netlink/cli/nh.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+#ifndef __NETLINK_CLI_NH_H_
+#define __NETLINK_CLI_NH_H_
+
+#include <netlink/route/nh.h>
+#include <netlink/cli/utils.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct rtnl_nh *nl_cli_nh_alloc(void);
+extern struct nl_cache *nl_cli_nh_alloc_cache_family(struct nl_sock *, int);
+extern struct nl_cache *nl_cli_nh_alloc_cache_family_flags(struct nl_sock *,
+							   int, unsigned int);
+extern struct nl_cache *nl_cli_nh_alloc_cache(struct nl_sock *);
+extern struct nl_cache *nl_cli_nh_alloc_cache_flags(struct nl_sock *,
+						    unsigned int);
+
+extern void nl_cli_nh_parse_family(struct rtnl_nh *, char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/hash.h b/include/netlink/hash.h
index 0bda74e..5df4099 100644
--- a/include/netlink/hash.h
+++ b/include/netlink/hash.h
@@ -5,6 +5,7 @@
  */
 #ifndef CCAN_HASH_H
 #define CCAN_HASH_H
+
 #include <stdint.h>
 #include <stdlib.h>
 #include <endian.h>
@@ -14,6 +15,10 @@
  * http://burtleburtle.net/bob/c/lookup3.c
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef __LITTLE_ENDIAN
 #   define HAVE_LITTLE_ENDIAN 1
 #elif __BIG_ENDIAN
@@ -66,4 +71,8 @@
 /* Our underlying operations. */
 uint32_t nl_hash_any(const void *key, size_t length, uint32_t base);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* HASH_H */
diff --git a/include/netlink/list.h b/include/netlink/list.h
index 7ab1438..7f300df 100644
--- a/include/netlink/list.h
+++ b/include/netlink/list.h
@@ -8,6 +8,10 @@
 
 #include <stddef.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct nl_list_head
 {
 	struct nl_list_head *	next;
@@ -86,4 +90,8 @@
 #define nl_init_list_head(head) \
 	do { (head)->next = (head); (head)->prev = (head); } while (0)
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/netlink/netlink-compat.h b/include/netlink/netlink-compat.h
index ed71ed4..76b4595 100644
--- a/include/netlink/netlink-compat.h
+++ b/include/netlink/netlink-compat.h
@@ -6,6 +6,10 @@
 #ifndef NETLINK_COMPAT_H_
 #define NETLINK_COMPAT_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #if !defined _LINUX_SOCKET_H && !defined _BITS_SOCKADDR_H
 typedef unsigned short  sa_family_t;
 #endif
@@ -45,4 +49,8 @@
 #define AF_MPLS		28
 #endif
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/netlink/route/link/bonding.h b/include/netlink/route/link/bonding.h
index 09d495e..e12d8a5 100644
--- a/include/netlink/route/link/bonding.h
+++ b/include/netlink/route/link/bonding.h
@@ -25,6 +25,12 @@
 extern int	rtnl_link_bond_release_ifindex(struct nl_sock *, int);
 extern int	rtnl_link_bond_release(struct nl_sock *, struct rtnl_link *);
 
+extern void	rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode);
+extern void	rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave);
+extern void	rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type);
+extern void	rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon);
+extern void	rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h
new file mode 100644
index 0000000..09689b3
--- /dev/null
+++ b/include/netlink/route/link/bridge_info.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 MaxLinear, Inc.
+ */
+
+#ifndef NETLINK_LINK_BRIDGE_INFO_H_
+#define NETLINK_LINK_BRIDGE_INFO_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link,
+						uint8_t vlan_filtering);
+extern int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link,
+					       uint8_t *vlan_filtering);
+
+extern void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link,
+					       uint16_t vlan_protocol);
+extern int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link,
+					      uint16_t *vlan_protocol);
+
+extern void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link,
+						    uint8_t vlan_stats_enabled);
+extern int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link,
+						   uint8_t *vlan_stats_enabled);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/link/can.h b/include/netlink/route/link/can.h
index 7df50e3..1c23660 100644
--- a/include/netlink/route/link/can.h
+++ b/include/netlink/route/link/can.h
@@ -60,6 +60,9 @@
 extern int rtnl_link_can_set_data_bittiming(struct rtnl_link *,
                                             const struct can_bittiming *);
 
+extern int rtnl_link_can_get_device_stats(struct rtnl_link *,
+				          struct can_device_stats *);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/netlink/route/link/inet.h b/include/netlink/route/link/inet.h
index 2e93cc5..b1318d1 100644
--- a/include/netlink/route/link/inet.h
+++ b/include/netlink/route/link/inet.h
@@ -7,6 +7,7 @@
 #define NETLINK_LINK_INET_H_
 
 #include <netlink/netlink.h>
+#include <netlink/route/link.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/netlink/route/link/inet6.h b/include/netlink/route/link/inet6.h
index cf257ca..8939427 100644
--- a/include/netlink/route/link/inet6.h
+++ b/include/netlink/route/link/inet6.h
@@ -7,6 +7,7 @@
 #define NETLINK_LINK_INET6_H_
 
 #include <netlink/netlink.h>
+#include <netlink/route/link.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -36,6 +37,10 @@
 extern int		rtnl_link_inet6_set_flags(struct rtnl_link *,
 							  uint32_t);
 
+extern int		rtnl_link_inet6_get_conf(struct rtnl_link *,
+						 unsigned int,
+						 uint32_t *);
+
 /* Link Flags Translations */
 extern char *	rtnl_link_inet6_flags2str(int, char *, size_t);
 extern int		rtnl_link_inet6_str2flags(const char *);
diff --git a/include/netlink/route/neighbour.h b/include/netlink/route/neighbour.h
index 3760414..657db53 100644
--- a/include/netlink/route/neighbour.h
+++ b/include/netlink/route/neighbour.h
@@ -79,6 +79,9 @@
 extern void			rtnl_neigh_set_master(struct rtnl_neigh *, int);
 extern int			rtnl_neigh_get_master(struct rtnl_neigh *);
 
+extern void			rtnl_neigh_set_nhid(struct rtnl_neigh *, uint32_t);
+extern int			rtnl_neigh_get_nhid(struct rtnl_neigh *, uint32_t *);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/netlink/route/netconf.h b/include/netlink/route/netconf.h
index 7006c6e..a6b1f89 100644
--- a/include/netlink/route/netconf.h
+++ b/include/netlink/route/netconf.h
@@ -10,6 +10,8 @@
 extern "C" {
 #endif
 
+struct nl_sock;
+struct nl_cache;
 struct rtnl_netconf;
 
 int rtnl_netconf_alloc_cache(struct nl_sock *sk, struct nl_cache **result);
diff --git a/include/netlink/route/nh.h b/include/netlink/route/nh.h
new file mode 100644
index 0000000..3edbad7
--- /dev/null
+++ b/include/netlink/route/nh.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+#ifndef NETLINK_ROUTE_NEXTHOP2_H_
+#define NETLINK_ROUTE_NEXTHOP2_H_
+
+#include <netlink/netlink.h>
+#include <netlink/addr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rtnl_nh;
+
+typedef struct nl_nh_group_info {
+	uint32_t nh_id; /*!< nexthop id */
+	uint8_t weight; /*!< weight in nexthop group */
+} nl_nh_group_info_t;
+
+typedef struct nl_nh_group {
+	int ce_refcnt;
+	unsigned size;
+	nl_nh_group_info_t *entries;
+} nl_nh_group_t;
+
+extern int rtnl_nh_alloc_cache(struct nl_sock *sk, int family,
+			       struct nl_cache **result);
+extern struct rtnl_nh *rtnl_nh_alloc(void);
+extern void rtnl_nh_put(struct rtnl_nh *);
+
+extern struct rtnl_nh *rtnl_nh_get(struct nl_cache *cache, int nhid);
+
+extern int rtnl_nh_set_gateway(struct rtnl_nh *, struct nl_addr *);
+extern struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *);
+
+extern int rtnl_nh_set_fdb(struct rtnl_nh *, int value);
+extern int rtnl_nh_get_fdb(struct rtnl_nh *);
+
+extern int rtnl_nh_get_group_entry(struct rtnl_nh *, int n);
+extern int rtnl_nh_get_group_size(struct rtnl_nh *);
+
+extern int rtnl_nh_get_id(struct rtnl_nh *);
+extern int rtnl_nh_get_oif(struct rtnl_nh *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/red.h b/include/netlink/route/qdisc/red.h
index 51d38ed..f74ad80 100644
--- a/include/netlink/route/qdisc/red.h
+++ b/include/netlink/route/qdisc/red.h
@@ -7,8 +7,17 @@
 #define NETLINK_RED_H_
 
 #include <netlink/netlink.h>
+#include <netlink/route/qdisc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 extern  void rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit);
 extern int rtnl_red_get_limit(struct rtnl_qdisc *qdisc);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/netlink/types.h b/include/netlink/types.h
index 1e3a9a9..a3a28fd 100644
--- a/include/netlink/types.h
+++ b/include/netlink/types.h
@@ -8,6 +8,10 @@
 
 #include <stdio.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * @ingroup utils
  * Enumeration of dumping variations (dp_type)
@@ -101,4 +105,8 @@
 	unsigned int		dp_line;
 };
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/netlink/utils.h b/include/netlink/utils.h
index c62df82..11a6b93 100644
--- a/include/netlink/utils.h
+++ b/include/netlink/utils.h
@@ -319,6 +319,18 @@
 	NL_CAPABILITY_VERSION_3_7_0 = 33,
 #define NL_CAPABILITY_VERSION_3_7_0 NL_CAPABILITY_VERSION_3_7_0
 
+	/**
+	 * The library version is libnl3 3.8.0 or newer. This capability should never be backported.
+	 */
+	NL_CAPABILITY_VERSION_3_8_0 = 34,
+#define NL_CAPABILITY_VERSION_3_8_0 NL_CAPABILITY_VERSION_3_8_0
+
+	/**
+	 * The library version is libnl3 3.9.0 or newer. This capability should never be backported.
+	 */
+	NL_CAPABILITY_VERSION_3_9_0 = 35,
+#define NL_CAPABILITY_VERSION_3_9_0 NL_CAPABILITY_VERSION_3_9_0
+
 	__NL_CAPABILITY_MAX,
 	NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1),
 #define NL_CAPABILITY_MAX NL_CAPABILITY_MAX
diff --git a/include/netlink/version.h.in b/include/netlink/version.h.in
index 7fccc95..3c43355 100644
--- a/include/netlink/version.h.in
+++ b/include/netlink/version.h.in
@@ -8,6 +8,10 @@
 
 /* Compile Time Versioning Information */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define LIBNL_STRING "@PACKAGE_STRING@"
 #define LIBNL_VERSION "@PACKAGE_VERSION@"
 
@@ -28,4 +32,8 @@
 extern const int        nl_ver_min;
 extern const int        nl_ver_mic;
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/nl-aux-core/README.md b/include/nl-aux-core/README.md
new file mode 100644
index 0000000..a9d6b81
--- /dev/null
+++ b/include/nl-aux-core/README.md
@@ -0,0 +1,15 @@
+include/nl-aux-core
+====================
+
+This contains private/internal helpers that depend on the public API of libnl-3 (core).
+
+Itself, it must only rely on C, include/base/ and public headers of libnl-3 (core).
+
+They can be used by all internal code that uses the public API of libnl-3.
+
+It can also be used by lib/ itself (that is, the implementation of
+libnl-core-3).
+
+It must not be used in public headers, it's internal only.
+
+Currently this is header-only, it does not require any additional linking.
diff --git a/include/nl-aux-core/nl-core.h b/include/nl-aux-core/nl-core.h
new file mode 100644
index 0000000..5b34bcb
--- /dev/null
+++ b/include/nl-aux-core/nl-core.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#ifndef NETLINK_NL_AUTO_H_
+#define NETLINK_NL_AUTO_H_
+
+#include "base/nl-base-utils.h"
+
+#ifdef NL_DEBUG
+#define NL_DBG(LVL, FMT, ARG...)                                           \
+	do {                                                               \
+		if (LVL <= nl_debug) {                                     \
+			int _errsv = errno;                                \
+			fprintf(stderr, "DBG<" #LVL ">%20s:%-4u %s: " FMT, \
+				__FILE__, __LINE__, __func__, ##ARG);      \
+			errno = _errsv;                                    \
+		}                                                          \
+	} while (0)
+#else /* NL_DEBUG */
+#define NL_DBG(LVL, FMT, ARG...) \
+	do {                     \
+	} while (0)
+#endif /* NL_DEBUG */
+
+struct nl_addr;
+void nl_addr_put(struct nl_addr *);
+#define _nl_auto_nl_addr _nl_auto(_nl_auto_nl_addr_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_addr *, _nl_auto_nl_addr_fcn, nl_addr_put);
+
+struct nl_data;
+void nl_data_free(struct nl_data *data);
+#define _nl_auto_nl_data _nl_auto(_nl_auto_nl_data_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_data *, _nl_auto_nl_data_fcn,
+			   nl_data_free);
+
+struct nl_msg;
+void nlmsg_free(struct nl_msg *);
+#define _nl_auto_nl_msg _nl_auto(_nl_auto_nl_msg_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_msg *, _nl_auto_nl_msg_fcn, nlmsg_free);
+
+struct nl_cache;
+void nl_cache_put(struct nl_cache *);
+#define _nl_auto_nl_cache _nl_auto(_nl_auto_nl_cache_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_cache *, _nl_auto_nl_cache_fcn,
+			   nl_cache_put);
+
+struct nl_sock;
+void nl_socket_free(struct nl_sock *);
+#define _nl_auto_nl_socket _nl_auto(_nl_auto_nl_socket_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct nl_sock *, _nl_auto_nl_socket_fcn,
+			   nl_socket_free);
+
+struct nl_addr *nl_addr_build(int, const void *, size_t);
+
+static inline struct nl_addr *_nl_addr_build(int family, const void *buf)
+{
+	return nl_addr_build(family, buf, _nl_addr_family_to_size(family));
+}
+
+#endif /* NETLINK_NL_AUTO_H_ */
diff --git a/include/nl-aux-route/README.md b/include/nl-aux-route/README.md
new file mode 100644
index 0000000..3c4d4d0
--- /dev/null
+++ b/include/nl-aux-route/README.md
@@ -0,0 +1,18 @@
+include/nl-aux-route
+====================
+
+This contains private/internal helpers that depend on the public libnl-3 (core)
+and libnl-route-3.
+
+Itself, it must only rely on C, include/base/ and public headers of libnl-3 (core)
+and libnl-route-3.
+
+They can be used by all internal code that uses the public API of both libnl-3 (core)
+and libnl-route-3.
+
+It can also be used by lib/route itself (that is, the implementation of
+libnl-route-3).
+
+It must not be used in public headers, it's internal only.
+
+Currently this is header-only, it does not require any additional linking.
diff --git a/include/nl-aux-route/nl-route.h b/include/nl-aux-route/nl-route.h
new file mode 100644
index 0000000..9c85337
--- /dev/null
+++ b/include/nl-aux-route/nl-route.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#ifndef __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__
+#define __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__
+
+#include "base/nl-base-utils.h"
+
+#include <netlink/route/action.h>
+
+struct rtnl_link;
+void rtnl_link_put(struct rtnl_link *);
+#define _nl_auto_rtnl_link _nl_auto(_nl_auto_rtnl_link_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link *, _nl_auto_rtnl_link_fcn,
+			   rtnl_link_put);
+
+struct rtnl_route;
+void rtnl_route_put(struct rtnl_route *);
+#define _nl_auto_rtnl_route _nl_auto(_nl_auto_rtnl_route_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_route *, _nl_auto_rtnl_route_fcn,
+			   rtnl_route_put);
+
+struct rtnl_mdb;
+void rtnl_mdb_put(struct rtnl_mdb *);
+#define _nl_auto_rtnl_mdb _nl_auto(_nl_auto_rtnl_mdb_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_mdb *, _nl_auto_rtnl_mdb_fcn,
+			   rtnl_mdb_put);
+
+struct rtnl_nexthop;
+void rtnl_route_nh_free(struct rtnl_nexthop *);
+#define _nl_auto_rtnl_nexthop _nl_auto(_nl_auto_rtnl_nexthop_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_nexthop *, _nl_auto_rtnl_nexthop_fcn,
+			   rtnl_route_nh_free);
+
+struct rtnl_nh;
+void rtnl_nh_put(struct rtnl_nh *);
+#define _nl_auto_rtnl_nh _nl_auto(_nl_auto_rtnl_nh_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_nh *, _nl_auto_rtnl_nh_fcn, rtnl_nh_put);
+
+struct rtnl_link_af_ops;
+void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
+#define _nl_auto_rtnl_link_af_ops _nl_auto(_nl_auto_rtnl_link_af_ops_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_link_af_ops *,
+			   _nl_auto_rtnl_link_af_ops_fcn, rtnl_link_af_ops_put);
+
+#define _nl_auto_rtnl_act _nl_auto(_nl_auto_rtnl_act_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_act *, _nl_auto_rtnl_act_fcn,
+			   rtnl_act_put);
+
+#define _nl_auto_rtnl_act_all _nl_auto(_nl_auto_rtnl_act_fcn_all)
+_NL_AUTO_DEFINE_FCN_INDIRECT0(struct rtnl_act *, _nl_auto_rtnl_act_fcn_all,
+			      rtnl_act_put_all);
+
+struct rtnl_ematch_tree;
+void rtnl_ematch_tree_free(struct rtnl_ematch_tree *);
+#define _nl_auto_rtnl_ematch_tree _nl_auto(_nl_auto_rtnl_ematch_tree_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_ematch_tree *,
+			   _nl_auto_rtnl_ematch_tree_fcn,
+			   rtnl_ematch_tree_free);
+
+struct rtnl_cls;
+void rtnl_cls_put(struct rtnl_cls *);
+#define _nl_auto_rtnl_cls _nl_auto(_nl_auto_rtnl_cls_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct rtnl_cls *, _nl_auto_rtnl_cls_fcn,
+			   rtnl_cls_put);
+
+/*****************************************************************************/
+
+static inline int _rtnl_act_append_get(struct rtnl_act **head,
+				       struct rtnl_act *new)
+{
+	int r;
+
+	r = rtnl_act_append(head, new);
+	if (r >= 0)
+		rtnl_act_get(new);
+	return r;
+}
+
+static inline int _rtnl_act_append_take(struct rtnl_act **head,
+					struct rtnl_act *new)
+{
+	int r;
+
+	r = rtnl_act_append(head, new);
+	if (r < 0)
+		rtnl_act_put(new);
+	return r;
+}
+
+#endif /* __NETLINK_NL_AUX_ROUTE_NL_ROUTE_H__ */
diff --git a/include/nl-aux-xfrm/README.md b/include/nl-aux-xfrm/README.md
new file mode 100644
index 0000000..9a4b6e2
--- /dev/null
+++ b/include/nl-aux-xfrm/README.md
@@ -0,0 +1,18 @@
+include/nl-aux-xfrm
+===================
+
+This contains private/internal helpers that depend on the public libnl-3 (core)
+and libnl-xfrm-3.
+
+Itself, it must only rely on C, include/base/ and public headers of libnl-3 (core)
+and libnl-xfrm-3.
+
+They can be used by all internal code that uses the public API of both libnl-3 (core)
+and libnl-xfrm-3.
+
+It can also be used by lib/xfrm itself (that is, the implementation of
+libnl-xfrm-3).
+
+It must not be used in public headers, it's internal only.
+
+Currently this is header-only, it does not require any additional linking.
diff --git a/include/nl-aux-xfrm/nl-xfrm.h b/include/nl-aux-xfrm/nl-xfrm.h
new file mode 100644
index 0000000..9c5c46a
--- /dev/null
+++ b/include/nl-aux-xfrm/nl-xfrm.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#ifndef __NETLINK_NL_AUX_XFRM_NL_XFRM_H__
+#define __NETLINK_NL_AUX_XFRM_NL_XFRM_H__
+
+#include "base/nl-base-utils.h"
+
+struct xfrmnl_sp;
+void xfrmnl_sp_put(struct xfrmnl_sp *sp);
+#define _nl_auto_xfrmnl_sp _nl_auto(_nl_auto_xfrmnl_sp_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_sp *, _nl_auto_xfrmnl_sp_fcn,
+			   xfrmnl_sp_put);
+
+struct xfrmnl_sa;
+void xfrmnl_sa_put(struct xfrmnl_sa *sa);
+#define _nl_auto_xfrmnl_sa _nl_auto(_nl_auto_xfrmnl_sa_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_sa *, _nl_auto_xfrmnl_sa_fcn,
+			   xfrmnl_sa_put);
+
+struct xfrmnl_ae;
+void xfrmnl_ae_put(struct xfrmnl_ae *ae);
+#define _nl_auto_xfrmnl_ae _nl_auto(_nl_auto_xfrmnl_ae_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_ae *, _nl_auto_xfrmnl_ae_fcn,
+			   xfrmnl_ae_put);
+
+struct xfrmnl_user_tmpl;
+void xfrmnl_user_tmpl_free(struct xfrmnl_user_tmpl *utmpl);
+#define _nl_auto_xfrmnl_user_tmpl _nl_auto(_nl_auto_xfrmnl_user_tmpl_fcn)
+_NL_AUTO_DEFINE_FCN_TYPED0(struct xfrmnl_user_tmpl *,
+			   _nl_auto_xfrmnl_user_tmpl_fcn,
+			   xfrmnl_user_tmpl_free);
+
+#endif /* __NETLINK_NL_AUX_XFRM_NL_XFRM_H__ */
diff --git a/include/nl-default.h b/include/nl-default.h
new file mode 100644
index 0000000..83dbcb4
--- /dev/null
+++ b/include/nl-default.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#ifndef __NL_DEFAULT_H__
+#define __NL_DEFAULT_H__
+
+#include "config.h"
+
+#include "base/nl-base-utils.h"
+
+#endif /* __NL_DEFAULT_H__ */
diff --git a/include/nl-priv-dynamic-core/README.md b/include/nl-priv-dynamic-core/README.md
new file mode 100644
index 0000000..9b2aef4
--- /dev/null
+++ b/include/nl-priv-dynamic-core/README.md
@@ -0,0 +1,8 @@
+include/nl-priv-dynamic-core
+============================
+
+Contains internal API on top of core (libnl-3). It is
+implemented by core and usable to all users that link
+against libnl-3.
+
+Note that the ABI, while being internal, should stay stable.
diff --git a/include/netlink-private/cache-api.h b/include/nl-priv-dynamic-core/cache-api.h
similarity index 93%
rename from include/netlink-private/cache-api.h
rename to include/nl-priv-dynamic-core/cache-api.h
index 38662b7..2ddc30c 100644
--- a/include/netlink-private/cache-api.h
+++ b/include/nl-priv-dynamic-core/cache-api.h
@@ -9,10 +9,6 @@
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * @ingroup cache
  * @defgroup cache_api Cache Implementation
@@ -258,8 +254,27 @@
 
 /** @} */
 
-#ifdef __cplusplus
+struct nl_cache {
+	struct nl_list_head c_items;
+	int c_nitems;
+	int c_iarg1;
+	int c_iarg2;
+	int c_refcnt;
+	unsigned int c_flags;
+	struct nl_hash_table *hashtable;
+	struct nl_cache_ops *c_ops;
+};
+
+static inline const char *nl_cache_name(struct nl_cache *cache)
+{
+	return cache->c_ops ? cache->c_ops->co_name : "unknown";
 }
-#endif
+
+struct nl_cache_assoc {
+	struct nl_cache *ca_cache;
+	change_func_t ca_change;
+	change_func_v2_t ca_change_v2;
+	void *ca_change_data;
+};
 
 #endif
diff --git a/include/nl-priv-dynamic-core/nl-core.h b/include/nl-priv-dynamic-core/nl-core.h
new file mode 100644
index 0000000..33ebfa1
--- /dev/null
+++ b/include/nl-priv-dynamic-core/nl-core.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef __NL_SHARED_CORE_NL_CORE_H__
+#define __NL_SHARED_CORE_NL_CORE_H__
+
+#define NL_SOCK_PASSCRED (1 << 1)
+#define NL_OWN_PORT (1 << 2)
+#define NL_MSG_PEEK (1 << 3)
+#define NL_MSG_PEEK_EXPLICIT (1 << 4)
+#define NL_NO_AUTO_ACK (1 << 5)
+
+struct nl_sock {
+	struct sockaddr_nl s_local;
+	struct sockaddr_nl s_peer;
+	int s_fd;
+	int s_proto;
+	unsigned int s_seq_next;
+	unsigned int s_seq_expect;
+	int s_flags;
+	struct nl_cb *s_cb;
+	size_t s_bufsize;
+};
+
+static inline int wait_for_ack(struct nl_sock *sk)
+{
+	if (sk->s_flags & NL_NO_AUTO_ACK)
+		return 0;
+	else
+		return nl_wait_for_ack(sk);
+}
+
+#define LOOSE_COMPARISON 1
+#define ID_COMPARISON 2
+
+#define NL_OBJ_MARK 1
+
+struct nl_data {
+	size_t d_size;
+	void *d_data;
+};
+
+struct nl_addr {
+	int a_family;
+	unsigned int a_maxsize;
+	unsigned int a_len;
+	int a_prefixlen;
+	int a_refcnt;
+	char a_addr[0];
+};
+
+#define NL_MSG_CRED_PRESENT 1
+
+struct nl_msg {
+	int nm_protocol;
+	int nm_flags;
+	struct sockaddr_nl nm_src;
+	struct sockaddr_nl nm_dst;
+	struct ucred nm_creds;
+	struct nlmsghdr *nm_nlh;
+	size_t nm_size;
+	int nm_refcnt;
+};
+
+/*****************************************************************************/
+
+int nl_getprotobyname(const char *name);
+
+bool nl_getprotobynumber(int proto, char *out_name, size_t name_len);
+
+extern const char *nl_strerror_l(int err);
+
+extern int __nl_read_num_str_file(const char *path,
+				  int (*cb)(long, const char *));
+
+extern int __trans_list_add(int, const char *, struct nl_list_head *);
+extern void __trans_list_clear(struct nl_list_head *);
+
+extern char *__type2str(int, char *, size_t, const struct trans_tbl *, size_t);
+extern int __str2type(const char *, const struct trans_tbl *, size_t);
+
+extern char *__list_type2str(int, char *, size_t, struct nl_list_head *);
+extern int __list_str2type(const char *, struct nl_list_head *);
+
+extern char *__flags2str(int, char *, size_t, const struct trans_tbl *, size_t);
+extern int __str2flags(const char *, const struct trans_tbl *, size_t);
+
+#endif /* __NL_SHARED_CORE_NL_CORE_H__ */
diff --git a/include/netlink-private/object-api.h b/include/nl-priv-dynamic-core/object-api.h
similarity index 97%
rename from include/netlink-private/object-api.h
rename to include/nl-priv-dynamic-core/object-api.h
index a2838fd..a20a9d5 100644
--- a/include/netlink-private/object-api.h
+++ b/include/nl-priv-dynamic-core/object-api.h
@@ -10,10 +10,6 @@
 #include <netlink/utils.h>
 #include <netlink/object.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * @ingroup object
  * @defgroup object_api Object API
@@ -149,12 +145,12 @@
  * 	// We help ourselves in defining our own DIFF macro which will
  *	// call ATTR_DIFF() on both objects which will make sure to only
  *	// compare the attributes if required.
- * 	#define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MY_ATTR_##ATTR, a, b, EXPR)
+ * 	#define MY_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
  *
  * 	// Call our own diff macro for each attribute to build a bitmask
  *	// representing the attributes which mismatch.
- * 	diff |= MY_DIFF(FOO, a->foo != b->foo)
- * 	diff |= MY_DIFF(BAR, strcmp(a->bar, b->bar))
+ * 	diff |= MY_DIFF(MY_ATTR_FOO, a->foo != b->foo)
+ * 	diff |= MY_DIFF(MY_ATTR_BAR, strcmp(a->bar, b->bar))
  *
  * 	return diff;
  * }
@@ -365,8 +361,4 @@
 
 /** @} */
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/include/nl-priv-dynamic-route/README.md b/include/nl-priv-dynamic-route/README.md
new file mode 100644
index 0000000..b27e14a
--- /dev/null
+++ b/include/nl-priv-dynamic-route/README.md
@@ -0,0 +1,11 @@
+include/nl-priv-dynamic-route
+=============================
+
+This exposes private API from libnl-route-3. The only purpose is for tests to
+be able to access the internals.  This is usable to lib/route itself, and tests
+that either statically or dynamically link with libnl-route-3.
+
+The difference between nl-priv-static-route and nl-priv-dynamic-route, is that
+the former uses internal ABI, so it is only usable when the test statically
+links with lib/route.  On the other hand, nl-priv-dynamic-route also works with
+only the public API (that is, dynamically linking with libnl-route-3).
diff --git a/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h b/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h
new file mode 100644
index 0000000..c8168a3
--- /dev/null
+++ b/include/nl-priv-dynamic-route/nl-priv-dynamic-route.h
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __NL_PRIVATE_TYPES_NL_ROUTE_H__
+#define __NL_PRIVATE_TYPES_NL_ROUTE_H__
+
+struct rtnl_ematch {
+	uint16_t e_id;
+	uint16_t e_kind;
+	uint16_t e_flags;
+	uint16_t e_index;
+	size_t e_datalen;
+
+	struct nl_list_head e_childs;
+	struct nl_list_head e_list;
+	struct rtnl_ematch_ops *e_ops;
+
+	void *e_data;
+};
+
+struct rtnl_ematch_tree {
+	uint16_t et_progid;
+	struct nl_list_head et_list;
+};
+
+/*****************************************************************************/
+
+/**
+ * Traffic control object operations
+ * @ingroup tc
+ *
+ * This structure holds function pointers and settings implementing
+ * the features of each traffic control object implementation.
+ */
+struct rtnl_tc_ops {
+	/**
+	 * Name of traffic control module
+	 */
+	char *to_kind;
+
+	/**
+	 * Type of traffic control object
+	 */
+	enum rtnl_tc_type to_type;
+
+	/**
+	 * Size of private data
+	 */
+	size_t to_size;
+
+	/**
+	 * Dump callbacks
+	 */
+	void (*to_dump[NL_DUMP_MAX + 1])(struct rtnl_tc *, void *,
+					 struct nl_dump_params *);
+	/**
+	 * Used to fill the contents of TCA_OPTIONS
+	 */
+	int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *);
+
+	/**
+	 * Uesd to to fill tc related messages, unlike with to_msg_fill,
+	 * the contents is not encapsulated with a TCA_OPTIONS nested
+	 * attribute.
+	 */
+	int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *);
+
+	/**
+	 * TCA_OPTIONS message parser
+	 */
+	int (*to_msg_parser)(struct rtnl_tc *, void *);
+
+	/**
+	 * Called before a tc object is destroyed
+	 */
+	void (*to_free_data)(struct rtnl_tc *, void *);
+
+	/**
+	 * Called whenever a classifier object needs to be cloned
+	 */
+	int (*to_clone)(void *, void *);
+
+	/**
+	 * Internal, don't touch
+	 */
+	struct nl_list_head to_list;
+};
+
+extern struct rtnl_tc_ops *rtnl_tc_lookup_ops(enum rtnl_tc_type, const char *);
+
+struct rtnl_tc_ops *rtnl_tc_get_ops(struct rtnl_tc *);
+
+#endif /* __NL_PRIVATE_TYPES_NL_ROUTE_H__ */
diff --git a/include/nl-priv-static-route/README.md b/include/nl-priv-static-route/README.md
new file mode 100644
index 0000000..fd2fa8e
--- /dev/null
+++ b/include/nl-priv-static-route/README.md
@@ -0,0 +1,11 @@
+include/nl-priv-static-route
+============================
+
+This exposes private API from libnl-route-3. The only purpose is for tests to
+be able to access the internals.  This is usable to lib/route itself, and to
+tests that statically link with libnl-route-3.
+
+The difference between nl-priv-static-route and nl-priv-dynamic-route, is that
+the former uses internal ABI, so it is only usable when the test statically
+links with lib/route.  On the other hand, nl-priv-dynamic-route also works with
+only the public API (that is, dynamically linking with libnl-route-3).
diff --git a/include/netlink-private/route/utils.h b/include/nl-priv-static-route/nl-priv-static-route.h
similarity index 100%
rename from include/netlink-private/route/utils.h
rename to include/nl-priv-static-route/nl-priv-static-route.h
diff --git a/lib/addr.c b/lib/addr.c
index fae1293..89a3b38 100644
--- a/lib/addr.c
+++ b/lib/addr.c
@@ -21,12 +21,17 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/socket.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/addr.h>
-#include <netlink-private/route/mpls.h>
-#include <linux/socket.h>
+#include <netlink/attr.h>
+
+#include "mpls.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /* All this DECnet stuff is stolen from iproute2, thanks to whoever wrote
  * this, probably Alexey. */
@@ -226,7 +231,7 @@
 		addr->a_prefixlen = size*8;
 	}
 
-	if (size)
+	if (size && buf)
 		memcpy(addr->a_addr, buf, size);
 
 	return addr;
@@ -316,8 +321,6 @@
 	    !strcasecmp(str, "all") ||
 	    !strcasecmp(str, "any")) {
 
-		len = 0;
-
 		switch (hint) {
 			case AF_INET:
 			case AF_UNSPEC:
@@ -325,14 +328,17 @@
 				 * no hint given the user wants to have a IPv4
 				 * address given back. */
 				family = AF_INET;
+				len = 4;
 				goto prefix;
 
 			case AF_INET6:
 				family = AF_INET6;
+				len = 16;
 				goto prefix;
 
 			case AF_LLC:
 				family = AF_LLC;
+				len = 6;
 				goto prefix;
 
 			default:
@@ -449,6 +455,8 @@
 
 	if (copy)
 		nl_addr_set_binary_addr(addr, buf, len);
+	else
+		addr->a_len = len;
 
 	if (prefix) {
 		char *p;
@@ -460,7 +468,7 @@
 		}
 		nl_addr_set_prefixlen(addr, pl);
 	} else {
-		if (!plen)
+		if (copy && !plen)
 			plen = len * 8;
 		nl_addr_set_prefixlen(addr, plen);
 	}
@@ -620,7 +628,7 @@
 	int d = a->a_family - b->a_family;
 
 	if (d == 0) {
-		int len = min(a->a_prefixlen, b->a_prefixlen);
+		int len = _NL_MIN(a->a_prefixlen, b->a_prefixlen);
 		int bytes = len / 8;
 
 		d = memcmp(a->a_addr, b->a_addr, bytes);
diff --git a/lib/attr.c b/lib/attr.c
index 6838dba..b8b9837 100644
--- a/lib/attr.c
+++ b/lib/attr.c
@@ -3,13 +3,18 @@
  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/socket.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/addr.h>
 #include <netlink/attr.h>
 #include <netlink/msg.h>
-#include <linux/socket.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-aux-core/nl-core.h"
 
 /**
  * @ingroup msg
@@ -349,10 +354,13 @@
 
 	if (!src)
 		return 0;
-	
-	minlen = min_t(int, count, nla_len(src));
-	memcpy(dest, nla_data(src), minlen);
 
+	minlen = _NL_MIN(count, nla_len(src));
+
+	if (minlen <= 0)
+		return 0;
+
+	memcpy(dest, nla_data(src), minlen);
 	return minlen;
 }
 
@@ -541,6 +549,9 @@
  */
 int nla_put_addr(struct nl_msg *msg, int attrtype, struct nl_addr *addr)
 {
+	if (nl_addr_get_len(addr) == 0)
+		return -NLE_INVAL;
+
 	return nla_put(msg, attrtype, nl_addr_get_len(addr),
 		       nl_addr_get_binary_addr(addr));
 }
@@ -988,6 +999,15 @@
 {
 	ssize_t len;
 
+	if (!attr) {
+		/* For robustness, allow a NULL attr to do nothing. NULL is also
+		 * what nla_nest_start() when out of buffer space.
+		 *
+		 * Warning, before libnl-3.8, the function did not accept NULL!
+		 * If you care, catch NULL yourself. */
+		return;
+	}
+
 	len = (char *) nlmsg_tail(msg->nm_nlh) - (char *) attr;
 	if (len < 0)
 		BUG();
diff --git a/lib/cache.c b/lib/cache.c
index eadce57..dd059c1 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -43,14 +43,20 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
 #include <netlink/hashtable.h>
 #include <netlink/utils.h>
 
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+
 /**
  * @name Access Functions
  * @{
diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c
index dd119f2..f16882f 100644
--- a/lib/cache_mngr.c
+++ b/lib/cache_mngr.c
@@ -26,13 +26,28 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
 
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+
 /** @cond SKIP */
+struct nl_cache_mngr
+{
+	int			cm_protocol;
+	int			cm_flags;
+	int			cm_nassocs;
+	struct nl_sock *	cm_sock;
+	struct nl_sock *	cm_sync_sock;
+	struct nl_cache_assoc *	cm_assocs;
+};
+
 #define NASSOC_INIT		16
 #define NASSOC_EXPAND		8
 /** @endcond */
diff --git a/lib/cache_mngt.c b/lib/cache_mngt.c
index f506976..7969d35 100644
--- a/lib/cache_mngt.c
+++ b/lib/cache_mngt.c
@@ -19,11 +19,17 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+
 static struct nl_cache_ops *cache_ops;
 static NL_RW_LOCK(cache_ops_lock);
 
diff --git a/lib/cli/cls/basic.c b/lib/cli/cls/basic.c
index 90ef554..5d33e89 100644
--- a/lib/cli/cls/basic.c
+++ b/lib/cli/cls/basic.c
@@ -3,11 +3,15 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/cls.h>
 #include <netlink/route/cls/basic.h>
 
+#include "base/nl-base-utils.h"
+
 static void print_usage(void)
 {
 	printf(
@@ -76,12 +80,12 @@
 	.tm_parse_argv		= parse_argv,
 };
 
-static void __init basic_init(void)
+static void _nl_init basic_init(void)
 {
 	nl_cli_tc_register(&basic_module);
 }
 
-static void __exit basic_exit(void)
+static void _nl_exit basic_exit(void)
 {
 	nl_cli_tc_unregister(&basic_module);
 }
diff --git a/lib/cli/cls/cgroup.c b/lib/cli/cls/cgroup.c
index 43536b5..296df69 100644
--- a/lib/cli/cls/cgroup.c
+++ b/lib/cli/cls/cgroup.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/cls.h>
@@ -58,12 +60,12 @@
 	.tm_parse_argv		= parse_argv,
 };
 
-static void __init cgroup_init(void)
+static void _nl_init cgroup_init(void)
 {
 	nl_cli_tc_register(&cgroup_module);
 }
 
-static void __exit cgroup_exit(void)
+static void _nl_exit cgroup_exit(void)
 {
 	nl_cli_tc_unregister(&cgroup_module);
 }
diff --git a/lib/cli/qdisc/bfifo.c b/lib/cli/qdisc/bfifo.c
index 7e53541..30db045 100644
--- a/lib/cli/qdisc/bfifo.c
+++ b/lib/cli/qdisc/bfifo.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/fifo.h>
@@ -66,12 +68,12 @@
 	.tm_parse_argv		= bfifo_parse_argv,
 };
 
-static void __init bfifo_init(void)
+static void _nl_init bfifo_init(void)
 {
 	nl_cli_tc_register(&bfifo_module);
 }
 
-static void __exit bfifo_exit(void)
+static void _nl_exit bfifo_exit(void)
 {
 	nl_cli_tc_unregister(&bfifo_module);
 }
diff --git a/lib/cli/qdisc/blackhole.c b/lib/cli/qdisc/blackhole.c
index 2425ab7..0ae0a53 100644
--- a/lib/cli/qdisc/blackhole.c
+++ b/lib/cli/qdisc/blackhole.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 
@@ -47,12 +49,12 @@
 	.tm_parse_argv		= blackhole_parse_argv,
 };
 
-static void __init blackhole_init(void)
+static void _nl_init blackhole_init(void)
 {
 	nl_cli_tc_register(&blackhole_module);
 }
 
-static void __exit blackhole_exit(void)
+static void _nl_exit blackhole_exit(void)
 {
 	nl_cli_tc_unregister(&blackhole_module);
 }
diff --git a/lib/cli/qdisc/fq_codel.c b/lib/cli/qdisc/fq_codel.c
index 90e609e..83e409a 100644
--- a/lib/cli/qdisc/fq_codel.c
+++ b/lib/cli/qdisc/fq_codel.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/fq_codel.h>
@@ -95,12 +97,12 @@
 	.tm_parse_argv		= fq_codel_parse_argv,
 };
 
-static void __init fq_codel_init(void)
+static void _nl_init fq_codel_init(void)
 {
 	nl_cli_tc_register(&fq_codel_module);
 }
 
-static void __exit fq_codel_exit(void)
+static void _nl_exit fq_codel_exit(void)
 {
 	nl_cli_tc_unregister(&fq_codel_module);
 }
diff --git a/lib/cli/qdisc/hfsc.c b/lib/cli/qdisc/hfsc.c
index cbbc100..9ab7f7e 100644
--- a/lib/cli/qdisc/hfsc.c
+++ b/lib/cli/qdisc/hfsc.c
@@ -3,10 +3,13 @@
  * Copyright (c) 2014 Cong Wang <xiyou.wangcong@gmail.com>
  */
 
+#include "nl-default.h"
+
+#include <linux/pkt_sched.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/hfsc.h>
-#include <linux/pkt_sched.h>
 
 static void print_qdisc_usage(void)
 {
@@ -233,13 +236,13 @@
 	.tm_parse_argv		= hfsc_parse_class_argv,
 };
 
-static void __init hfsc_init(void)
+static void _nl_init hfsc_init(void)
 {
 	nl_cli_tc_register(&hfsc_qdisc_module);
 	nl_cli_tc_register(&hfsc_class_module);
 }
 
-static void __exit hfsc_exit(void)
+static void _nl_exit hfsc_exit(void)
 {
 	nl_cli_tc_unregister(&hfsc_class_module);
 	nl_cli_tc_unregister(&hfsc_qdisc_module);
diff --git a/lib/cli/qdisc/htb.c b/lib/cli/qdisc/htb.c
index 235701c..5ca6ae5 100644
--- a/lib/cli/qdisc/htb.c
+++ b/lib/cli/qdisc/htb.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/htb.h>
@@ -184,13 +186,13 @@
 	.tm_parse_argv		= htb_parse_class_argv,
 };
 
-static void __init htb_init(void)
+static void _nl_init htb_init(void)
 {
 	nl_cli_tc_register(&htb_qdisc_module);
 	nl_cli_tc_register(&htb_class_module);
 }
 
-static void __exit htb_exit(void)
+static void _nl_exit htb_exit(void)
 {
 	nl_cli_tc_unregister(&htb_class_module);
 	nl_cli_tc_unregister(&htb_qdisc_module);
diff --git a/lib/cli/qdisc/ingress.c b/lib/cli/qdisc/ingress.c
index 3c2a6c0..9c09c4f 100644
--- a/lib/cli/qdisc/ingress.c
+++ b/lib/cli/qdisc/ingress.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Cong Wang <xiyou.wangcong@gmail.com>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 
@@ -47,12 +49,12 @@
 	.tm_parse_argv		= ingress_parse_argv,
 };
 
-static void __init ingress_init(void)
+static void _nl_init ingress_init(void)
 {
 	nl_cli_tc_register(&ingress_module);
 }
 
-static void __exit ingress_exit(void)
+static void _nl_exit ingress_exit(void)
 {
 	nl_cli_tc_unregister(&ingress_module);
 }
diff --git a/lib/cli/qdisc/pfifo.c b/lib/cli/qdisc/pfifo.c
index fbda6eb..fbaa872 100644
--- a/lib/cli/qdisc/pfifo.c
+++ b/lib/cli/qdisc/pfifo.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/fifo.h>
@@ -59,12 +61,12 @@
 	.tm_parse_argv		= pfifo_parse_argv,
 };
 
-static void __init pfifo_init(void)
+static void _nl_init pfifo_init(void)
 {
 	nl_cli_tc_register(&pfifo_module);
 }
 
-static void __exit pfifo_exit(void)
+static void _nl_exit pfifo_exit(void)
 {
 	nl_cli_tc_unregister(&pfifo_module);
 }
diff --git a/lib/cli/qdisc/plug.c b/lib/cli/qdisc/plug.c
index 549db0b..212a6cf 100644
--- a/lib/cli/qdisc/plug.c
+++ b/lib/cli/qdisc/plug.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2012 Shriram Rajagopalan <rshriram@cs.ubc.ca>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/route/qdisc/plug.h>
@@ -95,12 +97,12 @@
 	.tm_parse_argv		= plug_parse_argv,
 };
 
-static void __init plug_init(void)
+static void _nl_init plug_init(void)
 {
 	nl_cli_tc_register(&plug_module);
 }
 
-static void __exit plug_exit(void)
+static void _nl_exit plug_exit(void)
 {
 	nl_cli_tc_unregister(&plug_module);
 }
diff --git a/lib/data.c b/lib/data.c
index 87df30f..1052578 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -21,11 +21,17 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink/netlink.h>
-#include <netlink/utils.h>
+#include "nl-default.h"
+
 #include <linux/socket.h>
 
+#include <netlink/netlink.h>
+#include <netlink/data.h>
+#include <netlink/attr.h>
+#include <netlink/utils.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /**
  * @name General
  * @{
diff --git a/lib/error.c b/lib/error.c
index bd0b92d..9b6d806 100644
--- a/lib/error.c
+++ b/lib/error.c
@@ -3,7 +3,8 @@
  * Copyright (c) 2008 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 
 static const char *errmsg[NLE_MAX+1] = {
diff --git a/lib/fib_lookup/lookup.c b/lib/fib_lookup/lookup.c
index e258546..7ff2684 100644
--- a/lib/fib_lookup/lookup.c
+++ b/lib/fib_lookup/lookup.c
@@ -10,8 +10,8 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
@@ -21,7 +21,24 @@
 #include <netlink/fib_lookup/request.h>
 #include <netlink/fib_lookup/lookup.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /** @cond SKIP */
+struct flnl_result
+{
+	NLHDR_COMMON
+
+	struct flnl_request *	fr_req;
+	uint8_t			fr_table_id;
+	uint8_t			fr_prefixlen;
+	uint8_t			fr_nh_sel;
+	uint8_t			fr_type;
+	uint8_t			fr_scope;
+	uint32_t		fr_error;
+};
+
 static struct nl_cache_ops fib_lookup_ops;
 static struct nl_object_ops result_obj_ops;
 
@@ -333,12 +350,12 @@
 	.co_obj_ops		= &result_obj_ops,
 };
 
-static void __init fib_lookup_init(void)
+static void _nl_init fib_lookup_init(void)
 {
 	nl_cache_mngt_register(&fib_lookup_ops);
 }
 
-static void __exit fib_lookup_exit(void)
+static void _nl_exit fib_lookup_exit(void)
 {
 	nl_cache_mngt_unregister(&fib_lookup_ops);
 }
diff --git a/lib/fib_lookup/request.c b/lib/fib_lookup/request.c
index 0773c3b..81b7ba2 100644
--- a/lib/fib_lookup/request.c
+++ b/lib/fib_lookup/request.c
@@ -10,16 +10,31 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/fib_lookup/request.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+
 static struct nl_object_ops request_obj_ops;
 
 /** @cond SKIP */
+struct flnl_request
+{
+	NLHDR_COMMON
+
+	struct nl_addr *	lr_addr;
+	uint32_t		lr_fwmark;
+	uint8_t			lr_tos;
+	uint8_t			lr_scope;
+	uint8_t			lr_table;
+};
+
 #define REQUEST_ATTR_ADDR	0x01
 #define REQUEST_ATTR_FWMARK	0x02
 #define REQUEST_ATTR_TOS	0x04
@@ -57,15 +72,13 @@
 	struct flnl_request *b = (struct flnl_request *) _b;
 	uint64_t diff = 0;
 
-#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= REQ_DIFF(FWMARK,	a->lr_fwmark != b->lr_fwmark);
-	diff |= REQ_DIFF(TOS,		a->lr_tos != b->lr_tos);
-	diff |= REQ_DIFF(SCOPE,		a->lr_scope != b->lr_scope);
-	diff |= REQ_DIFF(TABLE,		a->lr_table != b->lr_table);
-	diff |= REQ_DIFF(ADDR,		nl_addr_cmp(a->lr_addr, b->lr_addr));
-
-#undef REQ_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(REQUEST_ATTR_FWMARK, a->lr_fwmark != b->lr_fwmark);
+	diff |= _DIFF(REQUEST_ATTR_TOS, a->lr_tos != b->lr_tos);
+	diff |= _DIFF(REQUEST_ATTR_SCOPE, a->lr_scope != b->lr_scope);
+	diff |= _DIFF(REQUEST_ATTR_TABLE, a->lr_table != b->lr_table);
+	diff |= _DIFF(REQUEST_ATTR_ADDR, nl_addr_cmp(a->lr_addr, b->lr_addr));
+#undef _DIFF
 
 	return diff;
 }
diff --git a/lib/genl/ctrl.c b/lib/genl/ctrl.c
index 65b5f05..1747076 100644
--- a/lib/genl/ctrl.c
+++ b/lib/genl/ctrl.c
@@ -15,7 +15,8 @@
  * @{
  */
 
-#include <netlink-private/genl.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
@@ -23,6 +24,10 @@
 #include <netlink/genl/ctrl.h>
 #include <netlink/utils.h>
 
+#include "nl-genl.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+
 /** @cond SKIP */
 #define CTRL_VERSION		0x0001
 
@@ -517,6 +522,12 @@
 
 extern struct nl_object_ops genl_family_ops;
 
+#define GENL_FAMILY(id, name) \
+	{ \
+		{ id, NL_ACT_UNSPEC, name }, \
+		END_OF_MSGTYPES_LIST, \
+	}
+
 static struct nl_cache_ops genl_ctrl_ops = {
 	.co_name		= "genl/family",
 	.co_hdrsize		= GENL_HDRSIZE(0),
@@ -527,12 +538,12 @@
 	.co_obj_ops		= &genl_family_ops,
 };
 
-static void __init ctrl_init(void)
+static void _nl_init ctrl_init(void)
 {
 	genl_register(&genl_ctrl_ops);
 }
 
-static void __exit ctrl_exit(void)
+static void _nl_exit ctrl_exit(void)
 {
 	genl_unregister(&genl_ctrl_ops);
 }
diff --git a/lib/genl/family.c b/lib/genl/family.c
index e8e0c9e..1749472 100644
--- a/lib/genl/family.c
+++ b/lib/genl/family.c
@@ -12,15 +12,26 @@
  * @{
  */
 
-#include <netlink-private/genl.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
 #include <netlink/utils.h>
 
-#include "netlink-private/utils.h"
+#include "nl-genl.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /** @cond SKIP */
+struct genl_family_op
+{
+	uint32_t		o_id;
+	uint32_t		o_flags;
+
+	struct nl_list_head	o_list;
+};
+
 #define FAMILY_ATTR_ID		0x01
 #define FAMILY_ATTR_NAME	0x02
 #define FAMILY_ATTR_VERSION	0x04
@@ -153,15 +164,13 @@
 	struct genl_family *b = (struct genl_family *) _b;
 	uint64_t diff = 0;
 
-#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= FAM_DIFF(ID,		a->gf_id != b->gf_id);
-	diff |= FAM_DIFF(VERSION,	a->gf_version != b->gf_version);
-	diff |= FAM_DIFF(HDRSIZE,	a->gf_hdrsize != b->gf_hdrsize);
-	diff |= FAM_DIFF(MAXATTR,	a->gf_maxattr != b->gf_maxattr);
-	diff |= FAM_DIFF(NAME,		strcmp(a->gf_name, b->gf_name));
-
-#undef FAM_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(FAMILY_ATTR_ID, a->gf_id != b->gf_id);
+	diff |= _DIFF(FAMILY_ATTR_VERSION, a->gf_version != b->gf_version);
+	diff |= _DIFF(FAMILY_ATTR_HDRSIZE, a->gf_hdrsize != b->gf_hdrsize);
+	diff |= _DIFF(FAMILY_ATTR_MAXATTR, a->gf_maxattr != b->gf_maxattr);
+	diff |= _DIFF(FAMILY_ATTR_NAME, strcmp(a->gf_name, b->gf_name));
+#undef _DIFF
 
 	return diff;
 }
diff --git a/lib/genl/genl.c b/lib/genl/genl.c
index 4fd7962..2e52aae 100644
--- a/lib/genl/genl.c
+++ b/lib/genl/genl.c
@@ -9,11 +9,15 @@
  * @{
  */
 
-#include <netlink-private/genl.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/genl/genl.h>
 #include <netlink/utils.h>
 
+#include "nl-genl.h"
+#include "nl-aux-core/nl-core.h"
+
 /**
  * @name Generic Netlink Socket
  * @{
diff --git a/lib/genl/mngt.c b/lib/genl/mngt.c
index 1dcddbc..e55256c 100644
--- a/lib/genl/mngt.c
+++ b/lib/genl/mngt.c
@@ -12,7 +12,8 @@
  * @{
  */
 
-#include <netlink-private/genl.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/genl/genl.h>
 #include <netlink/genl/mngt.h>
@@ -20,7 +21,7 @@
 #include <netlink/genl/ctrl.h>
 #include <netlink/utils.h>
 
-#include "netlink-private/utils.h"
+#include "nl-genl.h"
 
 /** @cond SKIP */
 
@@ -307,6 +308,7 @@
 	return -NLE_OBJ_NOTFOUND;
 }
 
+/* WARNING: this symbol is wrongly exported in libnl-genl-3.sym. */
 int genl_resolve_id(struct genl_ops *ops)
 {
 	struct nl_sock *sk;
diff --git a/lib/genl/nl-genl.h b/lib/genl/nl-genl.h
new file mode 100644
index 0000000..2ad7cd0
--- /dev/null
+++ b/lib/genl/nl-genl.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_GENL_PRIV_H_
+#define NETLINK_GENL_PRIV_H_
+
+#include <netlink/netlink.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+#define GENL_HDRSIZE(hdrlen) (GENL_HDRLEN + (hdrlen))
+
+/*****************************************************************************/
+
+/* WARNING: this symbol is wrongly exported in libnl-genl-3.sym. */
+extern int		genl_resolve_id(struct genl_ops *ops);
+
+/*****************************************************************************/
+
+#define GENL_OP_HAS_POLICY	1
+#define GENL_OP_HAS_DOIT	2
+#define GENL_OP_HAS_DUMPIT	4
+
+struct genl_family_grp {
+        struct genl_family      *family;        /* private */
+        struct nl_list_head     list;           /* private */
+        char                    name[GENL_NAMSIZ];
+        u_int32_t               id;
+};
+
+struct genl_family
+{
+	NLHDR_COMMON
+
+	uint16_t		gf_id;
+	char 			gf_name[GENL_NAMSIZ];
+	uint32_t		gf_version;
+	uint32_t		gf_hdrsize;
+	uint32_t		gf_maxattr;
+
+	struct nl_list_head	gf_ops;
+	struct nl_list_head	gf_mc_grps;
+};
+
+#endif
diff --git a/lib/handlers.c b/lib/handlers.c
index e6fca0e..14dffba 100644
--- a/lib/handlers.c
+++ b/lib/handlers.c
@@ -19,13 +19,16 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/msg.h>
 #include <netlink/handlers.h>
 
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
 {
 	char flags[128];
diff --git a/lib/hash.c b/lib/hash.c
index 17b5c8f..94a73f8 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -39,6 +39,8 @@
 on 1 byte), but shoehorning those bytes into integers efficiently is messy.
 -------------------------------------------------------------------------------
 */
+#include "nl-default.h"
+
 #include <netlink/hash.h>
 
 #if HAVE_LITTLE_ENDIAN
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 1b332ba..7cb6984 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2012 Cumulus Networks, Inc
  */
 
-#include <string.h>
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/object.h>
 #include <netlink/hash.h>
 #include <netlink/hashtable.h>
 
+#include "nl-aux-core/nl-core.h"
+
 /**
  * @ingroup core_types
  * @defgroup hashtable Hashtable
diff --git a/lib/idiag/idiag.c b/lib/idiag/idiag.c
index 38c3a6b..4f5d9f9 100644
--- a/lib/idiag/idiag.c
+++ b/lib/idiag/idiag.c
@@ -9,11 +9,15 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/inet_diag.h>
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/idiag/idiagnl.h>
-#include <linux/inet_diag.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /**
  * @name Socket Creation
diff --git a/lib/idiag/idiag_meminfo_obj.c b/lib/idiag/idiag_meminfo_obj.c
index 55ff8cc..ebb9767 100644
--- a/lib/idiag/idiag_meminfo_obj.c
+++ b/lib/idiag/idiag_meminfo_obj.c
@@ -3,9 +3,12 @@
  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/idiag/meminfo.h>
 
+#include "nl-idiag.h"
+
 /**
  * @ingroup idiag
  * @defgroup idiagnl_meminfo Inet Diag Memory Info
diff --git a/lib/idiag/idiag_msg_obj.c b/lib/idiag/idiag_msg_obj.c
index f42bd59..2c78eb1 100644
--- a/lib/idiag/idiag_msg_obj.c
+++ b/lib/idiag/idiag_msg_obj.c
@@ -3,15 +3,50 @@
  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/inet_diag.h>
+
 #include <netlink/hashtable.h>
 #include <netlink/idiag/msg.h>
 #include <netlink/idiag/meminfo.h>
 #include <netlink/idiag/vegasinfo.h>
-#include <linux/inet_diag.h>
+#include <netlink/idiag/idiagnl.h>
 
+#include "nl-idiag.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 /** @cond SKIP */
+struct idiagnl_msg {
+	NLHDR_COMMON
+
+	uint8_t			    idiag_family;
+	uint8_t			    idiag_state;
+	uint8_t			    idiag_timer;
+	uint8_t			    idiag_retrans;
+	uint16_t		    idiag_sport;
+	uint16_t		    idiag_dport;
+	struct nl_addr *	    idiag_src;
+	struct nl_addr *	    idiag_dst;
+	uint32_t		    idiag_ifindex;
+	uint32_t		    idiag_expires;
+	uint32_t		    idiag_rqueue;
+	uint32_t		    idiag_wqueue;
+	uint32_t		    idiag_uid;
+	uint32_t		    idiag_inode;
+
+	uint8_t			    idiag_tos;
+	uint8_t			    idiag_tclass;
+	uint8_t			    idiag_shutdown;
+	char *			    idiag_cong;
+	struct idiagnl_meminfo *    idiag_meminfo;
+	struct idiagnl_vegasinfo *  idiag_vegasinfo;
+	struct tcp_info		    idiag_tcpinfo;
+	uint32_t		    idiag_skmeminfo[SK_MEMINFO_VARS];
+};
+
 #define IDIAGNL_ATTR_FAMILY                     (0x1 << 1)
 #define IDIAGNL_ATTR_STATE                      (0x1 << 2)
 #define IDIAGNL_ATTR_TIMER                      (0x1 << 3)
@@ -110,12 +145,12 @@
 	.co_obj_ops		= &idiagnl_msg_obj_ops,
 };
 
-static void __init idiagnl_init(void)
+static void _nl_init idiagnl_init(void)
 {
 	nl_cache_mngt_register(&idiagnl_msg_ops);
 }
 
-static void __exit idiagnl_exit(void)
+static void _nl_exit idiagnl_exit(void)
 {
 	nl_cache_mngt_unregister(&idiagnl_msg_ops);
 }
@@ -864,30 +899,45 @@
 	struct idiagnl_msg *b = (struct idiagnl_msg *) _b;
 	uint64_t diff = 0;
 
-#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, IDIAGNL_ATTR_##ATTR, a, b, EXPR)
-	diff |= _DIFF(FAMILY,    a->idiag_family != b->idiag_family);
-	diff |= _DIFF(STATE,     a->idiag_state != b->idiag_state);
-	diff |= _DIFF(TIMER,     a->idiag_timer != b->idiag_timer);
-	diff |= _DIFF(RETRANS,   a->idiag_retrans != b->idiag_retrans);
-	diff |= _DIFF(SPORT,     a->idiag_sport != b->idiag_sport);
-	diff |= _DIFF(DPORT,     a->idiag_dport != b->idiag_dport);
-	diff |= _DIFF(SRC,       nl_addr_cmp (a->idiag_src, b->idiag_src));
-	diff |= _DIFF(DST,       nl_addr_cmp (a->idiag_dst, b->idiag_dst));
-	diff |= _DIFF(IFINDEX,   a->idiag_ifindex != b->idiag_ifindex);
-	diff |= _DIFF(EXPIRES,   a->idiag_expires != b->idiag_expires);
-	diff |= _DIFF(RQUEUE,    a->idiag_rqueue != b->idiag_rqueue);
-	diff |= _DIFF(WQUEUE,    a->idiag_wqueue != b->idiag_wqueue);
-	diff |= _DIFF(UID,       a->idiag_uid != b->idiag_uid);
-	diff |= _DIFF(INODE,     a->idiag_inode != b->idiag_inode);
-	diff |= _DIFF(TOS,       a->idiag_tos != b->idiag_tos);
-	diff |= _DIFF(TCLASS,    a->idiag_tclass != b->idiag_tclass);
-	diff |= _DIFF(SHUTDOWN,  a->idiag_shutdown != b->idiag_shutdown);
-	diff |= _DIFF(CONG,      strcmp(a->idiag_cong, b->idiag_cong));
-	diff |= _DIFF(MEMINFO,   nl_object_diff((struct nl_object *) a->idiag_meminfo, (struct nl_object *) b->idiag_meminfo));
-	diff |= _DIFF(VEGASINFO, nl_object_diff((struct nl_object *) a->idiag_vegasinfo, (struct nl_object *) b->idiag_vegasinfo));
-	diff |= _DIFF(TCPINFO,   memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo, sizeof(a->idiag_tcpinfo)));
-	diff |= _DIFF(SKMEMINFO, memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo, sizeof(a->idiag_skmeminfo)));
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(IDIAGNL_ATTR_FAMILY, a->idiag_family != b->idiag_family);
+	diff |= _DIFF(IDIAGNL_ATTR_STATE, a->idiag_state != b->idiag_state);
+	diff |= _DIFF(IDIAGNL_ATTR_TIMER, a->idiag_timer != b->idiag_timer);
+	diff |= _DIFF(IDIAGNL_ATTR_RETRANS,
+		      a->idiag_retrans != b->idiag_retrans);
+	diff |= _DIFF(IDIAGNL_ATTR_SPORT, a->idiag_sport != b->idiag_sport);
+	diff |= _DIFF(IDIAGNL_ATTR_DPORT, a->idiag_dport != b->idiag_dport);
+	diff |= _DIFF(IDIAGNL_ATTR_SRC,
+		      nl_addr_cmp(a->idiag_src, b->idiag_src));
+	diff |= _DIFF(IDIAGNL_ATTR_DST,
+		      nl_addr_cmp(a->idiag_dst, b->idiag_dst));
+	diff |= _DIFF(IDIAGNL_ATTR_IFINDEX,
+		      a->idiag_ifindex != b->idiag_ifindex);
+	diff |= _DIFF(IDIAGNL_ATTR_EXPIRES,
+		      a->idiag_expires != b->idiag_expires);
+	diff |= _DIFF(IDIAGNL_ATTR_RQUEUE, a->idiag_rqueue != b->idiag_rqueue);
+	diff |= _DIFF(IDIAGNL_ATTR_WQUEUE, a->idiag_wqueue != b->idiag_wqueue);
+	diff |= _DIFF(IDIAGNL_ATTR_UID, a->idiag_uid != b->idiag_uid);
+	diff |= _DIFF(IDIAGNL_ATTR_INODE, a->idiag_inode != b->idiag_inode);
+	diff |= _DIFF(IDIAGNL_ATTR_TOS, a->idiag_tos != b->idiag_tos);
+	diff |= _DIFF(IDIAGNL_ATTR_TCLASS, a->idiag_tclass != b->idiag_tclass);
+	diff |= _DIFF(IDIAGNL_ATTR_SHUTDOWN,
+		      a->idiag_shutdown != b->idiag_shutdown);
+	diff |= _DIFF(IDIAGNL_ATTR_CONG, strcmp(a->idiag_cong, b->idiag_cong));
+	diff |= _DIFF(IDIAGNL_ATTR_MEMINFO,
+		      nl_object_diff((struct nl_object *)a->idiag_meminfo,
+				     (struct nl_object *)b->idiag_meminfo));
+	diff |= _DIFF(IDIAGNL_ATTR_VEGASINFO,
+		      nl_object_diff((struct nl_object *)a->idiag_vegasinfo,
+				     (struct nl_object *)b->idiag_vegasinfo));
+	diff |= _DIFF(IDIAGNL_ATTR_TCPINFO,
+		      memcmp(&a->idiag_tcpinfo, &b->idiag_tcpinfo,
+			     sizeof(a->idiag_tcpinfo)));
+	diff |= _DIFF(IDIAGNL_ATTR_SKMEMINFO,
+		      memcmp(a->idiag_skmeminfo, b->idiag_skmeminfo,
+			     sizeof(a->idiag_skmeminfo)));
 #undef _DIFF
+
 	return diff;
 }
 
@@ -902,7 +952,7 @@
 		uint32_t dst_hash;
 		uint16_t sport;
 		uint16_t dport;
-	} __attribute__((packed)) key;
+	} _nl_packed key;
 
 	key_sz = sizeof(key);
 	key.family = msg->idiag_family;
diff --git a/lib/idiag/idiag_req_obj.c b/lib/idiag/idiag_req_obj.c
index e88fbc2..cc23a80 100644
--- a/lib/idiag/idiag_req_obj.c
+++ b/lib/idiag/idiag_req_obj.c
@@ -3,10 +3,30 @@
  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink/idiag/req.h>
+#include "nl-default.h"
+
 #include <linux/inet_diag.h>
 
+#include <netlink/idiag/req.h>
+#include <netlink/idiag/idiagnl.h>
+#include <netlink/data.h>
+#include <netlink/addr.h>
+#include <netlink/msg.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+
+struct idiagnl_req {
+	NLHDR_COMMON
+
+	uint8_t			idiag_family;
+	uint8_t			idiag_ext;
+	struct nl_addr *	idiag_src;
+	struct nl_addr *	idiag_dst;
+	uint32_t		idiag_ifindex;
+	uint32_t		idiag_states;
+	uint32_t		idiag_dbs;
+};
+
 /**
  * @ingroup idiag
  * @defgroup idiagnl_req Inet Diag Requests
diff --git a/lib/idiag/idiag_vegasinfo_obj.c b/lib/idiag/idiag_vegasinfo_obj.c
index ff9213d..f9e9408 100644
--- a/lib/idiag/idiag_vegasinfo_obj.c
+++ b/lib/idiag/idiag_vegasinfo_obj.c
@@ -3,9 +3,12 @@
  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/idiag/vegasinfo.h>
 
+#include "nl-idiag.h"
+
 /**
  * @ingroup idiag
  * @defgroup idiagnl_vegasinfo Inet Diag TCP Vegas Info
diff --git a/lib/idiag/nl-idiag.h b/lib/idiag/nl-idiag.h
new file mode 100644
index 0000000..3615bb3
--- /dev/null
+++ b/lib/idiag/nl-idiag.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __LIB_IDIAG_NL_IDIAG_H__
+#define __LIB_IDIAG_NL_IDIAG_H__
+
+#include "nl-priv-dynamic-core/object-api.h"
+
+struct idiagnl_meminfo {
+	NLHDR_COMMON
+
+	uint32_t idiag_rmem;
+	uint32_t idiag_wmem;
+	uint32_t idiag_fmem;
+	uint32_t idiag_tmem;
+};
+
+struct idiagnl_vegasinfo {
+	NLHDR_COMMON
+
+	uint32_t tcpv_enabled;
+	uint32_t tcpv_rttcnt;
+	uint32_t tcpv_rtt;
+	uint32_t tcpv_minrtt;
+};
+
+#endif /* __LIB_IDIAG_NL_IDIAG_H__ */
diff --git a/lib/mpls.c b/lib/mpls.c
index 6d0e493..d0189bf 100644
--- a/lib/mpls.c
+++ b/lib/mpls.c
@@ -3,13 +3,16 @@
  * Adapted from mpls_ntop and mpls_pton copied from iproute2,
  * lib/mpls_ntop.c and lib/mpls_pton.c
  */
-#include <errno.h>
+
+#include "nl-default.h"
+
 #include <stdio.h>
-#include <stdlib.h>
-#include <netinet/in.h>
+
+#include <linux/mpls.h>
+
 #include <netlink/netlink-compat.h>
-#include <netlink-private/route/mpls.h>
-#include <linux-private/linux/mpls.h>
+
+#include "mpls.h"
 
 static const char *mpls_ntop1(const struct mpls_label *addr,
 			      char *buf, size_t buflen)
diff --git a/include/netlink-private/route/mpls.h b/lib/mpls.h
similarity index 73%
rename from include/netlink-private/route/mpls.h
rename to lib/mpls.h
index 502fd34..591b3cc 100644
--- a/include/netlink-private/route/mpls.h
+++ b/lib/mpls.h
@@ -1,15 +1,7 @@
 #ifndef MPLS_H_
 #define MPLS_H_
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern const char *mpls_ntop(int af, const void *addr, char *buf, size_t buflen);
 extern int mpls_pton(int af, const char *src, void *addr, size_t alen);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/lib/msg.c b/lib/msg.c
index 17ca812..0e1592a 100644
--- a/lib/msg.c
+++ b/lib/msg.c
@@ -20,17 +20,25 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
+#include <ctype.h>
+
+#include <linux/socket.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/cache.h>
 #include <netlink/attr.h>
-#include <linux/socket.h>
+
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
 
 static size_t default_msg_size;
 
-static void __init init_msg_size(void)
+static void _nl_init init_msg_size(void)
 {
 	default_msg_size = getpagesize();
 }
@@ -148,7 +156,7 @@
  */
 int nlmsg_attrlen(const struct nlmsghdr *nlh, int hdrlen)
 {
-	return max_t(int, nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen), 0);
+	return _NL_MAX(nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen), 0u);
 }
 
 /** @} */
diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c
index d5725f4..3a69a2d 100644
--- a/lib/netfilter/ct.c
+++ b/lib/netfilter/ct.c
@@ -13,15 +13,19 @@
  * @{
  */
 
-#include <byteswap.h>
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_conntrack.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/ct.h>
-#include <netlink-private/utils.h>
+
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 static struct nl_cache_ops nfnl_ct_ops;
 
@@ -704,12 +708,12 @@
 	.co_obj_ops		= &ct_obj_ops,
 };
 
-static void __init ct_init(void)
+static void _nl_init ct_init(void)
 {
 	nl_cache_mngt_register(&nfnl_ct_ops);
 }
 
-static void __exit ct_exit(void)
+static void _nl_exit ct_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_ct_ops);
 }
diff --git a/lib/netfilter/ct_obj.c b/lib/netfilter/ct_obj.c
index 86cbc17..4430400 100644
--- a/lib/netfilter/ct_obj.c
+++ b/lib/netfilter/ct_obj.c
@@ -5,15 +5,22 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <linux/netfilter/nf_conntrack_common.h>
+
 #include <linux/netfilter/nf_conntrack_tcp.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/ct.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /** @cond SKIP */
 #define CT_ATTR_FAMILY		(1UL << 0)
 #define CT_ATTR_PROTO		(1UL << 1)
@@ -304,48 +311,46 @@
 	struct nfnl_ct *b = (struct nfnl_ct *) _b;
 	uint64_t diff = 0;
 
-#define CT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, CT_ATTR_##ATTR, a, b, EXPR)
-#define CT_DIFF_VAL(ATTR, FIELD) CT_DIFF(ATTR, a->FIELD != b->FIELD)
-#define CT_DIFF_ADDR(ATTR, FIELD) \
-	((flags & LOOSE_COMPARISON) \
-		? CT_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
-		: CT_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
-
-	diff |= CT_DIFF_VAL(FAMILY,		ct_family);
-	diff |= CT_DIFF_VAL(PROTO,		ct_proto);
-	diff |= CT_DIFF_VAL(TCP_STATE,		ct_protoinfo.tcp.state);
-	diff |= CT_DIFF_VAL(TIMEOUT,		ct_timeout);
-	diff |= CT_DIFF_VAL(MARK,		ct_mark);
-	diff |= CT_DIFF_VAL(USE,		ct_use);
-	diff |= CT_DIFF_VAL(ID,			ct_id);
-	diff |= CT_DIFF_ADDR(ORIG_SRC,		ct_orig.src);
-	diff |= CT_DIFF_ADDR(ORIG_DST,		ct_orig.dst);
-	diff |= CT_DIFF_VAL(ORIG_SRC_PORT,	ct_orig.proto.port.src);
-	diff |= CT_DIFF_VAL(ORIG_DST_PORT,	ct_orig.proto.port.dst);
-	diff |= CT_DIFF_VAL(ORIG_ICMP_ID,	ct_orig.proto.icmp.id);
-	diff |= CT_DIFF_VAL(ORIG_ICMP_TYPE,	ct_orig.proto.icmp.type);
-	diff |= CT_DIFF_VAL(ORIG_ICMP_CODE,	ct_orig.proto.icmp.code);
-	diff |= CT_DIFF_VAL(ORIG_PACKETS,	ct_orig.packets);
-	diff |= CT_DIFF_VAL(ORIG_BYTES,		ct_orig.bytes);
-	diff |= CT_DIFF_ADDR(REPL_SRC,		ct_repl.src);
-	diff |= CT_DIFF_ADDR(REPL_DST,		ct_repl.dst);
-	diff |= CT_DIFF_VAL(REPL_SRC_PORT,	ct_repl.proto.port.src);
-	diff |= CT_DIFF_VAL(REPL_DST_PORT,	ct_repl.proto.port.dst);
-	diff |= CT_DIFF_VAL(REPL_ICMP_ID,	ct_repl.proto.icmp.id);
-	diff |= CT_DIFF_VAL(REPL_ICMP_TYPE,	ct_repl.proto.icmp.type);
-	diff |= CT_DIFF_VAL(REPL_ICMP_CODE,	ct_repl.proto.icmp.code);
-	diff |= CT_DIFF_VAL(REPL_PACKETS,	ct_repl.packets);
-	diff |= CT_DIFF_VAL(REPL_BYTES,		ct_repl.bytes);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD)
+#define _DIFF_ADDR(ATTR, FIELD)                                                \
+	((flags & LOOSE_COMPARISON) ?                                          \
+		 _DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) :         \
+		 _DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
+	diff |= _DIFF_VAL(CT_ATTR_FAMILY, ct_family);
+	diff |= _DIFF_VAL(CT_ATTR_PROTO, ct_proto);
+	diff |= _DIFF_VAL(CT_ATTR_TCP_STATE, ct_protoinfo.tcp.state);
+	diff |= _DIFF_VAL(CT_ATTR_TIMEOUT, ct_timeout);
+	diff |= _DIFF_VAL(CT_ATTR_MARK, ct_mark);
+	diff |= _DIFF_VAL(CT_ATTR_USE, ct_use);
+	diff |= _DIFF_VAL(CT_ATTR_ID, ct_id);
+	diff |= _DIFF_ADDR(CT_ATTR_ORIG_SRC, ct_orig.src);
+	diff |= _DIFF_ADDR(CT_ATTR_ORIG_DST, ct_orig.dst);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_SRC_PORT, ct_orig.proto.port.src);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_DST_PORT, ct_orig.proto.port.dst);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_ID, ct_orig.proto.icmp.id);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_TYPE, ct_orig.proto.icmp.type);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_ICMP_CODE, ct_orig.proto.icmp.code);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_PACKETS, ct_orig.packets);
+	diff |= _DIFF_VAL(CT_ATTR_ORIG_BYTES, ct_orig.bytes);
+	diff |= _DIFF_ADDR(CT_ATTR_REPL_SRC, ct_repl.src);
+	diff |= _DIFF_ADDR(CT_ATTR_REPL_DST, ct_repl.dst);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_SRC_PORT, ct_repl.proto.port.src);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_DST_PORT, ct_repl.proto.port.dst);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_ID, ct_repl.proto.icmp.id);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_TYPE, ct_repl.proto.icmp.type);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_ICMP_CODE, ct_repl.proto.icmp.code);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_PACKETS, ct_repl.packets);
+	diff |= _DIFF_VAL(CT_ATTR_REPL_BYTES, ct_repl.bytes);
 
 	if (flags & LOOSE_COMPARISON)
-		diff |= CT_DIFF(STATUS, (a->ct_status ^ b->ct_status) &
-					b->ct_status_mask);
+		diff |= _DIFF(CT_ATTR_STATUS, (a->ct_status ^ b->ct_status) &
+						      b->ct_status_mask);
 	else
-		diff |= CT_DIFF(STATUS, a->ct_status != b->ct_status);
-
-#undef CT_DIFF
-#undef CT_DIFF_VAL
-#undef CT_DIFF_ADDR
+		diff |= _DIFF(CT_ATTR_STATUS, a->ct_status != b->ct_status);
+#undef _DIFF
+#undef _DIFF_VAL
+#undef _DIFF_ADDR
 
 	return diff;
 }
diff --git a/lib/netfilter/exp.c b/lib/netfilter/exp.c
index 05a6cdc..b0832d6 100644
--- a/lib/netfilter/exp.c
+++ b/lib/netfilter/exp.c
@@ -14,15 +14,20 @@
  * @{
  */
 
-#include <byteswap.h>
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_conntrack.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/exp.h>
 
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 static struct nl_cache_ops nfnl_exp_ops;
 
 static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
@@ -610,12 +615,12 @@
 	.co_obj_ops		= &exp_obj_ops,
 };
 
-static void __init exp_init(void)
+static void _nl_init exp_init(void)
 {
 	nl_cache_mngt_register(&nfnl_exp_ops);
 }
 
-static void __exit exp_exit(void)
+static void _nl_exit exp_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_exp_ops);
 }
diff --git a/lib/netfilter/exp_obj.c b/lib/netfilter/exp_obj.c
index 21311c9..8b78898 100644
--- a/lib/netfilter/exp_obj.c
+++ b/lib/netfilter/exp_obj.c
@@ -6,16 +6,22 @@
  * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com>
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
-#include <netinet/in.h>
+
 #include <linux/netfilter/nfnetlink_conntrack.h>
 #include <linux/netfilter/nf_conntrack_common.h>
+
 #include <linux/netfilter/nf_conntrack_tcp.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/exp.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 // The 32-bit attribute mask in the common object header isn't
 // big enough to handle all attributes of an expectation.  So
 // we'll for sure specify optional attributes + parent attributes
@@ -309,59 +315,67 @@
 	struct nfnl_exp *b = (struct nfnl_exp *) _b;
 	uint64_t diff = 0;
 
-#define EXP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, EXP_ATTR_##ATTR, a, b, EXPR)
-#define EXP_DIFF_VAL(ATTR, FIELD) EXP_DIFF(ATTR, a->FIELD != b->FIELD)
-#define EXP_DIFF_STRING(ATTR, FIELD) EXP_DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0))
-#define EXP_DIFF_ADDR(ATTR, FIELD) \
-		((flags & LOOSE_COMPARISON) \
-		? EXP_DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) \
-		: EXP_DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
-#define EXP_DIFF_L4PROTO_PORTS(ATTR, FIELD) \
-		EXP_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD)))
-#define EXP_DIFF_L4PROTO_ICMP(ATTR, FIELD) \
-		EXP_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD)))
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD)
+#define _DIFF_STRING(ATTR, FIELD) _DIFF(ATTR, (strcmp(a->FIELD, b->FIELD) != 0))
+#define _DIFF_ADDR(ATTR, FIELD)                                                \
+	((flags & LOOSE_COMPARISON) ?                                          \
+		 _DIFF(ATTR, nl_addr_cmp_prefix(a->FIELD, b->FIELD)) :         \
+		 _DIFF(ATTR, nl_addr_cmp(a->FIELD, b->FIELD)))
+#define _DIFF_L4PROTO_PORTS(ATTR, FIELD)                                       \
+	_DIFF(ATTR, exp_cmp_l4proto_ports(&(a->FIELD), &(b->FIELD)))
+#define _DIFF_L4PROTO_ICMP(ATTR, FIELD)                                        \
+	_DIFF(ATTR, exp_cmp_l4proto_icmp(&(a->FIELD), &(b->FIELD)))
+	diff |= _DIFF_VAL(EXP_ATTR_FAMILY, exp_family);
+	diff |= _DIFF_VAL(EXP_ATTR_TIMEOUT, exp_timeout);
+	diff |= _DIFF_VAL(EXP_ATTR_ID, exp_id);
+	diff |= _DIFF_VAL(EXP_ATTR_ZONE, exp_zone);
+	diff |= _DIFF_VAL(EXP_ATTR_CLASS, exp_class);
+	diff |= _DIFF_VAL(EXP_ATTR_FLAGS, exp_flags);
+	diff |= _DIFF_VAL(EXP_ATTR_NAT_DIR, exp_nat_dir);
 
-		diff |= EXP_DIFF_VAL(FAMILY,			exp_family);
-		diff |= EXP_DIFF_VAL(TIMEOUT,			exp_timeout);
-		diff |= EXP_DIFF_VAL(ID,			exp_id);
-		diff |= EXP_DIFF_VAL(ZONE,			exp_zone);
-		diff |= EXP_DIFF_VAL(CLASS,			exp_class);
-		diff |= EXP_DIFF_VAL(FLAGS,			exp_flags);
-		diff |= EXP_DIFF_VAL(NAT_DIR,			exp_nat_dir);
+	diff |= _DIFF_STRING(EXP_ATTR_FN, exp_fn);
+	diff |= _DIFF_STRING(EXP_ATTR_HELPER_NAME, exp_helper_name);
 
-		diff |= EXP_DIFF_STRING(FN,			exp_fn);
-		diff |= EXP_DIFF_STRING(HELPER_NAME,		exp_helper_name);
+	diff |= _DIFF_ADDR(EXP_ATTR_EXPECT_IP_SRC, exp_expect.src);
+	diff |= _DIFF_ADDR(EXP_ATTR_EXPECT_IP_DST, exp_expect.dst);
+	diff |= _DIFF_VAL(EXP_ATTR_EXPECT_L4PROTO_NUM,
+			  exp_expect.proto.l4protonum);
+	diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_EXPECT_L4PROTO_PORTS,
+				    exp_expect.proto.l4protodata);
+	diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_EXPECT_L4PROTO_ICMP,
+				   exp_expect.proto.l4protodata);
 
-		diff |= EXP_DIFF_ADDR(EXPECT_IP_SRC,			exp_expect.src);
-		diff |= EXP_DIFF_ADDR(EXPECT_IP_DST,			exp_expect.dst);
-		diff |= EXP_DIFF_VAL(EXPECT_L4PROTO_NUM,		exp_expect.proto.l4protonum);
-		diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS,	exp_expect.proto.l4protodata);
-		diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP,	exp_expect.proto.l4protodata);
+	diff |= _DIFF_ADDR(EXP_ATTR_MASTER_IP_SRC, exp_master.src);
+	diff |= _DIFF_ADDR(EXP_ATTR_MASTER_IP_DST, exp_master.dst);
+	diff |= _DIFF_VAL(EXP_ATTR_MASTER_L4PROTO_NUM,
+			  exp_master.proto.l4protonum);
+	diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_MASTER_L4PROTO_PORTS,
+				    exp_master.proto.l4protodata);
+	diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_MASTER_L4PROTO_ICMP,
+				   exp_master.proto.l4protodata);
 
-		diff |= EXP_DIFF_ADDR(MASTER_IP_SRC,			exp_master.src);
-		diff |= EXP_DIFF_ADDR(MASTER_IP_DST,			exp_master.dst);
-		diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM,		exp_master.proto.l4protonum);
-		diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS,	exp_master.proto.l4protodata);
-		diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP,	exp_master.proto.l4protodata);
+	diff |= _DIFF_ADDR(EXP_ATTR_MASK_IP_SRC, exp_mask.src);
+	diff |= _DIFF_ADDR(EXP_ATTR_MASK_IP_DST, exp_mask.dst);
+	diff |= _DIFF_VAL(EXP_ATTR_MASK_L4PROTO_NUM, exp_mask.proto.l4protonum);
+	diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_MASK_L4PROTO_PORTS,
+				    exp_mask.proto.l4protodata);
+	diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_MASK_L4PROTO_ICMP,
+				   exp_mask.proto.l4protodata);
 
-		diff |= EXP_DIFF_ADDR(MASK_IP_SRC,			exp_mask.src);
-		diff |= EXP_DIFF_ADDR(MASK_IP_DST,			exp_mask.dst);
-		diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM,			exp_mask.proto.l4protonum);
-		diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS,	exp_mask.proto.l4protodata);
-		diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP,	exp_mask.proto.l4protodata);
-
-		diff |= EXP_DIFF_ADDR(NAT_IP_SRC,			exp_nat.src);
-		diff |= EXP_DIFF_ADDR(NAT_IP_DST,			exp_nat.dst);
-		diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM,			exp_nat.proto.l4protonum);
-		diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS,	exp_nat.proto.l4protodata);
-		diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP,		exp_nat.proto.l4protodata);
-
-#undef EXP_DIFF
-#undef EXP_DIFF_VAL
-#undef EXP_DIFF_STRING
-#undef EXP_DIFF_ADDR
-#undef EXP_DIFF_L4PROTO_PORTS
-#undef EXP_DIFF_L4PROTO_ICMP
+	diff |= _DIFF_ADDR(EXP_ATTR_NAT_IP_SRC, exp_nat.src);
+	diff |= _DIFF_ADDR(EXP_ATTR_NAT_IP_DST, exp_nat.dst);
+	diff |= _DIFF_VAL(EXP_ATTR_NAT_L4PROTO_NUM, exp_nat.proto.l4protonum);
+	diff |= _DIFF_L4PROTO_PORTS(EXP_ATTR_NAT_L4PROTO_PORTS,
+				    exp_nat.proto.l4protodata);
+	diff |= _DIFF_L4PROTO_ICMP(EXP_ATTR_NAT_L4PROTO_ICMP,
+				   exp_nat.proto.l4protodata);
+#undef _DIFF
+#undef _DIFF_VAL
+#undef _DIFF_STRING
+#undef _DIFF_ADDR
+#undef _DIFF_L4PROTO_PORTS
+#undef _DIFF_L4PROTO_ICMP
 
 	return diff;
 }
diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c
index c14a4ea..7b0abaa 100644
--- a/lib/netfilter/log.c
+++ b/lib/netfilter/log.c
@@ -12,14 +12,19 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_log.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/log.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 /**
  * @name Log Commands
  * @{
@@ -237,12 +242,12 @@
 	},
 };
 
-static void __init log_init(void)
+static void _nl_init log_init(void)
 {
 	nl_cache_mngt_register(&nfnl_log_ops);
 }
 
-static void __exit log_exit(void)
+static void _nl_exit log_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_log_ops);
 }
diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c
index 2b1b125..2ddc06a 100644
--- a/lib/netfilter/log_msg.c
+++ b/lib/netfilter/log_msg.c
@@ -13,14 +13,18 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_log.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/log_msg.h>
-#include <netlink-private/utils.h>
+
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 static struct nla_policy log_msg_policy[NFULA_MAX+1] = {
 	[NFULA_PACKET_HDR]		= {
@@ -244,12 +248,12 @@
 	.co_obj_ops		= &log_msg_obj_ops,
 };
 
-static void __init log_msg_init(void)
+static void _nl_init log_msg_init(void)
 {
 	nl_cache_mngt_register(&nfnl_log_msg_ops);
 }
 
-static void __exit log_msg_exit(void)
+static void _nl_exit log_msg_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_log_msg_ops);
 }
diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c
index 6b26bc5..6b6ff07 100644
--- a/lib/netfilter/log_msg_obj.c
+++ b/lib/netfilter/log_msg_obj.c
@@ -5,10 +5,16 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/netfilter.h>
 #include <netlink/netfilter/log_msg.h>
+#include <netlink/netfilter/ct.h>
+#include <netlink/route/link.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-netfilter.h"
 
 /** @cond SKIP */
 #define LOG_MSG_ATTR_FAMILY		(1UL << 0)
diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c
index e26e5bd..acfe58b 100644
--- a/lib/netfilter/log_obj.c
+++ b/lib/netfilter/log_obj.c
@@ -6,11 +6,29 @@
  * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/log.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /** @cond SKIP */
+struct nfnl_log {
+	NLHDR_COMMON
+
+	uint16_t		log_group;
+	uint8_t			log_copy_mode;
+	uint32_t		log_copy_range;
+	uint32_t		log_flush_timeout;
+	uint32_t		log_alloc_size;
+	uint32_t		log_queue_threshold;
+	uint32_t		log_flags;
+	uint32_t		log_flag_mask;
+};
+
 #define LOG_ATTR_GROUP			(1UL << 0)
 #define LOG_ATTR_COPY_MODE		(1UL << 1)
 #define LOG_ATTR_COPY_RANGE		(1UL << 3)
@@ -237,17 +255,15 @@
 	uint64_t diff = 0;
 
 #define NFNL_LOG_DIFF(ATTR, EXPR) \
-	ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR)
+	ATTR_DIFF(attrs, ATTR, a, b, EXPR)
 #define NFNL_LOG_DIFF_VAL(ATTR, FIELD) \
 	NFNL_LOG_DIFF(ATTR, a->FIELD != b->FIELD)
-
-	diff |= NFNL_LOG_DIFF_VAL(GROUP,		log_group);
-	diff |= NFNL_LOG_DIFF_VAL(COPY_MODE,		log_copy_mode);
-	diff |= NFNL_LOG_DIFF_VAL(COPY_RANGE,		log_copy_range);
-	diff |= NFNL_LOG_DIFF_VAL(FLUSH_TIMEOUT,	log_flush_timeout);
-	diff |= NFNL_LOG_DIFF_VAL(ALLOC_SIZE,		log_alloc_size);
-	diff |= NFNL_LOG_DIFF_VAL(QUEUE_THRESHOLD,	log_queue_threshold);
-
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_GROUP,		log_group);
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_COPY_MODE,		log_copy_mode);
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_COPY_RANGE,		log_copy_range);
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_FLUSH_TIMEOUT,	log_flush_timeout);
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_ALLOC_SIZE,		log_alloc_size);
+	diff |= NFNL_LOG_DIFF_VAL(LOG_ATTR_QUEUE_THRESHOLD,	log_queue_threshold);
 #undef NFNL_LOG_DIFF
 #undef NFNL_LOG_DIFF_VAL
 
diff --git a/lib/netfilter/netfilter.c b/lib/netfilter/netfilter.c
index 616c10c..b8a5d2a 100644
--- a/lib/netfilter/netfilter.c
+++ b/lib/netfilter/netfilter.c
@@ -3,10 +3,14 @@
  * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink/netfilter/netfilter.h>
+#include "nl-default.h"
+
 #include <linux/netfilter.h>
 
+#include <netlink/netfilter/netfilter.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
+
 static const struct trans_tbl nfnl_verdicts[] = {
 	__ADD(NF_DROP,		NF_DROP),
 	__ADD(NF_ACCEPT,	NF_ACCEPT),
diff --git a/lib/netfilter/nfnl.c b/lib/netfilter/nfnl.c
index f18e498..c70827b 100644
--- a/lib/netfilter/nfnl.c
+++ b/lib/netfilter/nfnl.c
@@ -55,12 +55,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink/netlink.h>
-#include <netlink/netfilter/nfnl.h>
+#include "nl-default.h"
 
 #include <linux/netfilter/nfnetlink.h>
 
+#include <netlink/netlink.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/data.h>
+#include <netlink/msg.h>
+
+#include "nl-aux-core/nl-core.h"
+
 /**
  * @name Socket Creating
  * @{
diff --git a/lib/netfilter/nl-netfilter.h b/lib/netfilter/nl-netfilter.h
new file mode 100644
index 0000000..c8a4899
--- /dev/null
+++ b/lib/netfilter/nl-netfilter.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __LIB_NETFILTER_NL_NETFILTER_H__
+#define __LIB_NETFILTER_NL_NETFILTER_H__
+
+#include <netlink/netfilter/ct.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+
+union nfnl_ct_proto {
+	struct {
+		uint16_t src;
+		uint16_t dst;
+	} port;
+	struct {
+		uint16_t id;
+		uint8_t type;
+		uint8_t code;
+	} icmp;
+};
+
+struct nfnl_ct_dir {
+	struct nl_addr *src;
+	struct nl_addr *dst;
+	union nfnl_ct_proto proto;
+	uint64_t packets;
+	uint64_t bytes;
+};
+
+union nfnl_ct_protoinfo {
+	struct {
+		uint8_t state;
+	} tcp;
+};
+
+struct nfnl_ct {
+	NLHDR_COMMON
+
+	uint8_t ct_family;
+	uint8_t ct_proto;
+	union nfnl_ct_protoinfo ct_protoinfo;
+
+	uint32_t ct_status;
+	uint32_t ct_status_mask;
+	uint32_t ct_timeout;
+	uint32_t ct_mark;
+	uint32_t ct_use;
+	uint32_t ct_id;
+	uint16_t ct_zone;
+
+	struct nfnl_ct_dir ct_orig;
+	struct nfnl_ct_dir ct_repl;
+
+	struct nfnl_ct_timestamp ct_tstamp;
+};
+
+union nfnl_exp_protodata {
+	struct {
+		uint16_t src;
+		uint16_t dst;
+	} port;
+	struct {
+		uint16_t id;
+		uint8_t type;
+		uint8_t code;
+	} icmp;
+};
+
+// Allow for different master/expect l4 protocols
+struct nfnl_exp_proto {
+	uint8_t l4protonum;
+	union nfnl_exp_protodata l4protodata;
+};
+
+struct nfnl_exp_dir {
+	struct nl_addr *src;
+	struct nl_addr *dst;
+	struct nfnl_exp_proto proto;
+};
+
+struct nfnl_exp {
+	NLHDR_COMMON
+
+	uint8_t exp_family;
+	uint32_t exp_timeout;
+	uint32_t exp_id;
+	uint16_t exp_zone;
+	uint32_t exp_class;
+	uint32_t exp_flags;
+	char *exp_helper_name;
+	char *exp_fn;
+	uint8_t exp_nat_dir;
+
+	struct nfnl_exp_dir exp_expect;
+	struct nfnl_exp_dir exp_master;
+	struct nfnl_exp_dir exp_mask;
+	struct nfnl_exp_dir exp_nat;
+};
+
+struct nfnl_log_msg {
+	NLHDR_COMMON
+
+	uint8_t log_msg_family;
+	uint8_t log_msg_hook;
+	uint16_t log_msg_hwproto;
+	uint32_t log_msg_mark;
+	struct timeval log_msg_timestamp;
+	uint32_t log_msg_indev;
+	uint32_t log_msg_outdev;
+	uint32_t log_msg_physindev;
+	uint32_t log_msg_physoutdev;
+	uint8_t log_msg_hwaddr[8];
+	int log_msg_hwaddr_len;
+	void *log_msg_payload;
+	int log_msg_payload_len;
+	char *log_msg_prefix;
+	uint32_t log_msg_uid;
+	uint32_t log_msg_gid;
+	uint32_t log_msg_seq;
+	uint32_t log_msg_seq_global;
+	uint16_t log_msg_hwtype;
+	uint16_t log_msg_hwlen;
+	void *log_msg_hwheader;
+	int log_msg_hwheader_len;
+	uint16_t log_msg_vlan_tag;
+	uint16_t log_msg_vlan_proto;
+	uint32_t log_msg_ct_info;
+	struct nfnl_ct *log_msg_ct;
+};
+
+struct nfnl_queue_msg {
+	NLHDR_COMMON
+
+	uint16_t queue_msg_group;
+	uint8_t queue_msg_family;
+	uint8_t queue_msg_hook;
+	uint16_t queue_msg_hwproto;
+	uint32_t queue_msg_packetid;
+	uint32_t queue_msg_mark;
+	struct timeval queue_msg_timestamp;
+	uint32_t queue_msg_indev;
+	uint32_t queue_msg_outdev;
+	uint32_t queue_msg_physindev;
+	uint32_t queue_msg_physoutdev;
+	uint8_t queue_msg_hwaddr[8];
+	int queue_msg_hwaddr_len;
+	void *queue_msg_payload;
+	int queue_msg_payload_len;
+	uint32_t queue_msg_verdict;
+};
+
+#endif /* __LIB_NETFILTER_NL_NETFILTER_H__*/
diff --git a/lib/netfilter/queue.c b/lib/netfilter/queue.c
index 4ce3ad1..b780b0f 100644
--- a/lib/netfilter/queue.c
+++ b/lib/netfilter/queue.c
@@ -10,14 +10,19 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_queue.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/queue.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 struct nl_sock *nfnl_queue_socket_alloc(void)
 {
 	struct nl_sock *nlsk;
@@ -232,12 +237,12 @@
 	},
 };
 
-static void __init nfnl_queue_init(void)
+static void _nl_init nfnl_queue_init(void)
 {
 	nl_cache_mngt_register(&nfnl_queue_ops);
 }
 
-static void __exit nfnl_queue_exit(void)
+static void _nl_exit nfnl_queue_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_queue_ops);
 }
diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c
index 840b5e8..413d180 100644
--- a/lib/netfilter/queue_msg.c
+++ b/lib/netfilter/queue_msg.c
@@ -11,14 +11,19 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <sys/types.h>
+
 #include <linux/netfilter/nfnetlink_queue.h>
 
-#include <netlink-private/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/queue_msg.h>
-#include <netlink-private/utils.h>
+
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 static struct nl_cache_ops nfnl_queue_msg_ops;
 
@@ -290,12 +295,12 @@
 	.co_obj_ops		= &queue_msg_obj_ops,
 };
 
-static void __init nfnl_msg_queue_init(void)
+static void _nl_init nfnl_msg_queue_init(void)
 {
 	nl_cache_mngt_register(&nfnl_queue_msg_ops);
 }
 
-static void __exit nfnl_queue_msg_exit(void)
+static void _nl_exit nfnl_queue_msg_exit(void)
 {
 	nl_cache_mngt_unregister(&nfnl_queue_msg_ops);
 }
diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c
index 251cd90..000669b 100644
--- a/lib/netfilter/queue_msg_obj.c
+++ b/lib/netfilter/queue_msg_obj.c
@@ -3,11 +3,17 @@
  * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/netfilter.h>
+
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/netfilter.h>
 #include <netlink/netfilter/queue_msg.h>
-#include <linux/netfilter.h>
+#include <netlink/route/link.h>
+
+#include "nl-netfilter.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /** @cond SKIP */
 #define QUEUE_MSG_ATTR_GROUP		(1UL << 0)
diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c
index 1ea461d..a6b08a2 100644
--- a/lib/netfilter/queue_obj.c
+++ b/lib/netfilter/queue_obj.c
@@ -10,11 +10,24 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/queue.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /** @cond SKIP */
+struct nfnl_queue {
+	NLHDR_COMMON
+
+	uint16_t		queue_group;
+	uint32_t		queue_maxlen;
+	uint32_t		queue_copy_range;
+	uint8_t			queue_copy_mode;
+};
+
 #define QUEUE_ATTR_GROUP		(1UL << 0)
 #define QUEUE_ATTR_MAXLEN		(1UL << 1)
 #define QUEUE_ATTR_COPY_MODE		(1UL << 2)
@@ -162,18 +175,14 @@
 	struct nfnl_queue *b = (struct nfnl_queue *) _b;
 	uint64_t diff = 0;
 
-#define NFNL_QUEUE_DIFF(ATTR, EXPR) \
-	ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
-#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \
-	NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD)
-
-	diff |= NFNL_QUEUE_DIFF_VAL(GROUP,	queue_group);
-	diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN,	queue_maxlen);
-	diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE,	queue_copy_mode);
-	diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE,	queue_copy_range);
-
-#undef NFNL_QUEUE_DIFF
-#undef NFNL_QUEUE_DIFF_VAL
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+#define _DIFF_VAL(ATTR, FIELD) _DIFF(ATTR, a->FIELD != b->FIELD)
+	diff |= _DIFF_VAL(QUEUE_ATTR_GROUP, queue_group);
+	diff |= _DIFF_VAL(QUEUE_ATTR_MAXLEN, queue_maxlen);
+	diff |= _DIFF_VAL(QUEUE_ATTR_COPY_MODE, queue_copy_mode);
+	diff |= _DIFF_VAL(QUEUE_ATTR_COPY_RANGE, queue_copy_range);
+#undef _DIFF
+#undef _DIFF_VAL
 
 	return diff;
 }
diff --git a/lib/nl-core.h b/lib/nl-core.h
new file mode 100644
index 0000000..42d7629
--- /dev/null
+++ b/lib/nl-core.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2014 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef __LIB_NL_CORE_H__
+#define __LIB_NL_CORE_H__
+
+struct nl_cb
+{
+	nl_recvmsg_msg_cb_t	cb_set[NL_CB_TYPE_MAX+1];
+	void *			cb_args[NL_CB_TYPE_MAX+1];
+
+	nl_recvmsg_err_cb_t	cb_err;
+	void *			cb_err_arg;
+
+	/** May be used to replace nl_recvmsgs with your own implementation
+	 * in all internal calls to nl_recvmsgs. */
+	int			(*cb_recvmsgs_ow)(struct nl_sock *,
+						  struct nl_cb *);
+
+	/** Overwrite internal calls to nl_recv, must return the number of
+	 * octets read and allocate a buffer for the received data. */
+	int			(*cb_recv_ow)(struct nl_sock *,
+					      struct sockaddr_nl *,
+					      unsigned char **,
+					      struct ucred **);
+
+	/** Overwrites internal calls to nl_send, must send the netlink
+	 * message. */
+	int			(*cb_send_ow)(struct nl_sock *,
+					      struct nl_msg *);
+
+	int			cb_refcnt;
+	/** indicates the callback that is currently active */
+	enum nl_cb_type		cb_active;
+};
+
+static inline int nl_cb_call(struct nl_cb *cb, enum nl_cb_type type, struct nl_msg *msg)
+{
+	int ret;
+
+	cb->cb_active = type;
+	ret = cb->cb_set[type](msg, cb->cb_args[type]);
+	cb->cb_active = __NL_CB_TYPE_MAX;
+	return ret;
+}
+
+int _nl_socket_is_local_port_unspecified (struct nl_sock *sk);
+uint32_t _nl_socket_set_local_port_no_release(struct nl_sock *sk, int generate_other);
+
+void _nl_socket_used_ports_release_all(const uint32_t *used_ports);
+void _nl_socket_used_ports_set(uint32_t *used_ports, uint32_t port);
+
+extern int nl_cache_parse(struct nl_cache_ops *, struct sockaddr_nl *,
+			  struct nlmsghdr *, struct nl_parser_param *);
+
+extern void dump_from_ops(struct nl_object *, struct nl_dump_params *);
+
+#endif /* __LIB_NL_CORE_H__ */
diff --git a/lib/nl.c b/lib/nl.c
index 2a2f1eb..7d729a7 100644
--- a/lib/nl.c
+++ b/lib/nl.c
@@ -19,15 +19,20 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/socket.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
+#include <linux/socket.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/handlers.h>
 #include <netlink/msg.h>
 #include <netlink/attr.h>
-#include <linux/socket.h>
+
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 /**
  * @defgroup core_types Data Types
diff --git a/lib/object.c b/lib/object.c
index bef0b6f..9b147d6 100644
--- a/lib/object.c
+++ b/lib/object.c
@@ -21,12 +21,19 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
 #include <netlink/utils.h>
 
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+
 static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
 {
 	if (!obj->ce_ops)
@@ -392,7 +399,7 @@
 	diff = nl_object_diff64(a, b);
 
 	return (diff & ~((uint64_t) 0xFFFFFFFF))
-		? (uint32_t) diff | (1 << 31)
+		? (uint32_t) diff | (((uint32_t ) 1u) << 31)
 		: (uint32_t) diff;
 }
 
diff --git a/lib/route/act.c b/lib/route/act.c
index f7c0a78..670810f 100644
--- a/lib/route/act.c
+++ b/lib/route/act.c
@@ -9,15 +9,20 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/gen_stats.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/link.h>
 #include <netlink/route/action.h>
 
+#include "nl-route.h"
+#include "tc-api.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-route/nl-route.h"
 
 static struct nl_object_ops act_obj_ops;
 static struct nl_cache_ops rtnl_act_ops;
@@ -293,7 +298,7 @@
  * sends the request to the kernel and waits for the next ACK to be
  * received and thus blocks until the request has been processed.
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags)
 {
@@ -387,9 +392,16 @@
 	*head = NULL;
 }
 
+static struct nla_policy tc_act_stats_policy[TCA_STATS_MAX+1] = {
+	[TCA_STATS_BASIC]    	= { .minlen = sizeof(struct gnet_stats_basic) },
+	[TCA_STATS_QUEUE]    	= { .minlen = sizeof(struct gnet_stats_queue) },
+	[TCA_STATS_RATE_EST] 	= { .minlen = sizeof(struct gnet_stats_rate_est) },
+	[TCA_STATS_RATE_EST64] 	= { .minlen = sizeof(struct gnet_stats_rate_est64) },
+};
+
 int rtnl_act_parse(struct rtnl_act **head, struct nlattr *tb)
 {
-	struct rtnl_act *act;
+	_nl_auto_rtnl_act_all struct rtnl_act *tmp_head = NULL;
 	struct rtnl_tc_ops *ops;
 	struct nlattr *tb2[TCA_ACT_MAX + 1];
 	struct nlattr *nla[TCA_ACT_MAX_PRIO + 1];
@@ -402,63 +414,92 @@
 		return err;
 
 	for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
+		_nl_auto_rtnl_act struct rtnl_act *act = NULL;
 		struct rtnl_tc *tc;
 
 		if (nla[i] == NULL)
 			continue;
 
 		act = rtnl_act_alloc();
-		if (!act) {
-			err = -NLE_NOMEM;
-			goto err_free;
-		}
+		if (!act)
+			return -NLE_NOMEM;
+
 		tc = TC_CAST(act);
 		err = nla_parse(tb2, TCA_ACT_MAX, nla_data(nla[i]),
 				nla_len(nla[i]), NULL);
 		if (err < 0)
-			goto err_free;
+			return err;
 
-		if (tb2[TCA_ACT_KIND] == NULL) {
-			err = -NLE_MISSING_ATTR;
-			goto err_free;
-		}
+		if (tb2[TCA_ACT_KIND] == NULL)
+			return -NLE_MISSING_ATTR;
 
 		nla_strlcpy(kind, tb2[TCA_ACT_KIND], sizeof(kind));
 		rtnl_tc_set_kind(tc, kind);
 
 		if (tb2[TCA_ACT_OPTIONS]) {
 			tc->tc_opts = nl_data_alloc_attr(tb2[TCA_ACT_OPTIONS]);
-			if (!tc->tc_opts) {
-				err = -NLE_NOMEM;
-				goto err_free;
-			}
+			if (!tc->tc_opts)
+				return -NLE_NOMEM;
 			tc->ce_mask |= TCA_ATTR_OPTS;
 		}
 
+		if (tb2[TCA_ACT_STATS]) {
+			struct nlattr *tb3[TCA_STATS_MAX + 1];
+
+			err = nla_parse_nested(tb3, TCA_STATS_MAX, tb2[TCA_ACT_STATS],
+					       tc_act_stats_policy);
+			if (err < 0)
+				return err;
+
+			if (tb3[TCA_STATS_BASIC]) {
+				struct gnet_stats_basic bs;
+
+				memcpy(&bs, nla_data(tb3[TCA_STATS_BASIC]),
+				       sizeof(bs));
+				tc->tc_stats[RTNL_TC_BYTES] = bs.bytes;
+				tc->tc_stats[RTNL_TC_PACKETS] = bs.packets;
+			}
+			if (tb3[TCA_STATS_RATE_EST64]) {
+				struct gnet_stats_rate_est64 re;
+
+				memcpy(&re, nla_data(tb3[TCA_STATS_RATE_EST64]),
+				       sizeof(re));
+				tc->tc_stats[RTNL_TC_RATE_BPS] = re.bps;
+				tc->tc_stats[RTNL_TC_RATE_PPS] = re.pps;
+			} else if (tb3[TCA_STATS_RATE_EST]) {
+				struct gnet_stats_rate_est *re;
+
+				re = nla_data(tb3[TCA_STATS_RATE_EST]);
+				tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
+				tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
+			}
+			if (tb3[TCA_STATS_QUEUE]) {
+				struct gnet_stats_queue *q;
+
+				q = nla_data(tb3[TCA_STATS_QUEUE]);
+				tc->tc_stats[RTNL_TC_DROPS] = q->drops;
+				tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
+			}
+		}
+
 		ops = rtnl_tc_get_ops(tc);
 		if (ops && ops->to_msg_parser) {
 			void *data = rtnl_tc_data(tc);
 
-			if (!data) {
-				err = -NLE_NOMEM;
-				goto err_free;
-			}
+			if (!data)
+				return -NLE_NOMEM;
 
 			err = ops->to_msg_parser(tc, data);
 			if (err < 0)
-				goto err_free;
+				return err;
 		}
-		err = rtnl_act_append(head, act);
+		err = _rtnl_act_append_take(&tmp_head, _nl_steal_pointer(&act));
 		if (err < 0)
-			goto err_free;
+			return err;
 	}
+
+	*head = _nl_steal_pointer(&tmp_head);
 	return 0;
-
-err_free:
-	rtnl_act_put (act);
-	rtnl_act_put_all(head);
-
-	return err;
 }
 
 static int rtnl_act_msg_parse(struct nlmsghdr *n, struct rtnl_act **act)
@@ -575,13 +616,13 @@
 	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
 };
 
-static void __init act_init(void)
+static void _nl_init act_init(void)
 {
 	rtnl_tc_type_register(&act_ops);
 	nl_cache_mngt_register(&rtnl_act_ops);
 }
 
-static void __exit act_exit(void)
+static void _nl_exit act_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_act_ops);
 	rtnl_tc_type_unregister(&act_ops);
diff --git a/lib/route/act/gact.c b/lib/route/act/gact.c
index 1a4bacb..2e04c5a 100644
--- a/lib/route/act/gact.c
+++ b/lib/route/act/gact.c
@@ -10,14 +10,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/act/gact.h>
 
+#include "tc-api.h"
+
+struct rtnl_gact {
+	struct tc_gact g_parm;
+};
+
 static struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
 	[TCA_GACT_PARMS]             = { .minlen = sizeof(struct tc_gact) },
 };
@@ -144,12 +149,12 @@
 	},
 };
 
-static void __init gact_init(void)
+static void _nl_init gact_init(void)
 {
 	rtnl_tc_register(&gact_ops);
 }
 
-static void __exit gact_exit(void)
+static void _nl_exit gact_exit(void)
 {
 	rtnl_tc_unregister(&gact_ops);
 }
diff --git a/lib/route/act/mirred.c b/lib/route/act/mirred.c
index 01da134..72ead6b 100644
--- a/lib/route/act/mirred.c
+++ b/lib/route/act/mirred.c
@@ -10,14 +10,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/act/mirred.h>
 
+#include "tc-api.h"
+
+struct rtnl_mirred {
+	struct tc_mirred m_parm;
+};
+
 static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
 	[TCA_MIRRED_PARMS]      = { .minlen = sizeof(struct tc_mirred) },
 };
@@ -204,12 +209,12 @@
 	},
 };
 
-static void __init mirred_init(void)
+static void _nl_init mirred_init(void)
 {
 	rtnl_tc_register(&mirred_ops);
 }
 
-static void __exit mirred_exit(void)
+static void _nl_exit mirred_exit(void)
 {
 	rtnl_tc_unregister(&mirred_ops);
 }
diff --git a/lib/route/act/nat.c b/lib/route/act/nat.c
index 21c4247..ffc9d2b 100644
--- a/lib/route/act/nat.c
+++ b/lib/route/act/nat.c
@@ -10,15 +10,16 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/act/nat.h>
 #include <netlink/route/tc.h>
 
+#include "tc-api.h"
+
 static struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
 	[TCA_NAT_PARMS] = { .minlen = sizeof(struct tc_nat) },
 };
@@ -273,12 +274,12 @@
 	},
 };
 
-static void __init nat_init(void)
+static void _nl_init nat_init(void)
 {
 	rtnl_tc_register(&nat_ops);
 }
 
-static void __exit nat_exit(void)
+static void _nl_exit nat_exit(void)
 {
 	rtnl_tc_unregister(&nat_ops);
 }
diff --git a/lib/route/act/skbedit.c b/lib/route/act/skbedit.c
index 24f57e5..32a3506 100644
--- a/lib/route/act/skbedit.c
+++ b/lib/route/act/skbedit.c
@@ -10,14 +10,24 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/act/skbedit.h>
 
+#include "nl-route.h"
+#include "tc-api.h"
+
+struct rtnl_skbedit {
+	struct tc_skbedit s_parm;
+	uint32_t s_flags;
+	uint32_t s_mark;
+	uint32_t s_prio;
+	uint16_t s_queue_mapping;
+};
+
 static struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
 	[TCA_SKBEDIT_PARMS]             = { .minlen = sizeof(struct tc_skbedit) },
 	[TCA_SKBEDIT_PRIORITY]          = { .type = NLA_U32 },
@@ -261,12 +271,12 @@
 	},
 };
 
-static void __init skbedit_init(void)
+static void _nl_init skbedit_init(void)
 {
 	rtnl_tc_register(&skbedit_ops);
 }
 
-static void __exit skbedit_exit(void)
+static void _nl_exit skbedit_exit(void)
 {
 	rtnl_tc_unregister(&skbedit_ops);
 }
diff --git a/lib/route/act/vlan.c b/lib/route/act/vlan.c
index 3d9fc33..71f16e5 100644
--- a/lib/route/act/vlan.c
+++ b/lib/route/act/vlan.c
@@ -10,14 +10,25 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_act/tc_vlan.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/act/vlan.h>
 
+#include "tc-api.h"
+
+struct rtnl_vlan
+{
+	struct tc_vlan v_parm;
+	uint16_t       v_vid;
+	uint16_t       v_proto;
+	uint8_t        v_prio;
+	uint32_t       v_flags;
+};
 
 #define VLAN_F_VID   (1 << 0)
 #define VLAN_F_PROTO (1 << 1)
@@ -399,12 +410,12 @@
 	},
 };
 
-static void __init vlan_init(void)
+static void _nl_init vlan_init(void)
 {
 	rtnl_tc_register(&vlan_ops);
 }
 
-static void __exit vlan_exit(void)
+static void _nl_exit vlan_exit(void)
 {
 	rtnl_tc_unregister(&vlan_ops);
 }
diff --git a/lib/route/addr.c b/lib/route/addr.c
index 2873449..1f72c53 100644
--- a/lib/route/addr.c
+++ b/lib/route/addr.c
@@ -100,7 +100,8 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/addr.h>
@@ -108,7 +109,47 @@
 #include <netlink/route/link.h>
 #include <netlink/utils.h>
 
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 /** @cond SKIP */
+struct rtnl_addr_cacheinfo {
+	/* Preferred lifetime in seconds, ticking from when the message gets constructed */
+	uint32_t aci_prefered;
+
+	/* Valid lifetime in seconds, ticking from when the message gets constructed */
+	uint32_t aci_valid;
+
+	/* Timestamp of creation in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
+	uint32_t aci_cstamp;
+
+	/* Timestamp of last update in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
+	uint32_t aci_tstamp;
+};
+
+struct rtnl_addr {
+	NLHDR_COMMON
+
+	uint8_t a_family;
+	uint8_t a_prefixlen;
+	uint8_t a_scope;
+	uint32_t a_flags;
+	uint32_t a_ifindex;
+
+	struct nl_addr *a_peer;
+	struct nl_addr *a_local;
+	struct nl_addr *a_bcast;
+	struct nl_addr *a_anycast;
+	struct nl_addr *a_multicast;
+
+	struct rtnl_addr_cacheinfo a_cacheinfo;
+
+	char a_label[IFNAMSIZ];
+	uint32_t a_flag_mask;
+	struct rtnl_link *a_link;
+};
+
 #define ADDR_ATTR_FAMILY	0x0001
 #define ADDR_ATTR_PREFIXLEN	0x0002
 #define ADDR_ATTR_FLAGS		0x0004
@@ -493,41 +534,40 @@
 	struct rtnl_addr *b = (struct rtnl_addr *) _b;
 	uint64_t diff = 0;
 
-#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= ADDR_DIFF(IFINDEX,	a->a_ifindex != b->a_ifindex);
-	diff |= ADDR_DIFF(FAMILY,	a->a_family != b->a_family);
-	diff |= ADDR_DIFF(SCOPE,	a->a_scope != b->a_scope);
-	diff |= ADDR_DIFF(LABEL,	strcmp(a->a_label, b->a_label));
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(ADDR_ATTR_IFINDEX, a->a_ifindex != b->a_ifindex);
+	diff |= _DIFF(ADDR_ATTR_FAMILY, a->a_family != b->a_family);
+	diff |= _DIFF(ADDR_ATTR_SCOPE, a->a_scope != b->a_scope);
+	diff |= _DIFF(ADDR_ATTR_LABEL, strcmp(a->a_label, b->a_label));
 	if (attrs & ADDR_ATTR_PEER) {
-		if (   (flags & ID_COMPARISON)
-		    && a->a_family == AF_INET
-		    && b->a_family == AF_INET
-		    && a->a_peer
-		    && b->a_peer
-		    && a->a_prefixlen == b->a_prefixlen) {
+		if ((flags & ID_COMPARISON) && a->a_family == AF_INET &&
+		    b->a_family == AF_INET && a->a_peer && b->a_peer &&
+		    a->a_prefixlen == b->a_prefixlen) {
 			/* when comparing two IPv4 addresses for id-equality, the network part
 			 * of the PEER address shall be compared.
 			 */
-			diff |= ADDR_DIFF(PEER, nl_addr_cmp_prefix(a->a_peer, b->a_peer));
+			diff |= _DIFF(ADDR_ATTR_PEER,
+				      nl_addr_cmp_prefix(a->a_peer, b->a_peer));
 		} else
-			diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer));
+			diff |= _DIFF(ADDR_ATTR_PEER,
+				      nl_addr_cmp(a->a_peer, b->a_peer));
 	}
-	diff |= ADDR_DIFF(LOCAL,	nl_addr_cmp(a->a_local, b->a_local));
-	diff |= ADDR_DIFF(MULTICAST,	nl_addr_cmp(a->a_multicast,
-						    b->a_multicast));
-	diff |= ADDR_DIFF(BROADCAST,	nl_addr_cmp(a->a_bcast, b->a_bcast));
-	diff |= ADDR_DIFF(ANYCAST,	nl_addr_cmp(a->a_anycast, b->a_anycast));
-	diff |= ADDR_DIFF(CACHEINFO,    memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
-	                                       sizeof (a->a_cacheinfo)));
+	diff |= _DIFF(ADDR_ATTR_LOCAL, nl_addr_cmp(a->a_local, b->a_local));
+	diff |= _DIFF(ADDR_ATTR_MULTICAST,
+		      nl_addr_cmp(a->a_multicast, b->a_multicast));
+	diff |= _DIFF(ADDR_ATTR_BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
+	diff |= _DIFF(ADDR_ATTR_ANYCAST,
+		      nl_addr_cmp(a->a_anycast, b->a_anycast));
+	diff |= _DIFF(ADDR_ATTR_CACHEINFO,
+		      memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
+			     sizeof(a->a_cacheinfo)));
 
 	if (flags & LOOSE_COMPARISON)
-		diff |= ADDR_DIFF(FLAGS,
-				  (a->a_flags ^ b->a_flags) & b->a_flag_mask);
+		diff |= _DIFF(ADDR_ATTR_FLAGS,
+			      (a->a_flags ^ b->a_flags) & b->a_flag_mask);
 	else
-		diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags);
-
-#undef ADDR_DIFF
+		diff |= _DIFF(ADDR_ATTR_FLAGS, a->a_flags != b->a_flags);
+#undef _DIFF
 
 	return diff;
 }
@@ -743,7 +783,7 @@
  *
  * @see rtnl_addr_build_add_request()
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
 {
@@ -815,7 +855,7 @@
  *
  * @see rtnl_addr_build_delete_request();
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
 {
@@ -1198,12 +1238,12 @@
 	.co_obj_ops		= &addr_obj_ops,
 };
 
-static void __init addr_init(void)
+static void _nl_init addr_init(void)
 {
 	nl_cache_mngt_register(&rtnl_addr_ops);
 }
 
-static void __exit addr_exit(void)
+static void _nl_exit addr_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_addr_ops);
 }
diff --git a/lib/route/class.c b/lib/route/class.c
index 76cfac9..29ba809 100644
--- a/lib/route/class.c
+++ b/lib/route/class.c
@@ -9,15 +9,21 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/class.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/classifier.h>
 #include <netlink/utils.h>
 
+#include "nl-route.h"
+#include "tc-api.h"
+
+struct rtnl_class {
+	NL_TC_GENERIC(c);
+};
+
 static struct nl_cache_ops rtnl_class_ops;
 static struct nl_object_ops class_obj_ops;
 
@@ -485,13 +491,13 @@
 	.co_obj_ops		= &class_obj_ops,
 };
 
-static void __init class_init(void)
+static void _nl_init class_init(void)
 {
 	rtnl_tc_type_register(&class_ops);
 	nl_cache_mngt_register(&rtnl_class_ops);
 }
 
-static void __exit class_exit(void)
+static void _nl_exit class_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_class_ops);
 	rtnl_tc_type_unregister(&class_ops);
diff --git a/lib/route/classid.c b/lib/route/classid.c
index 350962a..f5a75f0 100644
--- a/lib/route/classid.c
+++ b/lib/route/classid.c
@@ -9,12 +9,18 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <sys/stat.h>
+#include <search.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/tc.h>
 
+#include "nl-route.h"
+#include "nl-aux-core/nl-core.h"
+
 struct classid_map
 {
 	uint32_t		classid;
@@ -427,7 +433,7 @@
 
 /** @} */
 
-static void __init classid_init(void)
+static void _nl_init classid_init(void)
 {
 	int err, i;
 
@@ -444,7 +450,7 @@
 	free(map);
 }
 
-static void __exit classid_exit(void)
+static void _nl_exit classid_exit(void)
 {
 	tdestroy(id_root, free_map);
 }
diff --git a/lib/route/cls.c b/lib/route/cls.c
index 8583103..8f970b1 100644
--- a/lib/route/cls.c
+++ b/lib/route/cls.c
@@ -9,15 +9,25 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/ethtool.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/link.h>
 
+#include "nl-route.h"
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_cls {
+	NL_TC_GENERIC(c);
+	uint16_t c_prio;
+	uint16_t c_protocol;
+};
+
 #define CLS_ATTR_PRIO		(TCA_ATTR_MAX << 1)
 #define CLS_ATTR_PROTOCOL	(TCA_ATTR_MAX << 2)
 /** @endcond */
@@ -215,7 +225,7 @@
  * sends the request to the kernel and waits for the next ACK to be
  * received and thus blocks until the request has been processed.
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
 {
@@ -516,13 +526,13 @@
 	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
 };
 
-static void __init cls_init(void)
+static void _nl_init cls_init(void)
 {
 	rtnl_tc_type_register(&cls_ops);
 	nl_cache_mngt_register(&rtnl_cls_ops);
 }
 
-static void __exit cls_exit(void)
+static void _nl_exit cls_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_cls_ops);
 	rtnl_tc_type_unregister(&cls_ops);
diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c
index 93bf75d..dc19256 100644
--- a/lib/route/cls/basic.c
+++ b/lib/route/cls/basic.c
@@ -16,15 +16,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/action.h>
 #include <netlink/route/cls/basic.h>
 #include <netlink/route/cls/ematch.h>
 
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
+
 struct rtnl_basic
 {
 	uint32_t			b_target;
@@ -222,12 +224,10 @@
 	if (!(b = rtnl_tc_data(TC_CAST(cls))))
 		return -NLE_NOMEM;
 
-	b->b_mask |= BASIC_ATTR_ACTION;
-	if ((err = rtnl_act_append(&b->b_act, act)))
+	if ((err = _rtnl_act_append_get(&b->b_act, act)) < 0)
 		return err;
 
-	/* In case user frees it */
-	rtnl_act_get(act);
+	b->b_mask |= BASIC_ATTR_ACTION;
 	return 0;
 }
 
@@ -282,12 +282,12 @@
 	},
 };
 
-static void __init basic_init(void)
+static void _nl_init basic_init(void)
 {
 	rtnl_tc_register(&basic_ops);
 }
 
-static void __exit basic_exit(void)
+static void _nl_exit basic_exit(void)
 {
 	rtnl_tc_unregister(&basic_ops);
 }
diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c
index ff993d1..3534281 100644
--- a/lib/route/cls/cgroup.c
+++ b/lib/route/cls/cgroup.c
@@ -10,17 +10,23 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/cgroup.h>
 #include <netlink/route/cls/ematch.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_cgroup {
+	struct rtnl_ematch_tree *cg_ematch;
+	int cg_mask;
+};
+
 #define CGROUP_ATTR_EMATCH      0x001
 /** @endcond */
 
@@ -180,12 +186,12 @@
 	},
 };
 
-static void __init cgroup_init(void)
+static void _nl_init cgroup_init(void)
 {
 	rtnl_tc_register(&cgroup_ops);
 }
 
-static void __exit cgroup_exit(void)
+static void _nl_exit cgroup_exit(void)
 {
 	rtnl_tc_unregister(&cgroup_ops);
 }
diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c
index 9052030..5a5a210 100644
--- a/lib/route/cls/ematch.c
+++ b/lib/route/cls/ematch.c
@@ -10,13 +10,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/ematch.h>
 #include <netlink/route/cls/ematch/cmp.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
+
+#include "nl-route.h"
+#include "nl-aux-core/nl-core.h"
 
 #include "ematch_syntax.h"
 #include "ematch_grammar.h"
diff --git a/lib/route/cls/ematch/cmp.c b/lib/route/cls/ematch/cmp.c
index f575866..9feb2e5 100644
--- a/lib/route/cls/ematch/cmp.c
+++ b/lib/route/cls/ematch/cmp.c
@@ -10,12 +10,13 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/cls/ematch.h>
 #include <netlink/route/cls/ematch/cmp.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
 
 void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg)
 {
@@ -80,7 +81,7 @@
 	.eo_dump	= cmp_dump,
 };
 
-static void __init cmp_init(void)
+static void _nl_init cmp_init(void)
 {
 	rtnl_ematch_register(&cmp_ops);
 }
diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c
index b23169b..ea2d166 100644
--- a/lib/route/cls/ematch/container.c
+++ b/lib/route/cls/ematch/container.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/route/cls/ematch.h>
 
+#include "nl-route.h"
+
 static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused)))
 {
 	/*
@@ -35,7 +37,7 @@
 	.eo_fill	= container_fill,
 };
 
-static void __init container_init(void)
+static void _nl_init container_init(void)
 {
 	rtnl_ematch_register(&container_ops);
 }
diff --git a/lib/route/cls/ematch/meta.c b/lib/route/cls/ematch/meta.c
index 3f63cde..2c884dc 100644
--- a/lib/route/cls/ematch/meta.c
+++ b/lib/route/cls/ematch/meta.c
@@ -10,12 +10,15 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_meta.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/cls/ematch.h>
 #include <netlink/route/cls/ematch/meta.h>
-#include <linux/tc_ematch/tc_em_meta.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
 
 struct rtnl_meta_value
 {
@@ -322,7 +325,7 @@
 	.eo_free	= meta_free,
 };
 
-static void __init meta_init(void)
+static void _nl_init meta_init(void)
 {
 	rtnl_ematch_register(&meta_ops);
 }
diff --git a/lib/route/cls/ematch/nbyte.c b/lib/route/cls/ematch/nbyte.c
index 735dfc8..d0ab84b 100644
--- a/lib/route/cls/ematch/nbyte.c
+++ b/lib/route/cls/ematch/nbyte.c
@@ -10,12 +10,13 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_nbyte.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/cls/ematch.h>
 #include <netlink/route/cls/ematch/nbyte.h>
-#include <linux/tc_ematch/tc_em_nbyte.h>
 
 struct nbyte_data
 {
@@ -126,7 +127,7 @@
 	.eo_free	= nbyte_free,
 };
 
-static void __init nbyte_init(void)
+static void _nl_init nbyte_init(void)
 {
 	rtnl_ematch_register(&nbyte_ops);
 }
diff --git a/lib/route/cls/ematch/text.c b/lib/route/cls/ematch/text.c
index b524833..d7a233f 100644
--- a/lib/route/cls/ematch/text.c
+++ b/lib/route/cls/ematch/text.c
@@ -10,13 +10,13 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_text.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/cls/ematch.h>
 #include <netlink/route/cls/ematch/text.h>
-#include <linux/tc_ematch/tc_em_text.h>
 
 struct text_data
 {
@@ -171,7 +171,7 @@
 	.eo_free	= text_free,
 };
 
-static void __init text_init(void)
+static void _nl_init text_init(void)
 {
 	rtnl_ematch_register(&text_ops);
 }
diff --git a/lib/route/cls/ematch_grammar.l b/lib/route/cls/ematch_grammar.l
index 4f57951..1035079 100644
--- a/lib/route/cls/ematch_grammar.l
+++ b/lib/route/cls/ematch_grammar.l
@@ -4,12 +4,14 @@
  */
 
 %{
- #include <netlink-private/netlink.h>
- #include <netlink-private/tc.h>
+ #include <linux/tc_ematch/tc_em_cmp.h>
+
  #include <netlink/netlink.h>
  #include <netlink/route/cls/ematch.h>
  #include <netlink/route/cls/ematch/cmp.h>
- #include <linux/tc_ematch/tc_em_cmp.h>
+
+ #include "nl-route.h"
+
  #include "ematch_syntax.h"
 
  int ematch_get_column(yyscan_t);
diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y
index 0c89603..961ee43 100644
--- a/lib/route/cls/ematch_syntax.y
+++ b/lib/route/cls/ematch_syntax.y
@@ -4,8 +4,10 @@
  */
 
 %{
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include <linux/tc_ematch/tc_em_meta.h>
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/pktloc.h>
@@ -14,8 +16,8 @@
 #include <netlink/route/cls/ematch/nbyte.h>
 #include <netlink/route/cls/ematch/text.h>
 #include <netlink/route/cls/ematch/meta.h>
-#include <linux/tc_ematch/tc_em_meta.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
+
+#include "nl-route.h"
 
 #define META_ALLOC rtnl_meta_value_alloc_id
 #define META_ID(name) TCF_META_ID_##name
@@ -23,6 +25,16 @@
 #define META_VAR TCF_META_TYPE_VAR
 %}
 
+%code requires {
+
+struct ematch_quoted {
+	char *	data;
+	size_t	len;
+	int	index;
+};
+
+}
+
 %error-verbose
 %define api.pure
 %name-prefix "ematch_"
@@ -406,7 +418,7 @@
 			if (nl_addr_parse($1, AF_UNSPEC, &addr) == 0) {
 				$$.len = nl_addr_get_len(addr);
 
-				$$.index = min_t(int, $$.len, nl_addr_get_prefixlen(addr)/8);
+				$$.index = _NL_MIN($$.len, nl_addr_get_prefixlen(addr)/8);
 
 				if (!($$.data = calloc(1, $$.len))) {
 					nl_addr_put(addr);
diff --git a/lib/route/cls/flower.c b/lib/route/cls/flower.c
index 11bd709..56f24c3 100644
--- a/lib/route/cls/flower.c
+++ b/lib/route/cls/flower.c
@@ -3,18 +3,41 @@
  * Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/ethtool.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/action.h>
 #include <netlink/route/cls/flower.h>
 
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
 
 /** @cond SKIP */
+struct rtnl_flower {
+	struct rtnl_act *cf_act;
+	int cf_mask;
+	uint32_t cf_flags;
+	uint16_t cf_proto;
+	uint16_t cf_vlan_id;
+	uint16_t cf_vlan_ethtype;
+	uint8_t cf_vlan_prio;
+	uint8_t cf_src_mac[ETH_ALEN];
+	uint8_t cf_src_mac_mask[ETH_ALEN];
+	uint8_t cf_dst_mac[ETH_ALEN];
+	uint8_t cf_dst_mac_mask[ETH_ALEN];
+	in_addr_t cf_ipv4_src;
+	in_addr_t cf_ipv4_src_mask;
+	in_addr_t cf_ipv4_dst;
+	in_addr_t cf_ipv4_dst_mask;
+	uint8_t cf_ip_dscp;
+	uint8_t cf_ip_dscp_mask;
+};
+
 #define FLOWER_ATTR_FLAGS         (1 << 0)
 #define FLOWER_ATTR_ACTION        (1 << 1)
 #define FLOWER_ATTR_VLAN_ID       (1 << 2)
@@ -787,6 +810,7 @@
 int rtnl_flower_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
 {
 	struct rtnl_flower *f;
+	int err;
 
 	if (!act)
 		return 0;
@@ -794,10 +818,11 @@
 	if (!(f = rtnl_tc_data(TC_CAST(cls))))
 		return -NLE_NOMEM;
 
-	f->cf_mask |= FLOWER_ATTR_ACTION;
+	if ((err = _rtnl_act_append_get(&f->cf_act, act)) < 0)
+		return err;
 
-	rtnl_act_get(act);
-	return rtnl_act_append(&f->cf_act, act);
+	f->cf_mask |= FLOWER_ATTR_ACTION;
+	return 0;
 }
 
 /**
@@ -885,12 +910,12 @@
 	},
 };
 
-static void __init flower_init(void)
+static void _nl_init flower_init(void)
 {
 	rtnl_tc_register(&flower_ops);
 }
 
-static void __exit flower_exit(void)
+static void _nl_exit flower_exit(void)
 {
 	rtnl_tc_unregister(&flower_ops);
 }
diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c
index 2952efc..01be33f 100644
--- a/lib/route/cls/fw.c
+++ b/lib/route/cls/fw.c
@@ -12,14 +12,24 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/fw.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_fw {
+	uint32_t cf_classid;
+	struct nl_data *cf_act;
+	struct nl_data *cf_police;
+	char cf_indev[IFNAMSIZ];
+	uint32_t cf_fwmask;
+	int cf_mask;
+};
+
 #define FW_ATTR_CLASSID      0x001
 #define FW_ATTR_ACTION       0x002
 #define FW_ATTR_POLICE       0x004
@@ -203,12 +213,12 @@
 	},
 };
 
-static void __init fw_init(void)
+static void _nl_init fw_init(void)
 {
 	rtnl_tc_register(&fw_ops);
 }
 
-static void __exit fw_exit(void)
+static void _nl_exit fw_exit(void)
 {
 	rtnl_tc_unregister(&fw_ops);
 }
diff --git a/lib/route/cls/mall.c b/lib/route/cls/mall.c
index ded08c6..030eaa8 100644
--- a/lib/route/cls/mall.c
+++ b/lib/route/cls/mall.c
@@ -10,16 +10,24 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/matchall.h>
 #include <netlink/route/action.h>
 
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
+
+struct rtnl_mall {
+	uint32_t m_classid;
+	uint32_t m_flags;
+	struct rtnl_act *m_act;
+	int m_mask;
+};
 
 #define MALL_ATTR_CLASSID 0x01
 #define MALL_ATTR_FLAGS   0x02
@@ -100,12 +108,10 @@
 	if (!(mall = rtnl_tc_data(TC_CAST(cls))))
 		return -NLE_NOMEM;
 
-	mall->m_mask |= MALL_ATTR_ACTION;
-	err = rtnl_act_append(&mall->m_act, act);
-	if (err < 0)
-	        return err;
+	if ((err = _rtnl_act_append_get(&mall->m_act, act)) < 0)
+		return err;
 
-	rtnl_act_get(act);
+	mall->m_mask |= MALL_ATTR_ACTION;
 	return 0;
 }
 
@@ -238,7 +244,7 @@
 			if (!new)
 				return -NLE_NOMEM;
 
-			err = rtnl_act_append(&dst->m_act, new);
+			err = _rtnl_act_append_take(&dst->m_act, new);
 			if (err < 0)
 				return err;
 
@@ -288,12 +294,12 @@
 	},
 };
 
-static void __init mall_init(void)
+static void _nl_init mall_init(void)
 {
 	rtnl_tc_register(&mall_ops);
 }
 
-static void __exit mall_exit(void)
+static void _nl_exit mall_exit(void)
 {
 	rtnl_tc_unregister(&mall_ops);
 }
diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c
index f7771ae..e7e3926 100644
--- a/lib/route/cls/police.c
+++ b/lib/route/cls/police.c
@@ -3,14 +3,15 @@
  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/police.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /**
  * @name Policer Type
  * @{
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 56952fb..52f6e31 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -12,19 +12,33 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/cls/u32.h>
 #include <netlink/route/action.h>
 
-#include "netlink-private/utils.h"
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
 
 /** @cond SKIP */
+struct rtnl_u32 {
+	uint32_t cu_divisor;
+	uint32_t cu_hash;
+	uint32_t cu_classid;
+	uint32_t cu_link;
+	struct nl_data *cu_pcnt;
+	struct nl_data *cu_selector;
+	struct nl_data *cu_mark;
+	struct rtnl_act *cu_act;
+	struct nl_data *cu_police;
+	char cu_indev[IFNAMSIZ];
+	int cu_mask;
+};
+
 #define U32_ATTR_DIVISOR      0x001
 #define U32_ATTR_HASH         0x002
 #define U32_ATTR_CLASSID      0x004
@@ -598,12 +612,10 @@
 	if (!(u = rtnl_tc_data(TC_CAST(cls))))
 		return -NLE_NOMEM;
 
-	u->cu_mask |= U32_ATTR_ACTION;
-	if ((err = rtnl_act_append(&u->cu_act, act)))
+	if ((err = _rtnl_act_append_get(&u->cu_act, act)) < 0)
 		return err;
 
-	/* In case user frees it */
-	rtnl_act_get(act);
+	u->cu_mask |= U32_ATTR_ACTION;
 	return 0;
 }
 
@@ -885,12 +897,12 @@
 	},
 };
 
-static void __init u32_init(void)
+static void _nl_init u32_init(void)
 {
 	rtnl_tc_register(&u32_ops);
 }
 
-static void __exit u32_exit(void)
+static void _nl_exit u32_exit(void)
 {
 	rtnl_tc_unregister(&u32_ops);
 }
diff --git a/include/netlink-private/route/link/sriov.h b/lib/route/link-sriov.h
similarity index 91%
rename from include/netlink-private/route/link/sriov.h
rename to lib/route/link-sriov.h
index f7c027a..6493a57 100644
--- a/include/netlink-private/route/link/sriov.h
+++ b/lib/route/link-sriov.h
@@ -10,10 +10,6 @@
 #include <netlink/netlink.h>
 #include <netlink/route/link/sriov.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 extern int rtnl_link_sriov_clone(struct rtnl_link *, struct rtnl_link *);
 extern void rtnl_link_sriov_dump_details(struct rtnl_link *, struct nl_dump_params *);
 extern void rtnl_link_sriov_dump_stats(struct rtnl_link *, struct nl_dump_params *);
@@ -21,8 +17,4 @@
 extern void rtnl_link_sriov_free_data(struct rtnl_link *);
 extern int rtnl_link_sriov_parse_vflist(struct rtnl_link *, struct nlattr **);
 
-#ifdef __cplusplus
-}
-#endif
-
 #endif
diff --git a/lib/route/link.c b/lib/route/link.c
index df8ea5b..ce1355b 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -12,7 +12,10 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_arp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
@@ -21,9 +24,13 @@
 #include <netlink/data.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink-private/route/link/sriov.h>
-#include <netlink-private/utils.h>
+
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-route.h"
+#include "link-sriov.h"
+#include "link/link-api.h"
 
 /** @cond SKIP */
 #define LINK_ATTR_MTU		(1 <<  0)
@@ -115,7 +122,7 @@
 	struct rtnl_link_af_ops *ops;
 
 	ops = rtnl_link_af_ops_lookup(af_type);
-	if (ops && ops->ao_override_rtm(changes))
+	if (ops && ops->ao_override_rtm && ops->ao_override_rtm(changes))
 		return RTM_SETLINK;
 
 	return RTM_NEWLINK;
@@ -1090,7 +1097,7 @@
 	struct link_hash_key {
 		uint32_t	l_index;
 		uint32_t	l_family;
-	} __attribute__((packed)) lkey;
+	} _nl_packed lkey;
 
 	lkey_sz = sizeof(lkey);
 	lkey.l_index = link->l_index;
@@ -1111,34 +1118,37 @@
 	struct rtnl_link *b = (struct rtnl_link *) _b;
 	uint64_t diff = 0;
 
-#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= LINK_DIFF(IFINDEX,	a->l_index != b->l_index);
-	diff |= LINK_DIFF(MTU,		a->l_mtu != b->l_mtu);
-	diff |= LINK_DIFF(LINK,		a->l_link != b->l_link);
-	diff |= LINK_DIFF(LINK_NETNSID, a->l_link_netnsid != b->l_link_netnsid);
-	diff |= LINK_DIFF(TXQLEN,	a->l_txqlen != b->l_txqlen);
-	diff |= LINK_DIFF(WEIGHT,	a->l_weight != b->l_weight);
-	diff |= LINK_DIFF(MASTER,	a->l_master != b->l_master);
-	diff |= LINK_DIFF(FAMILY,	a->l_family != b->l_family);
-	diff |= LINK_DIFF(OPERSTATE,	a->l_operstate != b->l_operstate);
-	diff |= LINK_DIFF(LINKMODE,	a->l_linkmode != b->l_linkmode);
-	diff |= LINK_DIFF(QDISC,	strcmp(a->l_qdisc, b->l_qdisc));
-	diff |= LINK_DIFF(IFNAME,	strcmp(a->l_name, b->l_name));
-	diff |= LINK_DIFF(ADDR,		nl_addr_cmp(a->l_addr, b->l_addr));
-	diff |= LINK_DIFF(BRD,		nl_addr_cmp(a->l_bcast, b->l_bcast));
-	diff |= LINK_DIFF(IFALIAS,	strcmp(a->l_ifalias, b->l_ifalias));
-	diff |= LINK_DIFF(NUM_VF,	a->l_num_vf != b->l_num_vf);
-	diff |= LINK_DIFF(PROMISCUITY,	a->l_promiscuity != b->l_promiscuity);
-	diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues);
-	diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues);
-	diff |= LINK_DIFF(GROUP,	a->l_group != b->l_group);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(LINK_ATTR_IFINDEX, a->l_index != b->l_index);
+	diff |= _DIFF(LINK_ATTR_MTU, a->l_mtu != b->l_mtu);
+	diff |= _DIFF(LINK_ATTR_LINK, a->l_link != b->l_link);
+	diff |= _DIFF(LINK_ATTR_LINK_NETNSID,
+		      a->l_link_netnsid != b->l_link_netnsid);
+	diff |= _DIFF(LINK_ATTR_TXQLEN, a->l_txqlen != b->l_txqlen);
+	diff |= _DIFF(LINK_ATTR_WEIGHT, a->l_weight != b->l_weight);
+	diff |= _DIFF(LINK_ATTR_MASTER, a->l_master != b->l_master);
+	diff |= _DIFF(LINK_ATTR_FAMILY, a->l_family != b->l_family);
+	diff |= _DIFF(LINK_ATTR_OPERSTATE, a->l_operstate != b->l_operstate);
+	diff |= _DIFF(LINK_ATTR_LINKMODE, a->l_linkmode != b->l_linkmode);
+	diff |= _DIFF(LINK_ATTR_QDISC, strcmp(a->l_qdisc, b->l_qdisc));
+	diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name));
+	diff |= _DIFF(LINK_ATTR_ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
+	diff |= _DIFF(LINK_ATTR_BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
+	diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
+	diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf);
+	diff |= _DIFF(LINK_ATTR_PROMISCUITY,
+		      a->l_promiscuity != b->l_promiscuity);
+	diff |= _DIFF(LINK_ATTR_NUM_TX_QUEUES,
+		      a->l_num_tx_queues != b->l_num_tx_queues);
+	diff |= _DIFF(LINK_ATTR_NUM_RX_QUEUES,
+		      a->l_num_rx_queues != b->l_num_rx_queues);
+	diff |= _DIFF(LINK_ATTR_GROUP, a->l_group != b->l_group);
 
 	if (flags & LOOSE_COMPARISON)
-		diff |= LINK_DIFF(FLAGS,
+		diff |= _DIFF(LINK_ATTR_FLAGS,
 				  (a->l_flags ^ b->l_flags) & b->l_flag_mask);
 	else
-		diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
+		diff |= _DIFF(LINK_ATTR_FLAGS, a->l_flags != b->l_flags);
 
 	/*
 	 * Compare LINK_ATTR_PROTINFO af_data
@@ -1148,15 +1158,15 @@
 			goto protinfo_mismatch;
 	}
 
-	diff |= LINK_DIFF(LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0);
+	diff |= _DIFF(LINK_ATTR_LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0);
 out:
 	return diff;
 
 protinfo_mismatch:
-	diff |= LINK_DIFF(PROTINFO, 1);
+	diff |= _DIFF(LINK_ATTR_PROTINFO, 1);
 	goto out;
 
-#undef LINK_DIFF
+#undef _DIFF
 }
 
 static const struct trans_tbl link_attrs[] = {
@@ -1913,7 +1923,7 @@
 }
 
 /**
- * Return a link object reference
+ * Release a link object reference
  * @arg link		Link object
  */
 void rtnl_link_put(struct rtnl_link *link)
@@ -3204,12 +3214,12 @@
 	.co_obj_ops		= &link_obj_ops,
 };
 
-static void __init link_init(void)
+static void _nl_init link_init(void)
 {
 	nl_cache_mngt_register(&rtnl_link_ops);
 }
 
-static void __exit link_exit(void)
+static void _nl_exit link_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_link_ops);
 }
diff --git a/lib/route/link/api.c b/lib/route/link/api.c
index cd2c42b..abc9e6a 100644
--- a/lib/route/link/api.c
+++ b/lib/route/link/api.c
@@ -19,12 +19,12 @@
  * 	.io_free		= vlan_free,
  * };
  *
- * static void __init vlan_init(void)
+ * static void _nl_init vlan_init(void)
  * {
  * 	rtnl_link_register_info(&vlan_info_ops);
  * }
  *
- * static void __exit vlan_exit(void)
+ * static void _nl_exit vlan_exit(void)
  * {
  * 	rtnl_link_unregister_info(&vlan_info_ops);
  * }
@@ -33,11 +33,14 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/link.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 static NL_LIST_HEAD(info_ops);
 
diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c
index 90e6470..63fd474 100644
--- a/lib/route/link/bonding.c
+++ b/lib/route/link/bonding.c
@@ -14,10 +14,186 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/route/link/bonding.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+
+#define BOND_HAS_MODE		(1 << 0)
+#define BOND_HAS_ACTIVE_SLAVE	(1 << 1)
+#define BOND_HAS_HASHING_TYPE	(1 << 2)
+#define BOND_HAS_MIIMON		(1 << 3)
+#define BOND_HAS_MIN_LINKS	(1 << 4)
+
+struct bond_info {
+	uint8_t bn_mode;
+	uint8_t hashing_type;
+	uint32_t ifindex;
+	uint32_t bn_mask;
+	uint32_t miimon;
+	uint32_t min_links;
+};
+
+static int bond_info_alloc(struct rtnl_link *link)
+{
+	struct bond_info *bn;
+
+	if (link->l_info)
+		memset(link->l_info, 0, sizeof(*bn));
+	else {
+		bn = calloc(1, sizeof(*bn));
+		if (!bn)
+			return -NLE_NOMEM;
+
+		link->l_info = bn;
+	}
+
+	return 0;
+}
+
+static void bond_info_free(struct rtnl_link *link)
+{
+	_nl_clear_free(&link->l_info);
+}
+
+static int bond_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
+{
+	struct bond_info *bn = link->l_info;
+	struct nlattr *data;
+
+	data = nla_nest_start(msg, IFLA_INFO_DATA);
+	if (!data)
+		return -NLE_MSGSIZE;
+	if (bn->bn_mask & BOND_HAS_MODE)
+		NLA_PUT_U8(msg, IFLA_BOND_MODE, bn->bn_mode);
+
+	if (bn->bn_mask & BOND_HAS_ACTIVE_SLAVE)
+		NLA_PUT_U32(msg, IFLA_BOND_ACTIVE_SLAVE, bn->ifindex);
+
+	if (bn->bn_mask & BOND_HAS_HASHING_TYPE)
+		NLA_PUT_U8(msg, IFLA_BOND_XMIT_HASH_POLICY, bn->hashing_type);
+
+	if (bn->bn_mask & BOND_HAS_MIIMON)
+		NLA_PUT_U32(msg, IFLA_BOND_MIIMON, bn->miimon);
+
+	if (bn->bn_mask & BOND_HAS_MIN_LINKS)
+		NLA_PUT_U32(msg, IFLA_BOND_MIN_LINKS, bn->min_links);
+
+	nla_nest_end(msg, data);
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(msg, data);
+	return -NLE_MSGSIZE;
+}
+
+static struct rtnl_link_info_ops bonding_info_ops = {
+	.io_name		= "bond",
+	.io_alloc		= bond_info_alloc,
+	.io_put_attrs		= bond_put_attrs,
+	.io_free		= bond_info_free,
+};
+
+#define IS_BOND_INFO_ASSERT(link)                                                    \
+	do {                                                                         \
+		if (link->l_info_ops != &bonding_info_ops) {                         \
+			APPBUG("Link is not a bond link. Set type \"bond\" first."); \
+		}                                                                    \
+	} while (0)
+
+/**
+ * Set active slave for bond
+ * @arg link            Link object of type bond
+ * @arg active          ifindex of active slave to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave)
+{
+	struct bond_info *bn = link->l_info;
+
+	IS_BOND_INFO_ASSERT(link);
+
+	bn->ifindex = active_slave;
+
+	bn->bn_mask |= BOND_HAS_ACTIVE_SLAVE;
+}
+
+/**
+ * Set bond mode
+ * @arg link            Link object of type bond
+ * @arg mode            bond mode to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode)
+{
+	struct bond_info *bn = link->l_info;
+
+	IS_BOND_INFO_ASSERT(link);
+
+	bn->bn_mode = mode;
+
+	bn->bn_mask |= BOND_HAS_MODE;
+}
+
+/**
+ * Set hashing type
+ * @arg link            Link object of type bond
+ * @arg type            bond hashing type to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type)
+{
+	struct bond_info *bn = link->l_info;
+
+	IS_BOND_INFO_ASSERT(link);
+
+	bn->hashing_type = type;
+
+	bn->bn_mask |= BOND_HAS_HASHING_TYPE;
+}
+
+/**
+ * Set MII monitoring interval
+ * @arg link            Link object of type bond
+ * @arg miimon          interval in milliseconds
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon)
+{
+	struct bond_info *bn = link->l_info;
+
+	IS_BOND_INFO_ASSERT(link);
+
+	bn->miimon = miimon;
+
+	bn->bn_mask |= BOND_HAS_MIIMON;
+}
+
+/**
+ * Set the minimum number of member ports that must be up before
+ * marking the bond device as up
+ * @arg link            Link object of type bond
+ * @arg min_links       Number of links
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links)
+{
+	struct bond_info *bn = link->l_info;
+
+	IS_BOND_INFO_ASSERT(link);
+
+	bn->min_links = min_links;
+
+	bn->bn_mask |= BOND_HAS_MIN_LINKS;
+}
 
 /**
  * Allocate link object of type bond
@@ -204,16 +380,12 @@
 				rtnl_link_get_ifindex(slave));
 }
 
-static struct rtnl_link_info_ops bonding_info_ops = {
-	.io_name		= "bond",
-};
-
-static void __init bonding_init(void)
+static void _nl_init bonding_init(void)
 {
 	rtnl_link_register_info(&bonding_info_ops);
 }
 
-static void __exit bonding_exit(void)
+static void _nl_exit bonding_exit(void)
 {
 	rtnl_link_unregister_info(&bonding_info_ops);
 }
diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c
index bd04253..5b44164 100644
--- a/lib/route/link/bridge.c
+++ b/lib/route/link/bridge.c
@@ -11,13 +11,18 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_bridge.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/bridge.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_bridge.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 #define VLAN_VID_MASK           0x0fff /* VLAN Identifier */
 
@@ -189,6 +194,7 @@
 		if (nla_type(attr) == IFLA_BRIDGE_MODE) {
 			bd->b_hwmode = nla_get_u16(attr);
 			bd->ce_mask |= BRIDGE_ATTR_HWMODE;
+			continue;
 		} else if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
 			continue;
 
@@ -430,21 +436,23 @@
 	struct bridge_data *b = bridge_data(_b);
 	int diff = 0;
 
-#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
-	diff |= BRIDGE_DIFF(PORT_STATE,	a->b_port_state != b->b_port_state);
-	diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
-	diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
-	diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
-					      sizeof(struct rtnl_link_bridge_vlan)));
-	diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
-	diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(BRIDGE_ATTR_PORT_STATE,
+		      a->b_port_state != b->b_port_state);
+	diff |= _DIFF(BRIDGE_ATTR_PRIORITY, a->b_priority != b->b_priority);
+	diff |= _DIFF(BRIDGE_ATTR_COST, a->b_cost != b->b_cost);
+	diff |= _DIFF(BRIDGE_ATTR_PORT_VLAN,
+		      memcmp(&a->vlan_info, &b->vlan_info,
+			     sizeof(struct rtnl_link_bridge_vlan)));
+	diff |= _DIFF(BRIDGE_ATTR_HWMODE, a->b_hwmode != b->b_hwmode);
+	diff |= _DIFF(BRIDGE_ATTR_SELF, a->b_self != b->b_self);
 
 	if (flags & LOOSE_COMPARISON)
-		diff |= BRIDGE_DIFF(FLAGS,
-				  (a->b_flags ^ b->b_flags) & b->b_flags_mask);
+		diff |= _DIFF(BRIDGE_ATTR_FLAGS,
+			      (a->b_flags ^ b->b_flags) & b->b_flags_mask);
 	else
-		diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
-#undef BRIDGE_DIFF
+		diff |= _DIFF(BRIDGE_ATTR_FLAGS, a->b_flags != b->b_flags);
+#undef _DIFF
 
 	return diff;
 }
@@ -972,12 +980,12 @@
 	.ao_fill_af_no_nest	= 1,
 };
 
-static void __init bridge_init(void)
+static void _nl_init bridge_init(void)
 {
 	rtnl_link_af_register(&bridge_ops);
 }
 
-static void __exit bridge_exit(void)
+static void _nl_exit bridge_exit(void)
 {
 	rtnl_link_af_unregister(&bridge_ops);
 }
diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c
new file mode 100644
index 0000000..61b885f
--- /dev/null
+++ b/lib/route/link/bridge_info.c
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 MaxLinear, Inc.
+ */
+
+/**
+ * @ingroup link
+ * @defgroup bridge Bridging
+ *
+ * @details
+ * @{
+ */
+
+#include "nl-default.h"
+
+#include <netlink/route/link/bridge_info.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+
+#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0)
+#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1)
+#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2)
+
+struct bridge_info {
+	uint32_t ce_mask; /* to support attr macros */
+	uint16_t b_vlan_protocol;
+	uint8_t b_vlan_filtering;
+	uint8_t b_vlan_stats_enabled;
+};
+
+static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
+	[IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
+	[IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 },
+	[IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 },
+};
+
+static inline struct bridge_info *bridge_info(struct rtnl_link *link)
+{
+	return link->l_info;
+}
+
+static int bridge_info_alloc(struct rtnl_link *link)
+{
+	struct bridge_info *bi;
+
+	if (link->l_info)
+		memset(link->l_info, 0, sizeof(*bi));
+	else {
+		bi = calloc(1, sizeof(*bi));
+		if (!bi)
+			return -NLE_NOMEM;
+
+		link->l_info = bi;
+	}
+
+	return 0;
+}
+
+static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data,
+			     struct nlattr *xstats)
+{
+	struct nlattr *tb[IFLA_BR_MAX + 1];
+	struct bridge_info *bi;
+	int err;
+
+	NL_DBG(3, "Parsing Bridge link info\n");
+
+	if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) <
+	    0)
+		return err;
+
+	if ((err = bridge_info_alloc(link)) < 0)
+		return err;
+
+	bi = link->l_info;
+
+	if (tb[IFLA_BR_VLAN_FILTERING]) {
+		bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
+		bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
+	}
+
+	if (tb[IFLA_BR_VLAN_PROTOCOL]) {
+		bi->b_vlan_protocol =
+			ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL]));
+		bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
+	}
+
+	if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
+		bi->b_vlan_stats_enabled =
+			nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]);
+		bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
+	}
+
+	return 0;
+}
+
+static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
+{
+	struct bridge_info *bi = link->l_info;
+	struct nlattr *data;
+
+	data = nla_nest_start(msg, IFLA_INFO_DATA);
+	if (!data)
+		return -NLE_MSGSIZE;
+
+	if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
+		NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
+
+	if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
+		NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL,
+			    htons(bi->b_vlan_protocol));
+
+	if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
+		NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED,
+			   bi->b_vlan_stats_enabled);
+
+	nla_nest_end(msg, data);
+	return 0;
+
+nla_put_failure:
+	nla_nest_cancel(msg, data);
+	return -NLE_MSGSIZE;
+}
+
+static void bridge_info_free(struct rtnl_link *link)
+{
+	_nl_clear_free(&link->l_info);
+}
+
+static struct rtnl_link_info_ops bridge_info_ops = {
+	.io_name = "bridge",
+	.io_alloc = bridge_info_alloc,
+	.io_parse = bridge_info_parse,
+	.io_put_attrs = bridge_info_put_attrs,
+	.io_free = bridge_info_free,
+};
+
+#define IS_BRIDGE_INFO_ASSERT(link)                                                      \
+	do {                                                                             \
+		if ((link)->l_info_ops != &bridge_info_ops) {                            \
+			APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
+		}                                                                        \
+	} while (0)
+
+/**
+ * Set VLAN filtering flag
+ * @arg link		Link object of type bridge
+ * @arg vlan_filtering	VLAN_filtering boolean flag to set.
+ *
+ * @see rtnl_link_bridge_get_vlan_filtering()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link,
+					 uint8_t vlan_filtering)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	bi->b_vlan_filtering = vlan_filtering;
+
+	bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
+}
+
+/**
+ * Get VLAN filtering flag
+ * @arg link		Link object of type bridge
+ * @arg vlan_filtering	Output argument.
+ *
+ * @see rtnl_link_bridge_set_vlan_filtering()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link,
+					uint8_t *vlan_filtering)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
+		return -NLE_NOATTR;
+
+	if (!vlan_filtering)
+		return -NLE_INVAL;
+
+	*vlan_filtering = bi->b_vlan_filtering;
+	return 0;
+}
+
+/**
+ * Set VLAN protocol
+ * @arg link		Link object of type bridge
+ * @arg vlan_protocol	VLAN protocol to set. The protocol
+ *   numbers is in host byte order.
+ *
+ * @see rtnl_link_bridge_get_vlan_protocol()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link,
+					uint16_t vlan_protocol)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	bi->b_vlan_protocol = vlan_protocol;
+
+	bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
+}
+
+/**
+ * Get VLAN protocol
+ * @arg link		Link object of type bridge
+ * @arg vlan_protocol	Output argument. The protocol number is in host byte order.
+ *
+ * @see rtnl_link_bridge_set_vlan_protocol()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link,
+				       uint16_t *vlan_protocol)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
+		return -NLE_NOATTR;
+
+	if (!vlan_protocol)
+		return -NLE_INVAL;
+
+	*vlan_protocol = bi->b_vlan_protocol;
+
+	return 0;
+}
+
+/**
+ * Set VLAN stats enabled flag
+ * @arg link		Link object of type bridge
+ * @arg vlan_stats_enabled	VLAN stats enabled flag to set
+ *
+ * @see rtnl_link_bridge_get_vlan_stats_enabled()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link,
+					     uint8_t vlan_stats_enabled)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	bi->b_vlan_stats_enabled = vlan_stats_enabled;
+
+	bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
+}
+
+/**
+ * Get VLAN stats enabled flag
+ * @arg link		Link object of type bridge
+ * @arg vlan_stats_enabled	Output argument.
+ *
+ * @see rtnl_link_bridge_set_vlan_stats_enabled()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link,
+					    uint8_t *vlan_stats_enabled)
+{
+	struct bridge_info *bi = bridge_info(link);
+
+	IS_BRIDGE_INFO_ASSERT(link);
+
+	if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
+		return -NLE_NOATTR;
+
+	if (!vlan_stats_enabled)
+		return -NLE_INVAL;
+
+	*vlan_stats_enabled = bi->b_vlan_stats_enabled;
+
+	return 0;
+}
+
+static void _nl_init bridge_info_init(void)
+{
+	rtnl_link_register_info(&bridge_info_ops);
+}
+
+static void _nl_exit bridge_info_exit(void)
+{
+	rtnl_link_unregister_info(&bridge_info_ops);
+}
+
+/** @} */
diff --git a/lib/route/link/can.c b/lib/route/link/can.c
index da8f092..da00144 100644
--- a/lib/route/link/can.c
+++ b/lib/route/link/can.c
@@ -16,16 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/can/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/can.h>
 
-#include <linux/can/netlink.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define CAN_HAS_BITTIMING		(1<<0)
@@ -38,6 +41,7 @@
 #define CAN_HAS_BERR_COUNTER		(1<<7)
 #define CAN_HAS_DATA_BITTIMING		(1<<8)
 #define CAN_HAS_DATA_BITTIMING_CONST	(1<<9)
+#define CAN_HAS_DEVICE_STATS		(1<<10)
 
 struct can_info {
 	uint32_t			ci_state;
@@ -51,6 +55,7 @@
 	uint32_t			ci_mask;
 	struct can_bittiming		ci_data_bittiming;
 	struct can_bittiming_const	ci_data_bittiming_const;
+	struct can_device_stats		ci_device_stats;
 };
 
 /** @endcond */
@@ -163,6 +168,11 @@
 		ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST;
 	}
 
+	if (xstats && nla_len(xstats) >= sizeof(ci->ci_device_stats)) {
+		nla_memcpy(&ci->ci_device_stats, xstats, sizeof(ci->ci_device_stats));
+		ci->ci_mask |= CAN_HAS_DEVICE_STATS;
+	}
+
 	err = 0;
 errout:
 	return err;
@@ -220,11 +230,8 @@
 static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
 {
 	struct can_info *ci = link->l_info;
-	char buf [64];
 
-	rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf));
-	nl_dump(p, "    bitrate %d %s <%s>",
-		ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf);
+	can_dump_line(link, p);
 
 	if (ci->ci_mask & CAN_HAS_RESTART) {
 		if (ci->ci_restart)
@@ -283,8 +290,28 @@
 		nl_dump_line(p,"    bus error TX %d\n",
 			     ci->ci_berr_counter.txerr);
 	}
+}
 
-	return;
+static void can_dump_stats(struct rtnl_link *link, struct nl_dump_params *p)
+{
+	struct can_info *ci = link->l_info;
+
+	can_dump_details(link, p);
+
+	if (ci->ci_mask & CAN_HAS_DEVICE_STATS) {
+		nl_dump_line(p,"    bus errors %d\n",
+			     ci->ci_device_stats.bus_error);
+		nl_dump_line(p,"    error warning state changes %d\n",
+			     ci->ci_device_stats.error_warning);
+		nl_dump_line(p,"    error passive state changes %d\n",
+			     ci->ci_device_stats.error_passive);
+		nl_dump_line(p,"    bus off state changes %d\n",
+			     ci->ci_device_stats.bus_off);
+		nl_dump_line(p,"    arbitration lost errors %d\n",
+			     ci->ci_device_stats.arbitration_lost);
+		nl_dump_line(p,"    restarts %d\n",
+			     ci->ci_device_stats.restarts);
+	}
 }
 
 static int can_clone(struct rtnl_link *dst, struct rtnl_link *src)
@@ -361,6 +388,7 @@
 	.io_dump = {
 	    [NL_DUMP_LINE]	= can_dump_line,
 	    [NL_DUMP_DETAILS]	= can_dump_details,
+	    [NL_DUMP_STATS]     = can_dump_stats,
 	},
 	.io_clone		= can_clone,
 	.io_put_attrs		= can_put_attrs,
@@ -861,6 +889,30 @@
 	return 0;
 }
 
+/**
+ * Get CAN device stats
+ * @arg link            Link object
+ * @arg device_stats	CAN device stats
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_link_can_get_device_stats(struct rtnl_link* link,
+				   struct can_device_stats *device_stats)
+{
+	struct can_info *ci = link->l_info;
+
+	IS_CAN_LINK_ASSERT(link);
+	if (!device_stats)
+		return -NLE_INVAL;
+
+	if (ci->ci_mask & CAN_HAS_DEVICE_STATS)
+		*device_stats = ci->ci_device_stats;
+	else
+		return -NLE_MISSING_ATTR;
+
+	return 0;
+}
+
 /** @} */
 
 /**
@@ -892,12 +944,12 @@
 
 /** @} */
 
-static void __init can_init(void)
+static void _nl_init can_init(void)
 {
 	rtnl_link_register_info(&can_info_ops);
 }
 
-static void __exit can_exit(void)
+static void _nl_exit can_exit(void)
 {
 	rtnl_link_unregister_info(&can_info_ops);
 }
diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c
index a6478d0..83d6ba7 100644
--- a/lib/route/link/dummy.c
+++ b/lib/route/link/dummy.c
@@ -13,20 +13,22 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
 
 static struct rtnl_link_info_ops dummy_info_ops = {
 	.io_name		= "dummy",
 };
 
-static void __init dummy_init(void)
+static void _nl_init dummy_init(void)
 {
 	rtnl_link_register_info(&dummy_info_ops);
 }
 
-static void __exit dummy_exit(void)
+static void _nl_exit dummy_exit(void)
 {
 	rtnl_link_unregister_info(&dummy_info_ops);
 }
diff --git a/lib/route/link/geneve.c b/lib/route/link/geneve.c
index cab57cc..61dd1f1 100644
--- a/lib/route/link/geneve.c
+++ b/lib/route/link/geneve.c
@@ -15,14 +15,16 @@
  *
  * @{
  */
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/geneve.h>
 
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define GENEVE_ATTR_ID          (1<<0)
@@ -788,12 +790,12 @@
 }
 
 /** @} */
-static void __init geneve_init(void)
+static void _nl_init geneve_init(void)
 {
         rtnl_link_register_info(&geneve_info_ops);
 }
 
-static void __exit geneve_exit(void)
+static void _nl_exit geneve_exit(void)
 {
         rtnl_link_unregister_info(&geneve_info_ops);
 }
diff --git a/lib/route/link/ifb.c b/lib/route/link/ifb.c
index 528647e..d5fc685 100644
--- a/lib/route/link/ifb.c
+++ b/lib/route/link/ifb.c
@@ -13,20 +13,22 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
 
 static struct rtnl_link_info_ops ifb_info_ops = {
 	.io_name		= "ifb",
 };
 
-static void __init ifb_init(void)
+static void _nl_init ifb_init(void)
 {
 	rtnl_link_register_info(&ifb_info_ops);
 }
 
-static void __exit ifb_exit(void)
+static void _nl_exit ifb_exit(void)
 {
 	rtnl_link_unregister_info(&ifb_info_ops);
 }
diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c
index 2f95fb6..7ed705e 100644
--- a/lib/route/link/inet.c
+++ b/lib/route/link/inet.c
@@ -51,12 +51,16 @@
  */
 
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/ip.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/inet.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
 
 /** @cond SKIP */
 struct inet_data
@@ -104,7 +108,7 @@
 
 	if (tb[IFLA_INET_CONF]) {
 		int i;
-		int len = min_t(int, IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
+		int len = _NL_MIN(IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
 
 		for (i = 0; i < len; i++)
 			id->i_confset[i] = 1;
@@ -277,12 +281,12 @@
 }
 
 
-static void __init inet_init(void)
+static void _nl_init inet_init(void)
 {
 	rtnl_link_af_register(&inet_ops);
 }
 
-static void __exit inet_exit(void)
+static void _nl_exit inet_exit(void)
 {
 	rtnl_link_af_unregister(&inet_ops);
 }
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
index afcbbce..87b057f 100644
--- a/lib/route/link/inet6.c
+++ b/lib/route/link/inet6.c
@@ -3,15 +3,19 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/ipv6.h>
+#include <linux/snmp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/inet6.h>
-#include <netlink-private/route/link/api.h>
 
-#include "netlink-private/route/utils.h"
-#include "netlink-private/utils.h"
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-static-route/nl-priv-static-route.h"
 
 #define I6_ADDR_GEN_MODE_UNKNOWN	UINT8_MAX
 
@@ -21,6 +25,7 @@
 	struct ifla_cacheinfo	i6_cacheinfo;
 	uint32_t		i6_conf[DEVCONF_MAX];
 	struct in6_addr		i6_token;
+	uint8_t			i6_conf_len;
 	uint8_t			i6_addr_gen_mode;
 };
 
@@ -165,9 +170,13 @@
 		nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
 			   sizeof(i6->i6_cacheinfo));
 
-	if (tb[IFLA_INET6_CONF])
+	if (tb[IFLA_INET6_CONF]) {
+		i6->i6_conf_len = _NL_MIN(ARRAY_SIZE(i6->i6_conf),
+				      nla_len(tb[IFLA_INET6_CONF]) /
+					      sizeof(i6->i6_conf[0]));
 		nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
-			   sizeof(i6->i6_conf));
+			   sizeof(i6->i6_conf[0]) * i6->i6_conf_len);
+	}
 
 	if (tb[IFLA_INET6_TOKEN])
 		nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN],
@@ -197,7 +206,7 @@
 			map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
 		}
 
-		len = min_t(int, __IPSTATS_MIB_MAX, len);
+		len = _NL_MIN(__IPSTATS_MIB_MAX, len);
 		for (i = 1; i < len; i++) {
 			memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
 			rtnl_link_set_stat(link, map_stat_id[i], stat);
@@ -205,12 +214,13 @@
 	}
 
 	if (tb[IFLA_INET6_ICMP6STATS]) {
+#define _NL_ICMP6_MIB_MAX 6
 		unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
 		uint64_t stat;
 		int i;
-		int len = min_t(int, __ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
+		int len = _NL_MIN(_NL_ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
 
-		_NL_STATIC_ASSERT (__ICMP6_MIB_MAX == 6);
+		_NL_STATIC_ASSERT (__ICMP6_MIB_MAX >= _NL_ICMP6_MIB_MAX);
 		_NL_STATIC_ASSERT (RTNL_LINK_ICMP6_CSUMERRORS - RTNL_LINK_ICMP6_INMSGS + 1 == 5);
 
 		for (i = 1; i < len; i++) {
@@ -351,7 +361,7 @@
 	nl_dump_line(p, "      devconf:\n");
 	nl_dump_line(p, "      ");
 
-	for (i = 0; i < DEVCONF_MAX; i++) {
+	for (i = 0; i < (int) i6->i6_conf_len; i++) {
 		char buf2[64];
 		uint32_t value = i6->i6_conf[i];
 		int x, offset;
@@ -689,12 +699,42 @@
 	return 0;
 }
 
-static void __init inet6_init(void)
+/**
+ * Get value of a ipv6 link configuration setting
+ * @arg link		Link object
+ * @arg cfgid		Configuration identifier
+ * @arg res		Result pointer
+ *
+ * Stores the value of the specified configuration setting in the provided
+ * result pointer.
+ *
+ * @return 0 on success or a negative error code.
+ * @return -NLE_RANGE cfgid is out of range or not provided by kernel.
+ * @return -NLE_NOATTR configuration setting not available
+ */
+int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid,
+			     uint32_t *res)
+{
+	struct inet6_data *id;
+
+	if (!(id = rtnl_link_af_data(link, &inet6_ops)))
+		return -NLE_NOATTR;
+
+	if (cfgid >= id->i6_conf_len)
+		return -NLE_RANGE;
+
+	*res = id->i6_conf[cfgid];
+
+	return 0;
+}
+
+
+static void _nl_init inet6_init(void)
 {
 	rtnl_link_af_register(&inet6_ops);
 }
 
-static void __exit inet6_exit(void)
+static void _nl_exit inet6_exit(void)
 {
 	rtnl_link_af_unregister(&inet6_ops);
 }
diff --git a/lib/route/link/ip6gre.c b/lib/route/link/ip6gre.c
index 5d5c3a0..51d4609 100644
--- a/lib/route/link/ip6gre.c
+++ b/lib/route/link/ip6gre.c
@@ -13,15 +13,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ip6gre.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IP6GRE_ATTR_LINK          (1 << 0)
 #define IP6GRE_ATTR_IFLAGS        (1 << 1)
@@ -875,12 +879,12 @@
 	return 0;
 }
 
-static void __init ip6gre_init(void)
+static void _nl_init ip6gre_init(void)
 {
 	rtnl_link_register_info(&ip6gre_info_ops);
 }
 
-static void __exit ip6gre_exit(void)
+static void _nl_exit ip6gre_exit(void)
 {
 	rtnl_link_unregister_info(&ip6gre_info_ops);
 }
diff --git a/lib/route/link/ip6tnl.c b/lib/route/link/ip6tnl.c
index cdc9024..9b3abfd 100644
--- a/lib/route/link/ip6tnl.c
+++ b/lib/route/link/ip6tnl.c
@@ -16,16 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ip6tnl.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
-#include <netinet/in.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IP6_TNL_ATTR_LINK          (1 << 0)
 #define IP6_TNL_ATTR_LOCAL         (1 << 1)
@@ -732,12 +735,12 @@
 	return 0;
 }
 
-static void __init ip6_tnl_init(void)
+static void _nl_init ip6_tnl_init(void)
 {
 	rtnl_link_register_info(&ip6_tnl_info_ops);
 }
 
-static void __exit ip6_tnl_exit(void)
+static void _nl_exit ip6_tnl_exit(void)
 {
 	rtnl_link_unregister_info(&ip6_tnl_info_ops);
 }
diff --git a/lib/route/link/ip6vti.c b/lib/route/link/ip6vti.c
index 8c603ab..b6c7a1b 100644
--- a/lib/route/link/ip6vti.c
+++ b/lib/route/link/ip6vti.c
@@ -13,15 +13,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ip6vti.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IP6VTI_ATTR_LINK      (1 << 0)
 #define IP6VTI_ATTR_IKEY      (1 << 1)
@@ -543,12 +547,12 @@
 	return 0;
 }
 
-static void __init ip6vti_init(void)
+static void _nl_init ip6vti_init(void)
 {
 	rtnl_link_register_info(&ip6vti_info_ops);
 }
 
-static void __exit ip6vti_exit(void)
+static void _nl_exit ip6vti_exit(void)
 {
 	rtnl_link_unregister_info(&ip6vti_info_ops);
 }
diff --git a/lib/route/link/ipgre.c b/lib/route/link/ipgre.c
index f5a4998..bd3cc40 100644
--- a/lib/route/link/ipgre.c
+++ b/lib/route/link/ipgre.c
@@ -16,15 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ipgre.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IPGRE_ATTR_LINK          (1 << 0)
 #define IPGRE_ATTR_IFLAGS        (1 << 1)
@@ -879,13 +883,13 @@
 	return 0;
 }
 
-static void __init ipgre_init(void)
+static void _nl_init ipgre_init(void)
 {
 	rtnl_link_register_info(&ipgre_info_ops);
 	rtnl_link_register_info(&ipgretap_info_ops);
 }
 
-static void __exit ipgre_exit(void)
+static void _nl_exit ipgre_exit(void)
 {
 	rtnl_link_unregister_info(&ipgre_info_ops);
 	rtnl_link_unregister_info(&ipgretap_info_ops);
diff --git a/lib/route/link/ipip.c b/lib/route/link/ipip.c
index e905ef9..74db890 100644
--- a/lib/route/link/ipip.c
+++ b/lib/route/link/ipip.c
@@ -16,15 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ipip.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IPIP_ATTR_LINK          (1 << 0)
 #define IPIP_ATTR_LOCAL         (1 << 1)
@@ -578,12 +582,12 @@
 	return 0;
 }
 
-static void __init ipip_init(void)
+static void _nl_init ipip_init(void)
 {
 	rtnl_link_register_info(&ipip_info_ops);
 }
 
-static void __exit ipip_exit(void)
+static void _nl_exit ipip_exit(void)
 {
 	rtnl_link_unregister_info(&ipip_info_ops);
 }
diff --git a/lib/route/link/ipvlan.c b/lib/route/link/ipvlan.c
index 020f2cb..807942b 100644
--- a/lib/route/link/ipvlan.c
+++ b/lib/route/link/ipvlan.c
@@ -16,16 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/ipvlan.h>
 
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define IPVLAN_HAS_MODE	(1<<0)
@@ -257,12 +260,12 @@
 
 /** @} */
 
-static void __init ipvlan_init(void)
+static void _nl_init ipvlan_init(void)
 {
 	rtnl_link_register_info(&ipvlan_info_ops);
 }
 
-static void __exit ipvlan_exit(void)
+static void _nl_exit ipvlan_exit(void)
 {
 	rtnl_link_unregister_info(&ipvlan_info_ops);
 }
diff --git a/lib/route/link/ipvti.c b/lib/route/link/ipvti.c
index 9f9d3d6..fd57895 100644
--- a/lib/route/link/ipvti.c
+++ b/lib/route/link/ipvti.c
@@ -16,15 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/ipvti.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define IPVTI_ATTR_LINK		 (1 << 0)
 #define IPVTI_ATTR_IKEY		 (1 << 1)
@@ -527,12 +531,12 @@
 	return 0;
 }
 
-static void __init ipvti_init(void)
+static void _nl_init ipvti_init(void)
 {
 	rtnl_link_register_info(&ipvti_info_ops);
 }
 
-static void __exit ipvti_exit(void)
+static void _nl_exit ipvti_exit(void)
 {
 	rtnl_link_unregister_info(&ipvti_info_ops);
 }
diff --git a/include/netlink-private/route/link/api.h b/lib/route/link/link-api.h
similarity index 97%
rename from include/netlink-private/route/link/api.h
rename to lib/route/link/link-api.h
index 189f361..0e54057 100644
--- a/include/netlink-private/route/link/api.h
+++ b/lib/route/link/link-api.h
@@ -7,10 +7,9 @@
 #define NETLINK_LINK_API_H_
 
 #include <netlink/netlink.h>
+#include <netlink/route/link.h>
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /**
  * @ingroup link_api
@@ -187,8 +186,6 @@
 							    struct rtnl_link *b,
 							    int flags);
 
-#ifdef __cplusplus
-}
-#endif
+extern struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex);
 
 #endif
diff --git a/lib/route/link/macsec.c b/lib/route/link/macsec.c
index 16b65b0..a989eed 100644
--- a/lib/route/link/macsec.c
+++ b/lib/route/link/macsec.c
@@ -15,17 +15,21 @@
  *
  * @{
  */
-#include <netlink-private/netlink.h>
+
+#include "nl-default.h"
+
+#include <linux/if_macsec.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/macsec.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink-private/utils.h>
 
-#include <linux/if_macsec.h>
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /** @cond SKIP */
 #define MACSEC_ATTR_SCI			(1 << 0)
@@ -367,33 +371,38 @@
 	int diff = 0;
 	uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
 
-#define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR)
-
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
 	if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
-		diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
+		diff |= _DIFF(MACSEC_ATTR_SCI, a->sci != b->sci);
 	else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
-		diff |= MACSEC_DIFF(PORT, a->port != b->port);
+		diff |= _DIFF(MACSEC_ATTR_PORT, a->port != b->port);
 
-	if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
-		diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
-		diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
+	if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE &&
+	    b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
+		diff |= _DIFF(MACSEC_ATTR_ICV_LEN, a->icv_len != b->icv_len);
+		diff |= _DIFF(MACSEC_ATTR_CIPHER_SUITE,
+			      a->cipher_suite != b->cipher_suite);
 	}
 
-	if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
-		int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
-		if (a->replay_protect && b->replay_protect)
-			d |= MACSEC_DIFF(WINDOW, a->window != b->window);
+	if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT &&
+	    b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
+		int d = _DIFF(MACSEC_ATTR_REPLAY_PROTECT,
+			      a->replay_protect != b->replay_protect);
+		if (a->replay_protect && b->replay_protect) {
+			d |= _DIFF(MACSEC_ATTR_WINDOW, a->window != b->window);
+		}
 		diff |= d;
 	}
 
-	diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
-	diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
-	diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
-	diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
-	diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
-	diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
-	diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
-#undef MACSEC_DIFF
+	diff |= _DIFF(MACSEC_ATTR_ENCODING_SA,
+		      a->encoding_sa != b->encoding_sa);
+	diff |= _DIFF(MACSEC_ATTR_ENCRYPT, a->encrypt != b->encrypt);
+	diff |= _DIFF(MACSEC_ATTR_PROTECT, a->protect != b->protect);
+	diff |= _DIFF(MACSEC_ATTR_INC_SCI, a->send_sci != b->send_sci);
+	diff |= _DIFF(MACSEC_ATTR_ES, a->end_station != b->end_station);
+	diff |= _DIFF(MACSEC_ATTR_SCB, a->scb != b->scb);
+	diff |= _DIFF(MACSEC_ATTR_VALIDATION, a->validate != b->validate);
+#undef _DIFF
 
 	return diff;
 }
@@ -413,12 +422,12 @@
 	.io_compare		= macsec_compare,
 };
 
-static void __init macsec_init(void)
+static void _nl_init macsec_init(void)
 {
 	rtnl_link_register_info(&macsec_info_ops);
 }
 
-static void __exit macsec_exit(void)
+static void _nl_exit macsec_exit(void)
 {
 	rtnl_link_unregister_info(&macsec_info_ops);
 }
@@ -652,9 +661,6 @@
 
 	IS_MACSEC_LINK_ASSERT(link);
 
-	if (offload > 1)
-		return -NLE_INVAL;
-
 	info->offload = offload;
 	info->ce_mask |= MACSEC_ATTR_OFFLOAD;
 
diff --git a/lib/route/link/macvlan.c b/lib/route/link/macvlan.c
index df61bb2..5452d9e 100644
--- a/lib/route/link/macvlan.c
+++ b/lib/route/link/macvlan.c
@@ -17,17 +17,22 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
+#include <linux/ethtool.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/macvlan.h>
 #include <netlink/route/link/macvtap.h>
 
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define MACVLAN_HAS_MODE        (1<<0)
@@ -855,13 +860,13 @@
 
 /** @} */
 
-static void __init macvlan_init(void)
+static void _nl_init macvlan_init(void)
 {
 	rtnl_link_register_info(&macvlan_info_ops);
 	rtnl_link_register_info(&macvtap_info_ops);
 }
 
-static void __exit macvlan_exit(void)
+static void _nl_exit macvlan_exit(void)
 {
 	rtnl_link_unregister_info(&macvlan_info_ops);
 	rtnl_link_unregister_info(&macvtap_info_ops);
diff --git a/lib/route/link/ppp.c b/lib/route/link/ppp.c
index a5fb400..34ca5f6 100644
--- a/lib/route/link/ppp.c
+++ b/lib/route/link/ppp.c
@@ -14,11 +14,13 @@
  * @{
  */
 
-#include <netlink/route/link/ppp.h>
+#include "nl-default.h"
 
-#include <netlink-private/netlink.h>
+#include <netlink/route/link/ppp.h>
 #include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define PPP_ATTR_FD		(1<<0)
@@ -204,12 +206,12 @@
 
 /** @} */
 
-static void __init ppp_init(void)
+static void _nl_init ppp_init(void)
 {
 	rtnl_link_register_info(&ppp_info_ops);
 }
 
-static void __exit ppp_exit(void)
+static void _nl_exit ppp_exit(void)
 {
 	rtnl_link_unregister_info(&ppp_info_ops);
 }
diff --git a/lib/route/link/sit.c b/lib/route/link/sit.c
index fabb811..69dd316 100644
--- a/lib/route/link/sit.c
+++ b/lib/route/link/sit.c
@@ -16,15 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/sit.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define SIT_ATTR_LINK          (1 << 0)
 #define SIT_ATTR_LOCAL         (1 << 1)
@@ -858,12 +862,12 @@
 	return 0;
 }
 
-static void __init sit_init(void)
+static void _nl_init sit_init(void)
 {
 	rtnl_link_register_info(&sit_info_ops);
 }
 
-static void __exit sit_exit(void)
+static void _nl_exit sit_exit(void)
 {
 	rtnl_link_unregister_info(&sit_info_ops);
 }
diff --git a/lib/route/link/sriov.c b/lib/route/link/sriov.c
index 3a72814..d47d1dd 100644
--- a/lib/route/link/sriov.c
+++ b/lib/route/link/sriov.c
@@ -19,17 +19,38 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink/netlink.h>
-#include <netlink/route/link.h>
+#include "nl-default.h"
 
 #include <linux/if_ether.h>
 #include <linux/if_link.h>
-#include <netlink-private/route/link/sriov.h>
+
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
 #include <netlink/route/link/sriov.h>
 
+#include "nl-route.h"
+#include "link-sriov.h"
+#include "link-api.h"
+
 /** @cond SKIP */
+struct rtnl_link_vf {
+	struct nl_list_head vf_list;
+	int ce_refcnt;
+	uint32_t ce_mask;
+	uint32_t vf_index;
+	uint64_t vf_guid_node;
+	uint64_t vf_guid_port;
+	uint32_t vf_linkstate;
+	struct nl_addr *vf_lladdr;
+	uint32_t vf_max_tx_rate;
+	uint32_t vf_min_tx_rate;
+	uint32_t vf_rate;
+	uint32_t vf_rss_query_en;
+	uint32_t vf_spoofchk;
+	uint64_t vf_stats[RTNL_LINK_VF_STATS_MAX + 1];
+	uint32_t vf_trust;
+	struct nl_vf_vlans *vf_vlans;
+};
 
 #define SRIOVON "on"
 #define SRIOVOFF "off"
diff --git a/lib/route/link/team.c b/lib/route/link/team.c
index 1bcc86e..0f1161b 100644
--- a/lib/route/link/team.c
+++ b/lib/route/link/team.c
@@ -14,11 +14,13 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/team.h>
 
+#include "link-api.h"
+
 /**
  * Allocate link object of type team
  *
@@ -89,12 +91,12 @@
 	.io_name		= "team",
 };
 
-static void __init team_init(void)
+static void _nl_init team_init(void)
 {
 	rtnl_link_register_info(&team_info_ops);
 }
 
-static void __exit team_exit(void)
+static void _nl_exit team_exit(void)
 {
 	rtnl_link_unregister_info(&team_info_ops);
 }
diff --git a/lib/route/link/veth.c b/lib/route/link/veth.c
index 37f43f6..be4b795 100644
--- a/lib/route/link/veth.c
+++ b/lib/route/link/veth.c
@@ -16,17 +16,20 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+#include <linux/veth.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/veth.h>
 
-#include <linux/if_link.h>
-#include <linux/veth.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 static struct nla_policy veth_policy[VETH_INFO_MAX+1] = {
 	[VETH_INFO_PEER]	= { .minlen = sizeof(struct ifinfomsg) },
@@ -289,12 +292,12 @@
 
 /** @} */
 
-static void __init veth_init(void)
+static void _nl_init veth_init(void)
 {
 	rtnl_link_register_info(&veth_info_ops);
 }
 
-static void __exit veth_exit(void)
+static void _nl_exit veth_exit(void)
 {
 	rtnl_link_unregister_info(&veth_info_ops);
 }
diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c
index 36f8822..60e4358 100644
--- a/lib/route/link/vlan.c
+++ b/lib/route/link/vlan.c
@@ -16,16 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_vlan.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/vlan.h>
 
-#include <linux/if_vlan.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define VLAN_HAS_ID		(1<<0)
@@ -288,9 +291,12 @@
 {
 	struct vlan_info *vi = link->l_info;
 	struct nlattr *data;
+	int nest_count = 0;
 
 	if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
-		return -NLE_MSGSIZE;
+		goto nla_put_failure;
+
+	nest_count++;
 
 	if (vi->vi_mask & VLAN_HAS_ID)
 		NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id);
@@ -315,6 +321,8 @@
 		if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
 			goto nla_put_failure;
 
+		nest_count++;
+
 		for (i = 0; i <= VLAN_PRIO_MAX; i++) {
 			if (vi->vi_ingress_qos_mask & (1 << i)) {
 				map.from = i;
@@ -325,6 +333,7 @@
 		}
 
 		nla_nest_end(msg, qos);
+		nest_count--;
 	}
 
 	if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
@@ -335,6 +344,8 @@
 		if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
 			goto nla_put_failure;
 
+		nest_count++;
+
 		for (i = 0; i < vi->vi_negress; i++) {
 			map.from = vi->vi_egress_qos[i].vm_from;
 			map.to = vi->vi_egress_qos[i].vm_to;
@@ -343,13 +354,16 @@
 		}
 
 		nla_nest_end(msg, qos);
+		nest_count--;
 	}
 
 	nla_nest_end(msg, data);
+	return 0;
 
 nla_put_failure:
-
-	return 0;
+	for (; nest_count > 0; nest_count--)
+		nla_nest_cancel(msg, data);
+	return -NLE_MSGSIZE;
 }
 
 static struct rtnl_link_info_ops vlan_info_ops = {
@@ -661,12 +675,12 @@
 /** @} */
 
 
-static void __init vlan_init(void)
+static void _nl_init vlan_init(void)
 {
 	rtnl_link_register_info(&vlan_info_ops);
 }
 
-static void __exit vlan_exit(void)
+static void _nl_exit vlan_exit(void)
 {
 	rtnl_link_unregister_info(&vlan_info_ops);
 }
diff --git a/lib/route/link/vrf.c b/lib/route/link/vrf.c
index c4edd3e..17cb3bd 100644
--- a/lib/route/link/vrf.c
+++ b/lib/route/link/vrf.c
@@ -17,17 +17,20 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+#include <linux/rtnetlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/vrf.h>
 
-#include <linux/if_link.h>
-#include <linux-private/linux/rtnetlink.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 #define VRF_TABLE_ID_MAX  RT_TABLE_MAX
 
@@ -244,12 +247,12 @@
 
 /** @} */
 
-static void __init vrf_init(void)
+static void _nl_init vrf_init(void)
 {
 	rtnl_link_register_info(&vrf_info_ops);
 }
 
-static void __exit vrf_exit(void)
+static void _nl_exit vrf_exit(void)
 {
 	rtnl_link_unregister_info(&vrf_info_ops);
 }
diff --git a/lib/route/link/vxlan.c b/lib/route/link/vxlan.c
index 7b8429c..4606dd5 100644
--- a/lib/route/link/vxlan.c
+++ b/lib/route/link/vxlan.c
@@ -16,16 +16,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
 #include <netlink/route/link/vxlan.h>
 
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
 
 /** @cond SKIP */
 #define VXLAN_ATTR_ID                  (1<<0)
@@ -616,37 +619,41 @@
 	int diff = 0;
 	uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
 
-#define VXLAN_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, VXLAN_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= VXLAN_DIFF(ID,    a->vxi_id    != b->vxi_id);
-	diff |= VXLAN_DIFF(GROUP, a->vxi_group != b->vxi_group);
-	diff |= VXLAN_DIFF(LINK,  a->vxi_link  != b->vxi_link);
-	diff |= VXLAN_DIFF(LOCAL, a->vxi_local != b->vxi_local);
-	diff |= VXLAN_DIFF(TOS,   a->vxi_tos   != b->vxi_tos);
-	diff |= VXLAN_DIFF(TTL,   a->vxi_ttl   != b->vxi_ttl);
-	diff |= VXLAN_DIFF(LEARNING, a->vxi_learning != b->vxi_learning);
-	diff |= VXLAN_DIFF(AGEING, a->vxi_ageing != b->vxi_ageing);
-	diff |= VXLAN_DIFF(LIMIT, a->vxi_limit != b->vxi_limit);
-	diff |= VXLAN_DIFF(PORT_RANGE,
-	                   a->vxi_port_range.low != b->vxi_port_range.low);
-	diff |= VXLAN_DIFF(PORT_RANGE,
-	                   a->vxi_port_range.high != b->vxi_port_range.high);
-	diff |= VXLAN_DIFF(PROXY, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(RSC, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(L2MISS, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(L3MISS, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(PORT, a->vxi_port != b->vxi_port);
-	diff |= VXLAN_DIFF(GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6, sizeof(a->vxi_group6)) != 0);
-	diff |= VXLAN_DIFF(LOCAL6,  memcmp(&a->vxi_local6, &b->vxi_local6, sizeof(a->vxi_local6)) != 0);
-	diff |= VXLAN_DIFF(UDP_CSUM, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_TX, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_RX, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(REMCSUM_TX, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(REMCSUM_RX, a->vxi_proxy != b->vxi_proxy);
-	diff |= VXLAN_DIFF(COLLECT_METADATA, a->vxi_collect_metadata != b->vxi_collect_metadata);
-	diff |= VXLAN_DIFF(LABEL, a->vxi_label != b->vxi_label);
-	diff |= VXLAN_DIFF(FLAGS, a->vxi_flags != b->vxi_flags);
-#undef VXLAN_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(VXLAN_ATTR_ID, a->vxi_id != b->vxi_id);
+	diff |= _DIFF(VXLAN_ATTR_GROUP, a->vxi_group != b->vxi_group);
+	diff |= _DIFF(VXLAN_ATTR_LINK, a->vxi_link != b->vxi_link);
+	diff |= _DIFF(VXLAN_ATTR_LOCAL, a->vxi_local != b->vxi_local);
+	diff |= _DIFF(VXLAN_ATTR_TOS, a->vxi_tos != b->vxi_tos);
+	diff |= _DIFF(VXLAN_ATTR_TTL, a->vxi_ttl != b->vxi_ttl);
+	diff |= _DIFF(VXLAN_ATTR_LEARNING, a->vxi_learning != b->vxi_learning);
+	diff |= _DIFF(VXLAN_ATTR_AGEING, a->vxi_ageing != b->vxi_ageing);
+	diff |= _DIFF(VXLAN_ATTR_LIMIT, a->vxi_limit != b->vxi_limit);
+	diff |= _DIFF(VXLAN_ATTR_PORT_RANGE,
+		      a->vxi_port_range.low != b->vxi_port_range.low);
+	diff |= _DIFF(VXLAN_ATTR_PORT_RANGE,
+		      a->vxi_port_range.high != b->vxi_port_range.high);
+	diff |= _DIFF(VXLAN_ATTR_PROXY, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_RSC, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_L2MISS, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_L3MISS, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_PORT, a->vxi_port != b->vxi_port);
+	diff |= _DIFF(VXLAN_ATTR_GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6,
+						sizeof(a->vxi_group6)) != 0);
+	diff |= _DIFF(VXLAN_ATTR_LOCAL6, memcmp(&a->vxi_local6, &b->vxi_local6,
+						sizeof(a->vxi_local6)) != 0);
+	diff |= _DIFF(VXLAN_ATTR_UDP_CSUM, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_TX,
+		      a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_RX,
+		      a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_REMCSUM_TX, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_REMCSUM_RX, a->vxi_proxy != b->vxi_proxy);
+	diff |= _DIFF(VXLAN_ATTR_COLLECT_METADATA,
+		      a->vxi_collect_metadata != b->vxi_collect_metadata);
+	diff |= _DIFF(VXLAN_ATTR_LABEL, a->vxi_label != b->vxi_label);
+	diff |= _DIFF(VXLAN_ATTR_FLAGS, a->vxi_flags != b->vxi_flags);
+#undef _DIFF
 
 	return diff;
 }
@@ -1767,12 +1774,12 @@
 
 /** @} */
 
-static void __init vxlan_init(void)
+static void _nl_init vxlan_init(void)
 {
 	rtnl_link_register_info(&vxlan_info_ops);
 }
 
-static void __exit vxlan_exit(void)
+static void _nl_exit vxlan_exit(void)
 {
 	rtnl_link_unregister_info(&vxlan_info_ops);
 }
diff --git a/lib/route/link/xfrmi.c b/lib/route/link/xfrmi.c
index 92531f2..09ceb80 100644
--- a/lib/route/link/xfrmi.c
+++ b/lib/route/link/xfrmi.c
@@ -18,14 +18,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/attr.h>
 #include <netlink/utils.h>
 #include <netlink/object.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link/xfrmi.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
 
 #define XFRMI_ATTR_LINK  (1 << 0)
 #define XFRMI_ATTR_IF_ID (1 << 1)
@@ -248,7 +251,7 @@
  * @arg link            Link object
  * @arg out_link        The output value on success
  *
- * @return 0 on sucess or a negative error code
+ * @return 0 on success or a negative error code
  */
 int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link)
 {
@@ -287,7 +290,7 @@
  * @arg link            Link object
  * @arg out_if_id       The output value on success
  *
- * @return 0 on sucess or a negative error code
+ * @return 0 on success or a negative error code
  */
 int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id)
 {
@@ -302,12 +305,12 @@
 	return 0;
 }
 
-static void __init xfrmi_init(void)
+static void _nl_init xfrmi_init(void)
 {
 	rtnl_link_register_info(&xfrmi_info_ops);
 }
 
-static void __exit xfrmi_exit(void)
+static void _nl_exit xfrmi_exit(void)
 {
 	rtnl_link_unregister_info(&xfrmi_info_ops);
 }
diff --git a/lib/route/mdb.c b/lib/route/mdb.c
index 459959e..7749c16 100644
--- a/lib/route/mdb.c
+++ b/lib/route/mdb.c
@@ -3,16 +3,41 @@
  * lib/route/mdb.c		Multicast Database
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_bridge.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/mdb.h>
+#include <netlink/route/nexthop.h>
 #include <netlink/utils.h>
-#include <linux/if_bridge.h>
+#include <netlink/route/rtnl.h>
+
+#include "nl-route.h"
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 /** @cond SKIP */
 #define MDB_ATTR_IFINDEX         0x000001
 #define MDB_ATTR_ENTRIES         0x000002
 
+struct rtnl_mdb {
+	NLHDR_COMMON
+	uint32_t ifindex;
+
+	struct nl_list_head mdb_entry_list;
+};
+
+struct rtnl_mdb_entry {
+	struct nl_list_head mdb_list;
+	struct nl_addr *addr;
+	uint32_t ifindex;
+	uint16_t vid;
+	uint16_t proto;
+	uint8_t state;
+};
+
 static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void);
 static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry);
 
@@ -55,9 +80,9 @@
 	struct rtnl_mdb_entry *a_entry, *b_entry;
 	uint64_t diff = 0;
 
-#define MDB_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MDB_ATTR_##ATTR, a, b, EXPR)
-	diff |= MDB_DIFF(IFINDEX, a->ifindex != b->ifindex);
-#undef MDB_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(MDB_ATTR_IFINDEX, a->ifindex != b->ifindex);
+#undef _DIFF
 
 	a_entry = nl_list_entry(a->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
 	b_entry = nl_list_entry(b->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
@@ -453,12 +478,12 @@
 	.co_obj_ops = &mdb_obj_ops,
 };
 
-static void __init mdb_init(void)
+static void _nl_init mdb_init(void)
 {
 	nl_cache_mngt_register(&rtnl_mdb_ops);
 }
 
-static void __exit mdb_exit(void)
+static void _nl_exit mdb_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_mdb_ops);
 }
diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index e1ef6a1..9150024 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -143,7 +143,8 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/hashtable.h>
@@ -152,7 +153,36 @@
 #include <netlink/route/link.h>
 #include <netlink/hashtable.h>
 
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 /** @cond SKIP */
+struct rtnl_ncacheinfo {
+	uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */
+	uint32_t nci_used; /**< Time since neighbour entry was last ued */
+	uint32_t nci_updated; /**< Time since last update */
+	uint32_t nci_refcnt; /**< Reference counter */
+};
+
+struct rtnl_neigh {
+	NLHDR_COMMON
+	uint32_t n_family;
+	uint32_t n_ifindex;
+	uint16_t n_state;
+	uint8_t n_flags;
+	uint8_t n_type;
+	struct nl_addr *n_lladdr;
+	struct nl_addr *n_dst;
+	uint32_t n_nhid;
+	uint32_t n_probes;
+	struct rtnl_ncacheinfo n_cacheinfo;
+	uint32_t n_state_mask;
+	uint32_t n_flag_mask;
+	uint32_t n_master;
+	uint16_t n_vlan;
+};
+
 #define NEIGH_ATTR_FLAGS        0x01
 #define NEIGH_ATTR_STATE        0x02
 #define NEIGH_ATTR_LLADDR       0x04
@@ -164,6 +194,7 @@
 #define NEIGH_ATTR_PROBES       0x100
 #define NEIGH_ATTR_MASTER       0x200
 #define NEIGH_ATTR_VLAN         0x400
+#define NEIGH_ATTR_NHID         0x800
 
 static struct nl_cache_ops rtnl_neigh_ops;
 static struct nl_object_ops neigh_obj_ops;
@@ -210,7 +241,7 @@
 		uint32_t	n_ifindex;
 		uint16_t	n_vlan;
 		char		n_addr[0];
-	} __attribute__((packed)) *nkey;
+	} _nl_packed *nkey;
 #ifdef NL_DEBUG
 	char buf[INET6_ADDRSTRLEN+5];
 #endif
@@ -265,27 +296,26 @@
 	struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
 	uint64_t diff = 0;
 
-#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= NEIGH_DIFF(IFINDEX,	a->n_ifindex != b->n_ifindex);
-	diff |= NEIGH_DIFF(FAMILY,	a->n_family != b->n_family);
-	diff |= NEIGH_DIFF(TYPE,	a->n_type != b->n_type);
-	diff |= NEIGH_DIFF(LLADDR,	nl_addr_cmp(a->n_lladdr, b->n_lladdr));
-	diff |= NEIGH_DIFF(DST,		nl_addr_cmp(a->n_dst, b->n_dst));
-	diff |= NEIGH_DIFF(MASTER,	a->n_master != b->n_master);
-	diff |= NEIGH_DIFF(VLAN,	a->n_vlan != b->n_vlan);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(NEIGH_ATTR_IFINDEX, a->n_ifindex != b->n_ifindex);
+	diff |= _DIFF(NEIGH_ATTR_FAMILY, a->n_family != b->n_family);
+	diff |= _DIFF(NEIGH_ATTR_TYPE, a->n_type != b->n_type);
+	diff |= _DIFF(NEIGH_ATTR_LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
+	diff |= _DIFF(NEIGH_ATTR_DST, nl_addr_cmp(a->n_dst, b->n_dst));
+	diff |= _DIFF(NEIGH_ATTR_MASTER, a->n_master != b->n_master);
+	diff |= _DIFF(NEIGH_ATTR_VLAN, a->n_vlan != b->n_vlan);
+	diff |= _DIFF(NEIGH_ATTR_NHID, a->n_nhid != b->n_nhid);
 
 	if (flags & LOOSE_COMPARISON) {
-		diff |= NEIGH_DIFF(STATE,
-				  (a->n_state ^ b->n_state) & b->n_state_mask);
-		diff |= NEIGH_DIFF(FLAGS,
-				  (a->n_flags ^ b->n_flags) & b->n_flag_mask);
+		diff |= _DIFF(NEIGH_ATTR_STATE,
+			      (a->n_state ^ b->n_state) & b->n_state_mask);
+		diff |= _DIFF(NEIGH_ATTR_FLAGS,
+			      (a->n_flags ^ b->n_flags) & b->n_flag_mask);
 	} else {
-		diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
-		diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
+		diff |= _DIFF(NEIGH_ATTR_STATE, a->n_state != b->n_state);
+		diff |= _DIFF(NEIGH_ATTR_FLAGS, a->n_flags != b->n_flags);
 	}
-
-#undef NEIGH_DIFF
+#undef _DIFF
 
 	return diff;
 }
@@ -302,6 +332,7 @@
 	__ADD(NEIGH_ATTR_PROBES, probes),
 	__ADD(NEIGH_ATTR_MASTER, master),
 	__ADD(NEIGH_ATTR_VLAN, vlan),
+	__ADD(NEIGH_ATTR_NHID, nhid),
 };
 
 static char *neigh_attrs2str(int attrs, char *buf, size_t len)
@@ -318,6 +349,7 @@
 		if (neigh->n_flags & NTF_SELF)
 			return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
 				       ((neigh->ce_mask & NEIGH_ATTR_DST) ? NEIGH_ATTR_DST: 0) |
+				       ((neigh->ce_mask & NEIGH_ATTR_NHID) ? NEIGH_ATTR_NHID: 0) |
 				       ((neigh->ce_mask & NEIGH_ATTR_VLAN) ? NEIGH_ATTR_VLAN : 0));
 		else
 			return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER | NEIGH_ATTR_VLAN);
@@ -419,6 +451,11 @@
 		neigh->ce_mask |= NEIGH_ATTR_VLAN;
 	}
 
+	if (tb[NDA_NH_ID]) {
+		neigh->n_nhid = nla_get_u32(tb[NDA_NH_ID]);
+		neigh->ce_mask |= NEIGH_ATTR_NHID;
+	}
+
 	/*
 	 * Get the bridge index for AF_BRIDGE family entries
 	 */
@@ -511,6 +548,9 @@
 	if (n->ce_mask & NEIGH_ATTR_VLAN)
 		nl_dump(p, "vlan %d ", n->n_vlan);
 
+	if (n->ce_mask & NEIGH_ATTR_NHID)
+		nl_dump(p, "nhid %u ", n->n_nhid);
+
 	if (n->ce_mask & NEIGH_ATTR_MASTER) {
 		if (link_cache)
 			nl_dump(p, "%s ", rtnl_link_i2name(link_cache, n->n_master,
@@ -721,6 +761,9 @@
 	if (tmpl->ce_mask & NEIGH_ATTR_VLAN)
 		NLA_PUT_U16(msg, NDA_VLAN, tmpl->n_vlan);
 
+	if (tmpl->ce_mask & NEIGH_ATTR_NHID)
+		NLA_PUT_U32(msg, NDA_NH_ID, tmpl->n_nhid);
+
 	*result = msg;
 	return 0;
 
@@ -771,7 +814,7 @@
  *  - Destination address (rtnl_neigh_set_dst())
  *  - Link layer address (rtnl_neigh_set_lladdr())
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
 {
@@ -826,7 +869,7 @@
  * sends the request to the kernel and waits for the next ACK to be
  * received and thus blocks until the request has been fullfilled.
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
 		      int flags)
@@ -1066,6 +1109,20 @@
 	return neigh->n_master;
 }
 
+void rtnl_neigh_set_nhid(struct rtnl_neigh *neigh, uint32_t nhid)
+{
+	neigh->n_nhid = nhid;
+	neigh->ce_mask |= NEIGH_ATTR_NHID;
+}
+
+int rtnl_neigh_get_nhid(struct rtnl_neigh *neigh, uint32_t *out_val) {
+	if (!(neigh->ce_mask & NEIGH_ATTR_NHID))
+		return -NLE_NOATTR;
+
+	*out_val = neigh->n_nhid;
+	return NLE_SUCCESS;
+}
+
 /** @} */
 
 static struct nl_object_ops neigh_obj_ops = {
@@ -1107,12 +1164,12 @@
 	.co_obj_ops		= &neigh_obj_ops,
 };
 
-static void __init neigh_init(void)
+static void _nl_init neigh_init(void)
 {
 	nl_cache_mngt_register(&rtnl_neigh_ops);
 }
 
-static void __exit neigh_exit(void)
+static void _nl_exit neigh_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_neigh_ops);
 }
diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c
index c4244fc..a699867 100644
--- a/lib/route/neightbl.c
+++ b/lib/route/neightbl.c
@@ -10,14 +10,130 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/neightbl.h>
 #include <netlink/route/link.h>
 
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+struct rtnl_neightbl_parms {
+	/**
+	 * Interface index of the device this parameter set is assigned
+	 * to or 0 for the default set.
+	 */
+	uint32_t ntp_ifindex;
+
+	/**
+	 * Number of references to this parameter set.
+	 */
+	uint32_t ntp_refcnt;
+
+	/**
+	 * Queue length for pending arp requests, i.e. the number of
+	 * packets which are accepted from other layers while the
+	 * neighbour address is still being resolved
+	 */
+	uint32_t ntp_queue_len;
+
+	/**
+	 * Number of requests to send to the user level ARP daemon.
+	 * Specify 0 to disable.
+	 */
+	uint32_t ntp_app_probes;
+
+	/**
+	 * Maximum number of retries for unicast solicitation.
+	 */
+	uint32_t ntp_ucast_probes;
+
+	/**
+	 * Maximum number of retries for multicast solicitation.
+	 */
+	uint32_t ntp_mcast_probes;
+
+	/**
+	 * Base value in milliseconds to ompute reachable time, see RFC2461.
+	 */
+	uint64_t ntp_base_reachable_time;
+
+	/**
+	 * Actual reachable time (read-only)
+	 */
+	uint64_t ntp_reachable_time; /* secs */
+
+	/**
+	 * The time in milliseconds between retransmitted Neighbor
+	 * Solicitation messages.
+	 */
+	uint64_t ntp_retrans_time;
+
+	/**
+	 * Interval in milliseconds to check for stale neighbour
+	 * entries.
+	 */
+	uint64_t ntp_gc_stale_time; /* secs */
+
+	/**
+	 * Delay in milliseconds for the first time probe if
+	 * the neighbour is reachable.
+	 */
+	uint64_t ntp_probe_delay; /* secs */
+
+	/**
+	 * Maximum delay in milliseconds of an answer to a neighbour
+	 * solicitation message.
+	 */
+	uint64_t ntp_anycast_delay;
+
+	/**
+	 * Minimum age in milliseconds before a neighbour entry
+	 * may be replaced.
+	 */
+	uint64_t ntp_locktime;
+
+	/**
+	 * Delay in milliseconds before answering to an ARP request
+	 * for which a proxy ARP entry exists.
+	 */
+	uint64_t ntp_proxy_delay;
+
+	/**
+	 * Queue length for the delayed proxy arp requests.
+	 */
+	uint32_t ntp_proxy_qlen;
+
+	/**
+	 * Mask of available parameter attributes
+	 */
+	uint32_t ntp_mask;
+};
+
+#define NTBLNAMSIZ 32
+
+/**
+ * Neighbour table
+ * @ingroup neightbl
+ */
+struct rtnl_neightbl {
+	NLHDR_COMMON
+
+	char nt_name[NTBLNAMSIZ];
+	uint32_t nt_family;
+	uint32_t nt_gc_thresh1;
+	uint32_t nt_gc_thresh2;
+	uint32_t nt_gc_thresh3;
+	uint64_t nt_gc_interval;
+	struct ndt_config nt_config;
+	struct rtnl_neightbl_parms nt_parms;
+	struct ndt_stats nt_stats;
+};
+
 /** @cond SKIP */
 #define NEIGHTBL_ATTR_FAMILY 0x001
 #define NEIGHTBL_ATTR_STATS 0x002
@@ -56,16 +172,18 @@
 	struct rtnl_neightbl *b = (struct rtnl_neightbl *)_b;
 	uint64_t diff = 0;
 
-#define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family);
-	diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name));
-	diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1);
-	diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2);
-	diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3);
-	diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval);
-
-#undef NT_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(NEIGHTBL_ATTR_FAMILY, a->nt_family != b->nt_family);
+	diff |= _DIFF(NEIGHTBL_ATTR_NAME, strcmp(a->nt_name, b->nt_name));
+	diff |= _DIFF(NEIGHTBL_ATTR_THRESH1,
+		      a->nt_gc_thresh1 != b->nt_gc_thresh1);
+	diff |= _DIFF(NEIGHTBL_ATTR_THRESH2,
+		      a->nt_gc_thresh2 != b->nt_gc_thresh2);
+	diff |= _DIFF(NEIGHTBL_ATTR_THRESH3,
+		      a->nt_gc_thresh3 != b->nt_gc_thresh3);
+	diff |= _DIFF(NEIGHTBL_ATTR_GC_INTERVAL,
+		      a->nt_gc_interval != b->nt_gc_interval);
+#undef _DIFF
 
 	if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) &&
 	    !(b->ce_mask & NEIGHTBL_ATTR_PARMS))
@@ -182,10 +300,10 @@
 		if (err < 0)
 			goto errout;
 
-#define COPY_ENTRY(name, var)                                                  \
-	if (tbp[NDTPA_##name]) {                                               \
-		p->ntp_##var = nla_get_u32(tbp[NDTPA_##name]);                 \
-		p->ntp_mask |= NEIGHTBLPARM_ATTR_##name;                       \
+#define COPY_ENTRY(name, var)                                  \
+	if (tbp[NDTPA_##name]) {                               \
+		p->ntp_##var = nla_get_u32(tbp[NDTPA_##name]); \
+		p->ntp_mask |= NEIGHTBLPARM_ATTR_##name;       \
 	}
 
 		COPY_ENTRY(IFINDEX, ifindex);
@@ -414,7 +532,7 @@
 	if (cache->c_ops != &rtnl_neightbl_ops)
 		return NULL;
 
-	nl_list_for_each_entry (nt, &cache->c_items, ce_list) {
+	nl_list_for_each_entry(nt, &cache->c_items, ce_list) {
 		if (!strcasecmp(nt->nt_name, name) &&
 		    ((!ifindex && !nt->nt_parms.ntp_ifindex) ||
 		     (ifindex && ifindex == nt->nt_parms.ntp_ifindex))) {
@@ -803,12 +921,12 @@
 	.co_obj_ops		= &neightbl_obj_ops,
 };
 
-static void __init neightbl_init(void)
+static void _nl_init neightbl_init(void)
 {
 	nl_cache_mngt_register(&rtnl_neightbl_ops);
 }
 
-static void __exit neightbl_exit(void)
+static void _nl_exit neightbl_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_neightbl_ops);
 }
diff --git a/lib/route/netconf.c b/lib/route/netconf.c
index 50c91bf..7863da6 100644
--- a/lib/route/netconf.c
+++ b/lib/route/netconf.c
@@ -11,14 +11,21 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/netconf.h>
+#include <linux/socket.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/netconf.h>
-#include <linux/netconf.h>
-#include <linux/socket.h>
 #include <netlink/hashtable.h>
 
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-priv-dynamic-core/object-api.h"
+
 /** @cond SKIP */
 #define NETCONF_ATTR_FAMILY		0x0001
 #define NETCONF_ATTR_IFINDEX		0x0002
@@ -270,7 +277,7 @@
 	struct nc_hash_key {
 		int        nc_family;
 		int        nc_index;
-	} __attribute__((packed)) nckey;
+	} _nl_packed nckey;
 
 	nckey_sz = sizeof(nckey);
 	nckey.nc_family = nc->family;
@@ -289,19 +296,19 @@
 	struct rtnl_netconf *b = (struct rtnl_netconf *) _b;
 	uint64_t diff = 0;
 
-#define NETCONF_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NETCONF_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= NETCONF_DIFF(FAMILY,	a->family != b->family);
-	diff |= NETCONF_DIFF(IFINDEX,	a->ifindex != b->ifindex);
-	diff |= NETCONF_DIFF(RP_FILTER,	a->rp_filter != b->rp_filter);
-	diff |= NETCONF_DIFF(FWDING,	a->forwarding != b->forwarding);
-	diff |= NETCONF_DIFF(MC_FWDING,	a->mc_forwarding != b->mc_forwarding);
-	diff |= NETCONF_DIFF(PROXY_NEIGH, a->proxy_neigh != b->proxy_neigh);
-	diff |= NETCONF_DIFF(IGNORE_RT_LINKDWN,
-			a->ignore_routes_linkdown != b->ignore_routes_linkdown);
-	diff |= NETCONF_DIFF(INPUT,	a->input != b->input);
-
-#undef NETCONF_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(NETCONF_ATTR_FAMILY, a->family != b->family);
+	diff |= _DIFF(NETCONF_ATTR_IFINDEX, a->ifindex != b->ifindex);
+	diff |= _DIFF(NETCONF_ATTR_RP_FILTER, a->rp_filter != b->rp_filter);
+	diff |= _DIFF(NETCONF_ATTR_FWDING, a->forwarding != b->forwarding);
+	diff |= _DIFF(NETCONF_ATTR_MC_FWDING,
+		      a->mc_forwarding != b->mc_forwarding);
+	diff |= _DIFF(NETCONF_ATTR_PROXY_NEIGH,
+		      a->proxy_neigh != b->proxy_neigh);
+	diff |= _DIFF(NETCONF_ATTR_IGNORE_RT_LINKDWN,
+		      a->ignore_routes_linkdown != b->ignore_routes_linkdown);
+	diff |= _DIFF(NETCONF_ATTR_INPUT, a->input != b->input);
+#undef _DIFF
 
 	return diff;
 }
@@ -553,12 +560,12 @@
 	.co_obj_ops		= &netconf_obj_ops,
 };
 
-static void __init netconf_init(void)
+static void _nl_init netconf_init(void)
 {
 	nl_cache_mngt_register(&rtnl_netconf_ops);
 }
 
-static void __exit netconf_exit(void)
+static void _nl_exit netconf_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_netconf_ops);
 }
diff --git a/include/netlink-private/route/nexthop-encap.h b/lib/route/nexthop-encap.h
similarity index 100%
rename from include/netlink-private/route/nexthop-encap.h
rename to lib/route/nexthop-encap.h
diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c
index 6835137..962f2ba 100644
--- a/lib/route/nexthop.c
+++ b/lib/route/nexthop.c
@@ -9,13 +9,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/route.h>
 
+#include "nexthop-encap.h"
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /** @cond SKIP */
 #define NH_ATTR_FLAGS   0x000001
 #define NH_ATTR_WEIGHT  0x000002
@@ -108,29 +112,26 @@
 int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
 			  uint32_t attrs, int loose)
 {
-	int diff = 0;
+	uint32_t diff = 0;
 
-#define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= NH_DIFF(IFINDEX,	a->rtnh_ifindex != b->rtnh_ifindex);
-	diff |= NH_DIFF(WEIGHT,		a->rtnh_weight != b->rtnh_weight);
-	diff |= NH_DIFF(REALMS,		a->rtnh_realms != b->rtnh_realms);
-	diff |= NH_DIFF(GATEWAY,	nl_addr_cmp(a->rtnh_gateway,
-						    b->rtnh_gateway));
-	diff |= NH_DIFF(NEWDST,		nl_addr_cmp(a->rtnh_newdst,
-						    b->rtnh_newdst));
-	diff |= NH_DIFF(VIA,		nl_addr_cmp(a->rtnh_via,
-						    b->rtnh_via));
-	diff |= NH_DIFF(ENCAP,		nh_encap_compare(a->rtnh_encap,
-							 b->rtnh_encap));
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
+	diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight);
+	diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms);
+	diff |= _DIFF(NH_ATTR_GATEWAY,
+		      nl_addr_cmp(a->rtnh_gateway, b->rtnh_gateway));
+	diff |= _DIFF(NH_ATTR_NEWDST,
+		      nl_addr_cmp(a->rtnh_newdst, b->rtnh_newdst));
+	diff |= _DIFF(NH_ATTR_VIA, nl_addr_cmp(a->rtnh_via, b->rtnh_via));
+	diff |= _DIFF(NH_ATTR_ENCAP,
+		      nh_encap_compare(a->rtnh_encap, b->rtnh_encap));
 
 	if (loose)
-		diff |= NH_DIFF(FLAGS,
-			  (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask);
+		diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) &
+						     b->rtnh_flag_mask);
 	else
-		diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags);
-	
-#undef NH_DIFF
+		diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags);
+#undef _DIFF
 
 	return diff;
 }
diff --git a/lib/route/nexthop_encap.c b/lib/route/nexthop_encap.c
index 2382886..226b901 100644
--- a/lib/route/nexthop_encap.c
+++ b/lib/route/nexthop_encap.c
@@ -1,10 +1,12 @@
 /* SPDX-License-Identifier: LGPL-2.1-only */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/types.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
 #include <linux/lwtunnel.h>
 
+#include "nl-route.h"
+#include "nexthop-encap.h"
+
 static struct lwtunnel_encap_type {
 	const char *name;
 	struct nh_encap_ops *ops;
diff --git a/lib/route/nh.c b/lib/route/nh.c
new file mode 100644
index 0000000..1072172
--- /dev/null
+++ b/lib/route/nh.c
@@ -0,0 +1,590 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+#include "nl-default.h"
+
+#include <linux/nexthop.h>
+
+#include <netlink/route/nh.h>
+#include <netlink/hashtable.h>
+#include <netlink/route/nexthop.h>
+
+#include "nl-aux-route/nl-route.h"
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+/** @cond SKIP */
+struct rtnl_nh {
+	NLHDR_COMMON
+
+	uint8_t nh_family;
+	uint32_t nh_flags;
+
+	uint32_t nh_id;
+	uint32_t nh_group_type;
+	nl_nh_group_t *nh_group;
+	uint32_t nh_oif;
+	struct nl_addr *nh_gateway;
+};
+
+#define NH_ATTR_FLAGS (1 << 0)
+#define NH_ATTR_ID (1 << 1)
+#define NH_ATTR_GROUP (1 << 2)
+#define NH_ATTR_FLAG_BLACKHOLE (1 << 3)
+#define NH_ATTR_OIF (1 << 4)
+#define NH_ATTR_GATEWAY (1 << 5)
+#define NH_ATTR_FLAG_GROUPS (1 << 6)
+#define NH_ATTR_FLAG_FDB (1 << 8)
+/** @endcond */
+
+struct nla_policy rtnl_nh_policy[NHA_MAX + 1] = {
+	[NHA_UNSPEC] = { .type = NLA_UNSPEC },
+	[NHA_ID] = { .type = NLA_U32 },
+	[NHA_GROUP] = { .type = NLA_NESTED },
+	[NHA_GROUP_TYPE] = { .type = NLA_U16 },
+	[NHA_BLACKHOLE] = { .type = NLA_UNSPEC },
+	[NHA_OIF] = { .type = NLA_U32 },
+};
+
+static struct nl_cache_ops rtnl_nh_ops;
+static struct nl_object_ops nh_obj_ops;
+
+static nl_nh_group_t *rtnl_nh_grp_alloc(unsigned size)
+{
+	nl_nh_group_t *nhg;
+
+	_nl_assert(size <= (unsigned)INT_MAX);
+
+	if (!(nhg = calloc(1, sizeof(*nhg))))
+		return NULL;
+
+	nhg->size = size;
+
+	if (!(nhg->entries = calloc(size, sizeof(*nhg->entries)))) {
+		free(nhg);
+		return NULL;
+	}
+
+	nhg->ce_refcnt = 1;
+
+	return nhg;
+}
+
+static void rtnl_nh_grp_put(nl_nh_group_t *nhg)
+{
+	if (!nhg)
+		return;
+
+	_nl_assert(nhg->ce_refcnt > 0);
+
+	nhg->ce_refcnt--;
+
+	if (nhg->ce_refcnt > 0)
+		return;
+
+	free(nhg);
+}
+
+static int rtnh_nh_grp_cmp(const nl_nh_group_t *a, const nl_nh_group_t *b)
+{
+	unsigned i;
+
+	_NL_CMP_SELF(a, b);
+	_NL_CMP_DIRECT(a->size, b->size);
+	for (i = 0; i < a->size; i++) {
+		_NL_CMP_DIRECT(a->entries[i].nh_id, b->entries[i].nh_id);
+		_NL_CMP_DIRECT(a->entries[i].weight, b->entries[i].weight);
+	}
+	return 0;
+}
+
+static int rtnh_nh_grp_clone(nl_nh_group_t *src, nl_nh_group_t **dst)
+{
+	nl_nh_group_t *ret;
+	unsigned i;
+
+	ret = rtnl_nh_grp_alloc(src->size);
+
+	if (!ret)
+		return -NLE_NOMEM;
+
+	for (i = 0; i < src->size; i++) {
+		ret->entries[i].nh_id = src->entries[i].nh_id;
+		ret->entries[i].weight = src->entries[i].weight;
+	}
+
+	*dst = ret;
+
+	return NLE_SUCCESS;
+}
+
+struct rtnl_nh *rtnl_nh_alloc(void)
+{
+	return (struct rtnl_nh *)nl_object_alloc(&nh_obj_ops);
+}
+
+static int nh_clone(struct nl_object *_src, struct nl_object *_dst)
+{
+	struct rtnl_nh *dst = nl_object_priv(_dst);
+	struct rtnl_nh *src = nl_object_priv(_src);
+
+	dst->nh_flags = src->nh_flags;
+	dst->nh_family = src->nh_family;
+	dst->nh_id = src->nh_id;
+	dst->nh_oif = src->nh_oif;
+	dst->ce_mask = src->ce_mask;
+
+	if (src->nh_gateway) {
+		dst->nh_gateway = nl_addr_clone(src->nh_gateway);
+		if (!dst->nh_gateway) {
+			return -NLE_NOMEM;
+		}
+	}
+
+	if (src->nh_group) {
+		if (rtnh_nh_grp_clone(src->nh_group, &dst->nh_group) < 0) {
+			return -NLE_NOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static void nh_free(struct nl_object *obj)
+{
+	struct rtnl_nh *nh = nl_object_priv(obj);
+	nl_addr_put(nh->nh_gateway);
+
+	if (nh->nh_group)
+		rtnl_nh_grp_put(nh->nh_group);
+}
+
+void rtnl_nh_put(struct rtnl_nh *nh)
+{
+	struct nl_object *obj = (struct nl_object *)nh;
+
+	nl_object_put(obj);
+}
+
+static void nexthop_keygen(struct nl_object *obj, uint32_t *hashkey,
+			   uint32_t table_sz)
+{
+	struct rtnl_nh *nexthop = nl_object_priv(obj);
+	unsigned int lkey_sz;
+	struct nexthop_hash_key {
+		uint32_t nh_id;
+	} __attribute__((packed)) lkey;
+
+	lkey_sz = sizeof(lkey);
+	lkey.nh_id = nexthop->nh_id;
+
+	*hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz;
+
+	return;
+}
+
+int rtnl_nh_set_gateway(struct rtnl_nh *nexthop, struct nl_addr *addr)
+{
+	if (nexthop->ce_mask & NH_ATTR_GATEWAY) {
+		nl_addr_put(nexthop->nh_gateway);
+	}
+
+	nexthop->nh_gateway = nl_addr_clone(addr);
+	nexthop->ce_mask |= NH_ATTR_GATEWAY;
+
+	return 0;
+}
+
+struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *nexthop)
+{
+	return nexthop->nh_gateway;
+}
+
+int rtnl_nh_set_fdb(struct rtnl_nh *nexthop, int value)
+{
+	if (value)
+		nexthop->ce_mask |= NH_ATTR_FLAG_FDB;
+	else
+		nexthop->ce_mask &= ~NH_ATTR_FLAG_FDB;
+
+	return 0;
+}
+
+int rtnl_nh_get_oif(struct rtnl_nh *nexthop)
+{
+	if (nexthop->ce_mask & NH_ATTR_OIF)
+		return nexthop->nh_oif;
+
+	return 0;
+}
+
+int rtnl_nh_get_fdb(struct rtnl_nh *nexthop)
+{
+	return nexthop->ce_mask & NH_ATTR_FLAG_FDB;
+}
+
+int rtnl_nh_get_group_entry(struct rtnl_nh *nexthop, int n)
+{
+	if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group)
+		return -NLE_MISSING_ATTR;
+
+	if (n < 0 || ((unsigned)n) >= nexthop->nh_group->size)
+		return -NLE_INVAL;
+
+	return nexthop->nh_group->entries[n].nh_id;
+}
+
+int rtnl_nh_get_group_size(struct rtnl_nh *nexthop)
+{
+	if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group)
+		return -NLE_MISSING_ATTR;
+
+	_nl_assert(nexthop->nh_group->size <= INT_MAX);
+
+	return (int)nexthop->nh_group->size;
+}
+
+static int rtnl_nh_grp_info(unsigned size, const struct nexthop_grp *vi,
+			    nl_nh_group_t **nvi)
+{
+	nl_nh_group_t *ret;
+	unsigned i;
+
+	if (!(ret = rtnl_nh_grp_alloc(size)))
+		return -NLE_NOMEM;
+
+	for (i = 0; i < size; i++) {
+		ret->entries[i].nh_id = vi[i].id;
+		ret->entries[i].weight = vi[i].weight;
+	}
+
+	*nvi = ret;
+	return NLE_SUCCESS;
+}
+
+int rtnl_nh_get_id(struct rtnl_nh *nh)
+{
+	if (nh->ce_mask & NH_ATTR_ID)
+		return nh->nh_id;
+
+	return -NLE_INVAL;
+}
+
+static int nexthop_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+			      struct nlmsghdr *n, struct nl_parser_param *pp)
+{
+	_nl_auto_rtnl_nh struct rtnl_nh *nexthop = NULL;
+	struct nhmsg *ifi;
+	struct nlattr *tb[NHA_MAX + 1];
+	int err;
+	int family;
+
+	nexthop = rtnl_nh_alloc();
+	if (nexthop == NULL)
+		return -NLE_NOMEM;
+
+	nexthop->ce_msgtype = n->nlmsg_type;
+
+	if (!nlmsg_valid_hdr(n, sizeof(*ifi)))
+		return -NLE_MSG_TOOSHORT;
+
+	ifi = nlmsg_data(n);
+	family = ifi->nh_family;
+	nexthop->nh_family = family;
+	nexthop->nh_flags = ifi->nh_flags;
+	nexthop->ce_mask = (NH_ATTR_FLAGS);
+
+	err = nlmsg_parse(n, sizeof(*ifi), tb, NHA_MAX, rtnl_nh_policy);
+	if (err < 0)
+		return err;
+
+	if (tb[NHA_ID]) {
+		nexthop->nh_id = nla_get_u32(tb[NHA_ID]);
+		nexthop->ce_mask |= NH_ATTR_ID;
+	}
+
+	if (tb[NHA_OIF]) {
+		nexthop->nh_oif = nla_get_u32(tb[NHA_OIF]);
+		nexthop->ce_mask |= NH_ATTR_OIF;
+	}
+
+	if (tb[NHA_GATEWAY]) {
+		nexthop->nh_gateway =
+			nl_addr_alloc_attr(tb[NHA_GATEWAY], family);
+		nexthop->ce_mask |= NH_ATTR_GATEWAY;
+	}
+
+	if (tb[NHA_BLACKHOLE]) {
+		nexthop->ce_mask |= NH_ATTR_FLAG_BLACKHOLE;
+	}
+
+	if (tb[NHA_GROUPS]) {
+		nexthop->ce_mask |= NH_ATTR_FLAG_GROUPS;
+	}
+
+	if (tb[NHA_FDB]) {
+		nexthop->ce_mask |= NH_ATTR_FLAG_FDB;
+	}
+
+	if (tb[NHA_GROUP]) {
+		nl_nh_group_t *nh_group = NULL;
+		const void *data;
+		unsigned size;
+		unsigned len;
+
+		data = nla_data(tb[NHA_GROUP]);
+		len = nla_len(tb[NHA_GROUP]);
+		size = len / sizeof(struct nexthop_grp);
+
+		err = rtnl_nh_grp_info(size, (const struct nexthop_grp *)data,
+				       &nh_group);
+		if (err < 0) {
+			return err;
+		}
+
+		nexthop->nh_group = nh_group;
+		nexthop->ce_mask |= NH_ATTR_GROUP;
+	}
+
+	return pp->pp_cb((struct nl_object *)nexthop, pp);
+}
+
+static int nexthop_request_update(struct nl_cache *cache, struct nl_sock *sk)
+{
+	_nl_auto_nl_msg struct nl_msg *msg = NULL;
+	int family = cache->c_iarg1;
+	struct nhmsg hdr = { .nh_family = family };
+	int err;
+
+	msg = nlmsg_alloc_simple(RTM_GETNEXTHOP, NLM_F_DUMP);
+	if (!msg)
+		return -NLE_NOMEM;
+
+	if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0)
+		return -NLE_MSGSIZE;
+
+	err = nl_send_auto(sk, msg);
+	if (err < 0)
+		return err;
+
+	return NLE_SUCCESS;
+}
+
+static void dump_nh_group(nl_nh_group_t *group, struct nl_dump_params *dp)
+{
+	unsigned i;
+
+	nl_dump(dp, " nh_grp:");
+	for (i = 0; i < group->size; i++) {
+		nl_dump(dp, " %u", group->entries[i].nh_id);
+	}
+}
+
+static void nh_dump_line(struct nl_object *obj, struct nl_dump_params *dp)
+{
+	struct nl_cache *cache;
+	char buf[128];
+	struct rtnl_nh *nh = nl_object_priv(obj);
+
+	cache = nl_cache_mngt_require_safe("route/nh");
+
+	if (nh->ce_mask & NH_ATTR_ID)
+		nl_dump(dp, "nhid %u", nh->nh_id);
+
+	if (nh->ce_mask & NH_ATTR_OIF)
+		nl_dump(dp, " oif %d", nh->nh_oif);
+
+	if (nh->ce_mask & NH_ATTR_GATEWAY)
+		nl_dump(dp, " via %s",
+			nl_addr2str(nh->nh_gateway, buf, sizeof(buf)));
+
+	if (nh->ce_mask & NH_ATTR_FLAG_BLACKHOLE)
+		nl_dump(dp, " blackhole");
+
+	if (nh->ce_mask & NH_ATTR_FLAG_GROUPS)
+		nl_dump(dp, " groups");
+
+	if (nh->ce_mask & NH_ATTR_GROUP)
+		dump_nh_group(nh->nh_group, dp);
+
+	if (nh->ce_mask & NH_ATTR_FLAG_FDB)
+		nl_dump(dp, " fdb");
+
+	nl_dump(dp, "\n");
+
+	if (cache)
+		nl_cache_put(cache);
+}
+
+static void nh_dump_details(struct nl_object *nh, struct nl_dump_params *dp)
+{
+	nh_dump_line(nh, dp);
+}
+
+static uint64_t nh_compare(struct nl_object *a, struct nl_object *b,
+			   uint64_t attrs, int loose)
+{
+	int diff = 0;
+	struct rtnl_nh *src = nl_object_priv(a);
+	struct rtnl_nh *dst = nl_object_priv(b);
+
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(NH_ATTR_ID, src->nh_id != dst->nh_id);
+	diff |= _DIFF(NH_ATTR_GATEWAY,
+		      nl_addr_cmp(src->nh_gateway, dst->nh_gateway));
+	diff |= _DIFF(NH_ATTR_OIF, src->nh_oif != dst->nh_oif);
+	diff |= _DIFF(NH_ATTR_GROUP,
+		      rtnh_nh_grp_cmp(src->nh_group, dst->nh_group));
+	diff |= _DIFF(NH_ATTR_FLAG_FDB, false);
+	diff |= _DIFF(NH_ATTR_FLAG_GROUPS, false);
+	diff |= _DIFF(NH_ATTR_FLAG_BLACKHOLE, false);
+#undef _DIFF
+
+	return diff;
+}
+
+struct rtnl_nh *rtnl_nh_get(struct nl_cache *cache, int nhid)
+{
+	struct rtnl_nh *nh;
+
+	if (cache->c_ops != &rtnl_nh_ops)
+		return NULL;
+
+	nl_list_for_each_entry(nh, &cache->c_items, ce_list) {
+		if (nh->nh_id == nhid) {
+			nl_object_get((struct nl_object *)nh);
+			return nh;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * Allocate nexthop cache and fill in all configured nexthops.
+ * @arg sk		Netnexthop socket.
+ * @arg family		nexthop address family or AF_UNSPEC
+ * @arg result		Pointer to store resulting cache.
+ * @arg flags		Flags to set in nexthop cache before filling
+ *
+ * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop
+ * message is sent to the kernel requesting a full dump of all configured
+ * nexthops. The returned messages are parsed and filled into the cache. If
+ * the operation succeeds, the resulting cache will contain a nexthop object for
+ * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the
+ * cache is still empty.
+ *
+ * If \c family is set to an address family other than \c AF_UNSPEC the
+ * contents of the cache can be limited to a specific address family.
+ * Currently the following address families are supported:
+ * - AF_BRIDGE
+ * - AF_INET6
+ *
+ * @route_doc{nexthop_list, Get List of nexthops}
+ * @see rtnl_nh_get()
+ * @see rtnl_nh_get_by_name()
+ * @return 0 on success or a negative error code.
+ */
+static int rtnl_nh_alloc_cache_flags(struct nl_sock *sk, int family,
+				     struct nl_cache **result,
+				     unsigned int flags)
+{
+	struct nl_cache *cache;
+	int err;
+
+	cache = nl_cache_alloc(&rtnl_nh_ops);
+	if (!cache)
+		return -NLE_NOMEM;
+
+	cache->c_iarg1 = family;
+
+	if (flags)
+		nl_cache_set_flags(cache, flags);
+
+	if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
+		nl_cache_free(cache);
+		return err;
+	}
+
+	*result = cache;
+	return 0;
+}
+
+/**
+ * Allocate nexthop cache and fill in all configured nexthops.
+ * @arg sk		Netnexthop socket.
+ * @arg family		nexthop address family or AF_UNSPEC
+ * @arg result		Pointer to store resulting cache.
+ *
+ * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop
+ * message is sent to the kernel requesting a full dump of all configured
+ * nexthops. The returned messages are parsed and filled into the cache. If
+ * the operation succeeds, the resulting cache will contain a nexthop object for
+ * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the
+ * cache is still empty.
+ *
+ * If \c family is set to an address family other than \c AF_UNSPEC the
+ * contents of the cache can be limited to a specific address family.
+ * Currently the following address families are supported:
+ * - AF_BRIDGE
+ * - AF_INET6
+ *
+ * @route_doc{nexthop_list, Get List of nexthops}
+ * @see rtnl_nh_get()
+ * @see rtnl_nh_get_by_name()
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nh_alloc_cache(struct nl_sock *sk, int family,
+			struct nl_cache **result)
+{
+	return rtnl_nh_alloc_cache_flags(sk, family, result, 0);
+}
+
+static struct nl_object_ops nh_obj_ops = {
+  .oo_name		= "route/nh",
+  .oo_size		= sizeof(struct rtnl_nh),
+  .oo_free_data		= nh_free,
+  .oo_clone		= nh_clone,
+  .oo_dump = {
+      [NL_DUMP_LINE]	= nh_dump_line,
+      [NL_DUMP_DETAILS]	= nh_dump_details,
+  },
+  .oo_compare		= nh_compare,
+  .oo_keygen		= nexthop_keygen,
+  .oo_attrs2str		= rtnl_route_nh_flags2str,
+  .oo_id_attrs		= NH_ATTR_ID,
+};
+
+static struct nl_af_group nh_groups[] = {
+	{ AF_UNSPEC, RTNLGRP_NEXTHOP },
+	{ END_OF_GROUP_LIST },
+};
+
+static struct nl_cache_ops rtnl_nh_ops = {
+  .co_name		= "route/nh",
+  .co_hdrsize		= sizeof(struct nhmsg),
+  .co_msgtypes		= {
+          { RTM_NEWNEXTHOP, NL_ACT_NEW, "new" },
+          { RTM_DELNEXTHOP, NL_ACT_DEL, "del" },
+          { RTM_GETNEXTHOP, NL_ACT_GET, "get" },
+          END_OF_MSGTYPES_LIST,
+          },
+  .co_protocol  = NETLINK_ROUTE,
+  .co_groups		= nh_groups,
+  .co_request_update	= nexthop_request_update,
+  .co_msg_parser		= nexthop_msg_parser,
+  .co_obj_ops		= &nh_obj_ops,
+};
+
+static void _nl_init nexthop_init(void)
+{
+	nl_cache_mngt_register(&rtnl_nh_ops);
+}
+
+static void _nl_exit nexthop_exit(void)
+{
+	nl_cache_mngt_unregister(&rtnl_nh_ops);
+}
diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c
index d30acc2..a780291 100644
--- a/lib/route/nh_encap_mpls.c
+++ b/lib/route/nh_encap_mpls.c
@@ -1,12 +1,15 @@
 /* SPDX-License-Identifier: LGPL-2.1-only */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/types.h>
-#include <netlink-private/route/nexthop-encap.h>
-#include <netlink/route/nexthop.h>
+#include "nl-default.h"
+
 #include <linux/mpls_iptunnel.h>
 #include <linux/lwtunnel.h>
 
+#include <netlink/route/nexthop.h>
+
+#include "nl-route.h"
+#include "nexthop-encap.h"
+
 struct mpls_iptunnel_encap {
 	struct nl_addr *dst;
 	uint8_t ttl;
diff --git a/lib/route/nl-route.h b/lib/route/nl-route.h
new file mode 100644
index 0000000..28d0166
--- /dev/null
+++ b/lib/route/nl-route.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __LIB_ROUTE_NL_ROUTE_H__
+#define __LIB_ROUTE_NL_ROUTE_H__
+
+#include <netlink/route/tc.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
+#include "nl-aux-core/nl-core.h"
+
+/*****************************************************************************/
+
+struct rtnl_link_map {
+	uint64_t lm_mem_start;
+	uint64_t lm_mem_end;
+	uint64_t lm_base_addr;
+	uint16_t lm_irq;
+	uint8_t lm_dma;
+	uint8_t lm_port;
+};
+
+#define IFQDISCSIZ 32
+
+struct rtnl_link {
+	NLHDR_COMMON
+
+	char l_name[IFNAMSIZ];
+	uint32_t l_family;
+	uint32_t l_arptype;
+	uint32_t l_index;
+	uint32_t l_flags;
+	uint32_t l_change;
+	uint32_t l_mtu;
+	uint32_t l_link;
+	int32_t l_link_netnsid;
+	uint32_t l_txqlen;
+	uint32_t l_weight;
+	uint32_t l_master;
+	struct nl_addr *l_addr;
+	struct nl_addr *l_bcast;
+	char l_qdisc[IFQDISCSIZ];
+	struct rtnl_link_map l_map;
+	uint64_t l_stats[RTNL_LINK_STATS_MAX + 1];
+	uint32_t l_flag_mask;
+	uint32_t l_num_vf;
+	uint8_t l_operstate;
+	uint8_t l_linkmode;
+	/* 2 byte hole */
+	char *l_info_kind;
+	char *l_info_slave_kind;
+	struct rtnl_link_info_ops *l_info_ops;
+	void *l_af_data[AF_MAX];
+	void *l_info;
+	char *l_ifalias;
+	uint32_t l_promiscuity;
+	uint32_t l_num_tx_queues;
+	uint32_t l_num_rx_queues;
+	uint32_t l_gso_max_segs;
+	uint32_t l_gso_max_size;
+	uint32_t l_group;
+	uint8_t l_carrier;
+	/* 3 byte hole */
+	uint32_t l_carrier_changes;
+	struct rtnl_link_af_ops *l_af_ops;
+	struct nl_data *l_phys_port_id;
+	char l_phys_port_name[IFNAMSIZ];
+	struct nl_data *l_phys_switch_id;
+	int l_ns_fd;
+	pid_t l_ns_pid;
+	struct rtnl_link_vf *l_vf_list;
+};
+
+struct rtnl_nh_encap {
+	struct nh_encap_ops *ops;
+	void *priv; /* private data for encap type */
+};
+
+struct rtnl_nexthop {
+	uint8_t rtnh_flags;
+	uint8_t rtnh_flag_mask;
+	uint8_t rtnh_weight;
+	/* 1 byte spare */
+	uint32_t rtnh_ifindex;
+	struct nl_addr *rtnh_gateway;
+	uint32_t ce_mask; /* HACK to support attr macros */
+	struct nl_list_head rtnh_list;
+	uint32_t rtnh_realms;
+	struct nl_addr *rtnh_newdst;
+	struct nl_addr *rtnh_via;
+	struct rtnl_nh_encap *rtnh_encap;
+};
+
+struct rtnl_ratespec {
+	uint64_t rs_rate64;
+	uint16_t rs_overhead;
+	int16_t rs_cell_align;
+	uint16_t rs_mpu;
+	uint8_t rs_cell_log;
+};
+
+#define TCKINDSIZ 32
+
+#define NL_TC_GENERIC(pre)                           \
+	NLHDR_COMMON                                 \
+	uint32_t pre##_family;                       \
+	uint32_t pre##_ifindex;                      \
+	uint32_t pre##_handle;                       \
+	uint32_t pre##_parent;                       \
+	uint32_t pre##_info;                         \
+	uint32_t pre##_mtu;                          \
+	uint32_t pre##_mpu;                          \
+	uint32_t pre##_overhead;                     \
+	uint32_t pre##_linktype;                     \
+	char pre##_kind[TCKINDSIZ];                  \
+	struct nl_data *pre##_opts;                  \
+	uint64_t pre##_stats[RTNL_TC_STATS_MAX + 1]; \
+	struct nl_data *pre##_xstats;                \
+	struct nl_data *pre##_subdata;               \
+	struct rtnl_link *pre##_link;                \
+	struct rtnl_tc_ops *pre##_ops;               \
+	enum rtnl_tc_type pre##_type;                \
+	uint32_t pre##_chain
+
+struct rtnl_tc {
+	NL_TC_GENERIC(tc);
+};
+
+struct rtnl_qdisc {
+	NL_TC_GENERIC(q);
+};
+
+struct rtnl_act {
+	NL_TC_GENERIC(c);
+	struct rtnl_act *a_next;
+};
+
+/*****************************************************************************/
+
+static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
+				      struct tc_ratespec *src)
+{
+	dst->rs_cell_log = src->cell_log;
+	dst->rs_overhead = src->overhead;
+	dst->rs_cell_align = src->cell_align;
+	dst->rs_mpu = src->mpu;
+	dst->rs_rate64 = src->rate;
+}
+
+static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
+				       struct rtnl_ratespec *src)
+{
+	dst->cell_log = src->rs_cell_log;
+	dst->overhead = src->rs_overhead;
+	dst->cell_align = src->rs_cell_align;
+	dst->mpu = src->rs_mpu;
+	dst->rate = src->rs_rate64 > 0xFFFFFFFFull ? 0xFFFFFFFFull :
+						     (uint32_t)src->rs_rate64;
+}
+
+/*****************************************************************************/
+
+static inline int build_sysconf_path(char **strp, const char *filename)
+{
+	char *sysconfdir;
+
+	sysconfdir = getenv("NLSYSCONFDIR");
+
+	if (!sysconfdir)
+		sysconfdir = SYSCONFDIR;
+
+	return asprintf(strp, "%s/%s", sysconfdir, filename);
+}
+
+/*****************************************************************************/
+
+static inline int rtnl_tc_calc_txtime64(int bufsize, uint64_t rate)
+{
+	return ((double)bufsize / (double)rate) * 1000000.0;
+}
+
+static inline int rtnl_tc_calc_bufsize64(int txtime, uint64_t rate)
+{
+	return ((double)txtime * (double)rate) / 1000000.0;
+}
+
+#endif /* __LIB_ROUTE_NL_ROUTE_H__ */
diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c
index 599e593..7f320d9 100644
--- a/lib/route/pktloc.c
+++ b/lib/route/pktloc.c
@@ -25,12 +25,16 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <sys/stat.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/pktloc.h>
 
+#include "nl-route.h"
+
 #include "pktloc_syntax.h"
 #include "pktloc_grammar.h"
 
@@ -242,7 +246,7 @@
 			cb(loc, arg);
 }
 
-static int __init pktloc_init(void)
+static int _nl_init pktloc_init(void)
 {
 	int i;
 
diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l
index ab592d1..2db229d 100644
--- a/lib/route/pktloc_grammar.l
+++ b/lib/route/pktloc_grammar.l
@@ -1,10 +1,10 @@
 %{
- #include <netlink-private/netlink.h>
- #include <netlink-private/tc.h>
+ #include <linux/tc_ematch/tc_em_cmp.h>
+
  #include <netlink/netlink.h>
  #include <netlink/utils.h>
  #include <netlink/route/pktloc.h>
- #include <linux/tc_ematch/tc_em_cmp.h>
+
  #include "pktloc_syntax.h"
 
  int pktloc_get_column(yyscan_t);
diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y
index 3c9326f..661463a 100644
--- a/lib/route/pktloc_syntax.y
+++ b/lib/route/pktloc_syntax.y
@@ -1,9 +1,9 @@
 %{
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/pktloc.h>
+
+#include "nl-route.h"
 %}
 
 %locations
diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c
index 62c4390..67ea358 100644
--- a/lib/route/qdisc.c
+++ b/lib/route/qdisc.c
@@ -9,16 +9,17 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/link.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/class.h>
 #include <netlink/route/classifier.h>
 
+#include "tc-api.h"
+
 static struct nl_cache_ops rtnl_qdisc_ops;
 static struct nl_object_ops qdisc_obj_ops;
 
@@ -587,13 +588,13 @@
 	.oo_id_attrs		= (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
 };
 
-static void __init qdisc_init(void)
+static void _nl_init qdisc_init(void)
 {
 	rtnl_tc_type_register(&qdisc_ops);
 	nl_cache_mngt_register(&rtnl_qdisc_ops);
 }
 
-static void __exit qdisc_exit(void)
+static void _nl_exit qdisc_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_qdisc_ops);
 	rtnl_tc_type_unregister(&qdisc_ops);
diff --git a/lib/route/qdisc/blackhole.c b/lib/route/qdisc/blackhole.c
index c24507a..8d8f4ba 100644
--- a/lib/route/qdisc/blackhole.c
+++ b/lib/route/qdisc/blackhole.c
@@ -9,21 +9,23 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
+
+#include "tc-api.h"
 
 static struct rtnl_tc_ops blackhole_ops = {
 	.to_kind		= "blackhole",
 	.to_type		= RTNL_TC_TYPE_QDISC,
 };
 
-static void __init blackhole_init(void)
+static void _nl_init blackhole_init(void)
 {
 	rtnl_tc_register(&blackhole_ops);
 }
 
-static void __exit blackhole_exit(void)
+static void _nl_exit blackhole_exit(void)
 {
 	rtnl_tc_unregister(&blackhole_ops);
 }
diff --git a/lib/route/qdisc/cbq.c b/lib/route/qdisc/cbq.c
index 62af823..b9a6696 100644
--- a/lib/route/qdisc/cbq.c
+++ b/lib/route/qdisc/cbq.c
@@ -3,17 +3,27 @@
  * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/class.h>
 #include <netlink/route/link.h>
 #include <netlink/route/qdisc/cbq.h>
 #include <netlink/route/cls/police.h>
 
+#include "tc-api.h"
+
+struct rtnl_cbq {
+	struct tc_cbq_lssopt cbq_lss;
+	struct tc_ratespec cbq_rate;
+	struct tc_cbq_wrropt cbq_wrr;
+	struct tc_cbq_ovl cbq_ovl;
+	struct tc_cbq_fopt cbq_fopt;
+	struct tc_cbq_police cbq_police;
+};
+
 /**
  * @ingroup qdisc
  * @ingroup class
@@ -183,13 +193,13 @@
 	},
 };
 
-static void __init cbq_init(void)
+static void _nl_init cbq_init(void)
 {
 	rtnl_tc_register(&cbq_qdisc_ops);
 	rtnl_tc_register(&cbq_class_ops);
 }
 
-static void __exit cbq_exit(void)
+static void _nl_exit cbq_exit(void)
 {
 	rtnl_tc_unregister(&cbq_qdisc_ops);
 	rtnl_tc_unregister(&cbq_class_ops);
diff --git a/lib/route/qdisc/dsmark.c b/lib/route/qdisc/dsmark.c
index 07f938c..f5718f9 100644
--- a/lib/route/qdisc/dsmark.c
+++ b/lib/route/qdisc/dsmark.c
@@ -10,16 +10,30 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/qdisc.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/class.h>
 #include <netlink/route/qdisc/dsmark.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_dsmark_qdisc {
+	uint16_t qdm_indices;
+	uint16_t qdm_default_index;
+	uint32_t qdm_set_tc_index;
+	uint32_t qdm_mask;
+};
+
+struct rtnl_dsmark_class {
+	uint8_t cdm_bmask;
+	uint8_t cdm_value;
+	uint32_t cdm_mask;
+};
+
 #define SCH_DSMARK_ATTR_INDICES		0x1
 #define SCH_DSMARK_ATTR_DEFAULT_INDEX	0x2
 #define SCH_DSMARK_ATTR_SET_TC_INDEX	0x4
@@ -392,13 +406,13 @@
 	.to_msg_fill		= dsmark_class_msg_fill,
 };
 
-static void __init dsmark_init(void)
+static void _nl_init dsmark_init(void)
 {
 	rtnl_tc_register(&dsmark_qdisc_ops);
 	rtnl_tc_register(&dsmark_class_ops);
 }
 
-static void __exit dsmark_exit(void)
+static void _nl_exit dsmark_exit(void)
 {
 	rtnl_tc_unregister(&dsmark_qdisc_ops);
 	rtnl_tc_unregister(&dsmark_class_ops);
diff --git a/lib/route/qdisc/fifo.c b/lib/route/qdisc/fifo.c
index dc6d189..9976803 100644
--- a/lib/route/qdisc/fifo.c
+++ b/lib/route/qdisc/fifo.c
@@ -23,15 +23,21 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/fifo.h>
 #include <netlink/utils.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_fifo {
+	uint32_t qf_limit;
+	uint32_t qf_mask;
+};
+
 #define SCH_FIFO_ATTR_LIMIT 1
 /** @endcond */
 
@@ -148,13 +154,13 @@
 	.to_msg_fill		= fifo_msg_fill,
 };
 
-static void __init fifo_init(void)
+static void _nl_init fifo_init(void)
 {
 	rtnl_tc_register(&pfifo_ops);
 	rtnl_tc_register(&bfifo_ops);
 }
 
-static void __exit fifo_exit(void)
+static void _nl_exit fifo_exit(void)
 {
 	rtnl_tc_unregister(&pfifo_ops);
 	rtnl_tc_unregister(&bfifo_ops);
diff --git a/lib/route/qdisc/fq_codel.c b/lib/route/qdisc/fq_codel.c
index 34f6b44..a44ab22 100644
--- a/lib/route/qdisc/fq_codel.c
+++ b/lib/route/qdisc/fq_codel.c
@@ -11,15 +11,26 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/fq_codel.h>
 #include <netlink/utils.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_fq_codel {
+	int fq_limit;
+	uint32_t fq_target;
+	uint32_t fq_interval;
+	int fq_flows;
+	uint32_t fq_quantum;
+	int fq_ecn;
+	uint32_t fq_mask;
+};
+
 #define SCH_FQ_CODEL_ATTR_TARGET	0x1
 #define SCH_FQ_CODEL_ATTR_LIMIT		0x2
 #define SCH_FQ_CODEL_ATTR_INTERVAL	0x4
@@ -358,12 +369,12 @@
 	.to_msg_fill		= fq_codel_msg_fill,
 };
 
-static void __init fq_codel_init(void)
+static void _nl_init fq_codel_init(void)
 {
 	rtnl_tc_register(&fq_codel_ops);
 }
 
-static void __exit fq_codel_exit(void)
+static void _nl_exit fq_codel_exit(void)
 {
 	rtnl_tc_unregister(&fq_codel_ops);
 }
diff --git a/lib/route/qdisc/hfsc.c b/lib/route/qdisc/hfsc.c
index 0167e97..49c24c7 100644
--- a/lib/route/qdisc/hfsc.c
+++ b/lib/route/qdisc/hfsc.c
@@ -10,18 +10,31 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/class.h>
 #include <netlink/route/link.h>
 #include <netlink/route/qdisc/hfsc.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_hfsc_qdisc {
+	uint32_t qh_defcls;
+	uint32_t qh_mask;
+};
+
+struct rtnl_hfsc_class {
+	struct tc_service_curve ch_rsc;
+	struct tc_service_curve ch_fsc;
+	struct tc_service_curve ch_usc;
+	uint32_t ch_mask;
+};
+
 #define SCH_HFSC_CLS_HAS_RSC		0x001
 #define SCH_HFSC_CLS_HAS_FSC		0x002
 #define SCH_HFSC_CLS_HAS_USC		0x004
@@ -330,13 +343,13 @@
 	.to_msg_fill		= hfsc_class_msg_fill,
 };
 
-static void __init hfsc_init(void)
+static void _nl_init hfsc_init(void)
 {
 	rtnl_tc_register(&hfsc_qdisc_ops);
 	rtnl_tc_register(&hfsc_class_ops);
 }
 
-static void __exit hfsc_exit(void)
+static void _nl_exit hfsc_exit(void)
 {
 	rtnl_tc_unregister(&hfsc_qdisc_ops);
 	rtnl_tc_unregister(&hfsc_class_ops);
diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c
index ebe38f9..28061b9 100644
--- a/lib/route/qdisc/htb.c
+++ b/lib/route/qdisc/htb.c
@@ -12,18 +12,37 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/class.h>
 #include <netlink/route/link.h>
 #include <netlink/route/qdisc/htb.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_htb_qdisc {
+	uint32_t qh_rate2quantum;
+	uint32_t qh_defcls;
+	uint32_t qh_mask;
+	uint32_t qh_direct_pkts;
+};
+
+struct rtnl_htb_class {
+	uint32_t ch_prio;
+	struct rtnl_ratespec ch_rate;
+	struct rtnl_ratespec ch_ceil;
+	uint32_t ch_rbuffer;
+	uint32_t ch_cbuffer;
+	uint32_t ch_quantum;
+	uint32_t ch_mask;
+	uint32_t ch_level;
+};
+
 #define SCH_HTB_HAS_RATE2QUANTUM	0x01
 #define SCH_HTB_HAS_DEFCLS		0x02
 
@@ -727,13 +746,13 @@
 	.to_msg_fill		= htb_class_msg_fill,
 };
 
-static void __init htb_init(void)
+static void _nl_init htb_init(void)
 {
 	rtnl_tc_register(&htb_qdisc_ops);
 	rtnl_tc_register(&htb_class_ops);
 }
 
-static void __exit htb_exit(void)
+static void _nl_exit htb_exit(void)
 {
 	rtnl_tc_unregister(&htb_qdisc_ops);
 	rtnl_tc_unregister(&htb_class_ops);
diff --git a/lib/route/qdisc/ingress.c b/lib/route/qdisc/ingress.c
index 73d2440..5363c26 100644
--- a/lib/route/qdisc/ingress.c
+++ b/lib/route/qdisc/ingress.c
@@ -10,13 +10,14 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/utils.h>
 
+#include "tc-api.h"
+
 struct dumb {
 	uint32_t foo;
 };
@@ -45,12 +46,12 @@
 	.to_msg_fill		= dumb_msg_fill,
 };
 
-static void __init ingress_init(void)
+static void _nl_init ingress_init(void)
 {
 	rtnl_tc_register(&ingress_ops);
 }
 
-static void __exit ingress_exit(void)
+static void _nl_exit ingress_exit(void)
 {
 	rtnl_tc_unregister(&ingress_ops);
 }
diff --git a/lib/route/qdisc/mqprio.c b/lib/route/qdisc/mqprio.c
index c165404..5e9d08f 100644
--- a/lib/route/qdisc/mqprio.c
+++ b/lib/route/qdisc/mqprio.c
@@ -3,15 +3,29 @@
  * Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/mqprio.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_mqprio {
+	uint8_t qm_num_tc;
+	uint8_t qm_prio_map[TC_QOPT_BITMASK + 1];
+	uint8_t qm_hw;
+	uint16_t qm_count[TC_QOPT_MAX_QUEUE];
+	uint16_t qm_offset[TC_QOPT_MAX_QUEUE];
+	uint16_t qm_mode;
+	uint16_t qm_shaper;
+	uint64_t qm_min_rate[TC_QOPT_MAX_QUEUE];
+	uint64_t qm_max_rate[TC_QOPT_MAX_QUEUE];
+	uint32_t qm_mask;
+};
+
 #define SCH_MQPRIO_ATTR_NUMTC           (1 << 0)
 #define SCH_MQPRIO_ATTR_PRIOMAP         (1 << 1)
 #define SCH_MQPRIO_ATTR_HW              (1 << 2)
@@ -591,12 +605,12 @@
 	.to_msg_fill            = mqprio_msg_fill,
 };
 
-static void __init mqprio_init(void)
+static void _nl_init mqprio_init(void)
 {
 	rtnl_tc_register(&mqprio_ops);
 }
 
-static void __exit mqprio_exit(void)
+static void _nl_exit mqprio_exit(void)
 {
 	rtnl_tc_unregister(&mqprio_ops);
 }
diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c
index 0ca1d57..6dde4f0 100644
--- a/lib/route/qdisc/netem.c
+++ b/lib/route/qdisc/netem.c
@@ -12,17 +12,52 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/netem.h>
 
-#include "netlink-private/utils.h"
+#include "tc-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 /** @cond SKIP */
+struct rtnl_netem_corr {
+	uint32_t nmc_delay;
+	uint32_t nmc_loss;
+	uint32_t nmc_duplicate;
+};
+
+struct rtnl_netem_reo {
+	uint32_t nmro_probability;
+	uint32_t nmro_correlation;
+};
+
+struct rtnl_netem_crpt {
+	uint32_t nmcr_probability;
+	uint32_t nmcr_correlation;
+};
+
+struct rtnl_netem_dist {
+	int16_t *dist_data;
+	size_t dist_size;
+};
+
+struct rtnl_netem {
+	uint32_t qnm_latency;
+	uint32_t qnm_limit;
+	uint32_t qnm_loss;
+	uint32_t qnm_gap;
+	uint32_t qnm_duplicate;
+	uint32_t qnm_jitter;
+	uint32_t qnm_mask;
+	struct rtnl_netem_corr qnm_corr;
+	struct rtnl_netem_reo qnm_ro;
+	struct rtnl_netem_crpt qnm_crpt;
+	struct rtnl_netem_dist qnm_dist;
+};
+
 #define SCH_NETEM_ATTR_LATENCY		0x0001
 #define SCH_NETEM_ATTR_LIMIT		0x0002
 #define SCH_NETEM_ATTR_LOSS		0x0004
@@ -686,7 +721,7 @@
  * Set packet duplication correlation probability of netem qdisc.
  * @arg qdisc		Netem qdisc to be modified.
  * @arg prob		New packet duplication correlation probability.
- * @return 0 on sucess or a negative error code.
+ * @return 0 on success or a negative error code.
  */
 void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob)
 {
@@ -979,12 +1014,12 @@
 	.to_msg_fill_raw	= netem_msg_fill_raw,
 };
 
-static void __init netem_init(void)
+static void _nl_init netem_init(void)
 {
 	rtnl_tc_register(&netem_ops);
 }
 
-static void __exit netem_exit(void)
+static void _nl_exit netem_exit(void)
 {
 	rtnl_tc_unregister(&netem_ops);
 }
diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c
index 38c1c1a..f010802 100644
--- a/lib/route/qdisc/plug.c
+++ b/lib/route/qdisc/plug.c
@@ -54,13 +54,19 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc/plug.h>
 
+#include "tc-api.h"
+
+struct rtnl_plug {
+	int action;
+	uint32_t limit;
+};
+
 static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
 {
 	struct rtnl_plug *plug = data;
@@ -158,12 +164,12 @@
 	.to_msg_fill		= plug_msg_fill,
 };
 
-static void __init plug_init(void)
+static void _nl_init plug_init(void)
 {
 	rtnl_tc_register(&plug_ops);
 }
 
-static void __exit plug_exit(void)
+static void _nl_exit plug_exit(void)
 {
 	rtnl_tc_unregister(&plug_ops);
 }
diff --git a/lib/route/qdisc/prio.c b/lib/route/qdisc/prio.c
index 28242a0..e733845 100644
--- a/lib/route/qdisc/prio.c
+++ b/lib/route/qdisc/prio.c
@@ -20,15 +20,22 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/prio.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_prio {
+	uint32_t qp_bands;
+	uint8_t qp_priomap[TC_PRIO_MAX + 1];
+	uint32_t qp_mask;
+};
+
 #define SCH_PRIO_ATTR_BANDS	1
 #define SCH_PRIO_ATTR_PRIOMAP	2
 /** @endcond */
@@ -273,13 +280,13 @@
 	.to_msg_fill		= prio_msg_fill,
 };
 
-static void __init prio_init(void)
+static void _nl_init prio_init(void)
 {
 	rtnl_tc_register(&prio_ops);
 	rtnl_tc_register(&pfifo_fast_ops);
 }
 
-static void __exit prio_exit(void)
+static void _nl_exit prio_exit(void)
 {
 	rtnl_tc_unregister(&prio_ops);
 	rtnl_tc_unregister(&pfifo_fast_ops);
diff --git a/lib/route/qdisc/red.c b/lib/route/qdisc/red.c
index ccab947..e793b78 100644
--- a/lib/route/qdisc/red.c
+++ b/lib/route/qdisc/red.c
@@ -10,15 +10,27 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/red.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_red {
+	uint32_t qr_limit;
+	uint32_t qr_qth_min;
+	uint32_t qr_qth_max;
+	uint8_t qr_flags;
+	uint8_t qr_wlog;
+	uint8_t qr_plog;
+	uint8_t qr_scell_log;
+	uint32_t qr_mask;
+};
+
 #define RED_ATTR_LIMIT		0x01
 #define RED_ATTR_QTH_MIN	0x02
 #define RED_ATTR_QTH_MAX	0x04
@@ -171,12 +183,12 @@
 	.to_msg_fill		= red_msg_fill,
 };
 
-static void __init red_init(void)
+static void _nl_init red_init(void)
 {
 	rtnl_tc_register(&red_ops);
 }
 
-static void __exit red_exit(void)
+static void _nl_exit red_exit(void)
 {
 	rtnl_tc_unregister(&red_ops);
 }
diff --git a/lib/route/qdisc/sfq.c b/lib/route/qdisc/sfq.c
index f52452e..4379889 100644
--- a/lib/route/qdisc/sfq.c
+++ b/lib/route/qdisc/sfq.c
@@ -17,15 +17,25 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/qdisc/sfq.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_sfq {
+	uint32_t qs_quantum;
+	uint32_t qs_perturb;
+	uint32_t qs_limit;
+	uint32_t qs_divisor;
+	uint32_t qs_flows;
+	uint32_t qs_mask;
+};
+
 #define SCH_SFQ_ATTR_QUANTUM	0x01
 #define SCH_SFQ_ATTR_PERTURB	0x02
 #define SCH_SFQ_ATTR_LIMIT	0x04
@@ -237,12 +247,12 @@
 	.to_msg_fill		= sfq_msg_fill,
 };
 
-static void __init sfq_init(void)
+static void _nl_init sfq_init(void)
 {
 	rtnl_tc_register(&sfq_ops);
 }
 
-static void __exit sfq_exit(void)
+static void _nl_exit sfq_exit(void)
 {
 	rtnl_tc_unregister(&sfq_ops);
 }
diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c
index ba8e304..67996eb 100644
--- a/lib/route/qdisc/tbf.c
+++ b/lib/route/qdisc/tbf.c
@@ -9,18 +9,30 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
 #include <netlink/route/qdisc.h>
 #include <netlink/route/class.h>
 #include <netlink/route/link.h>
 #include <netlink/route/qdisc/tbf.h>
 
+#include "tc-api.h"
+
 /** @cond SKIP */
+struct rtnl_tbf {
+	uint32_t qt_limit;
+	struct rtnl_ratespec qt_rate;
+	uint32_t qt_rate_bucket;
+	uint32_t qt_rate_txtime;
+	struct rtnl_ratespec qt_peakrate;
+	uint32_t qt_peakrate_bucket;
+	uint32_t qt_peakrate_txtime;
+	uint32_t qt_mask;
+};
+
 #define TBF_ATTR_LIMIT			0x01
 #define TBF_ATTR_RATE			0x02
 #define TBF_ATTR_PEAKRATE		0x10
@@ -441,12 +453,12 @@
 	.to_msg_fill		= tbf_msg_fill,
 };
 
-static void __init tbf_init(void)
+static void _nl_init tbf_init(void)
 {
 	rtnl_tc_register(&tbf_tc_ops);
 }
 
-static void __exit tbf_exit(void)
+static void _nl_exit tbf_exit(void)
 {
 	rtnl_tc_unregister(&tbf_tc_ops);
 }
diff --git a/lib/route/route.c b/lib/route/route.c
index fcc7459..0a16ff4 100644
--- a/lib/route/route.c
+++ b/lib/route/route.c
@@ -10,8 +10,8 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/nl-auto.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
@@ -20,6 +20,11 @@
 #include <netlink/route/route.h>
 #include <netlink/route/link.h>
 
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-route/nl-route.h"
+
 static struct nl_cache_ops rtnl_route_ops;
 
 static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
@@ -215,12 +220,12 @@
 	.co_obj_ops		= &route_obj_ops,
 };
 
-static void __init route_init(void)
+static void _nl_init route_init(void)
 {
 	nl_cache_mngt_register(&rtnl_route_ops);
 }
 
-static void __exit route_exit(void)
+static void _nl_exit route_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_route_ops);
 }
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c
index 9441b77..ce68259 100644
--- a/lib/route/route_obj.c
+++ b/lib/route/route_obj.c
@@ -24,9 +24,10 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
+#include <linux/in_route.h>
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/utils.h>
@@ -36,9 +37,40 @@
 #include <netlink/route/route.h>
 #include <netlink/route/link.h>
 #include <netlink/route/nexthop.h>
-#include <linux/in_route.h>
+
+#include "nl-route.h"
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nexthop-encap.h"
 
 /** @cond SKIP */
+struct rtnl_route {
+	NLHDR_COMMON
+
+	uint8_t rt_family;
+	uint8_t rt_dst_len;
+	uint8_t rt_src_len;
+	uint8_t rt_tos;
+	uint8_t rt_protocol;
+	uint8_t rt_scope;
+	uint8_t rt_type;
+	uint8_t rt_nmetrics;
+	uint8_t rt_ttl_propagate;
+	uint32_t rt_flags;
+	struct nl_addr *rt_dst;
+	struct nl_addr *rt_src;
+	uint32_t rt_table;
+	uint32_t rt_iif;
+	uint32_t rt_prio;
+	uint32_t rt_metrics[RTAX_MAX];
+	uint32_t rt_metrics_mask;
+	uint32_t rt_nr_nh;
+	struct nl_addr *rt_pref_src;
+	struct nl_list_head rt_nexthops;
+	struct rtnl_rtcacheinfo rt_cacheinfo;
+	uint32_t rt_flag_mask;
+};
+
 #define ROUTE_ATTR_FAMILY    0x000001
 #define ROUTE_ATTR_TOS       0x000002
 #define ROUTE_ATTR_TABLE     0x000004
@@ -145,7 +177,8 @@
 		nl_dump(p, "cache ");
 
 	if (!(r->ce_mask & ROUTE_ATTR_DST) ||
-	    nl_addr_get_len(r->rt_dst) == 0)
+	    (nl_addr_get_prefixlen(r->rt_dst) == 0 &&
+	     nl_addr_get_len(r->rt_dst) > 0 && nl_addr_iszero(r->rt_dst)))
 		nl_dump(p, "default ");
 	else
 		nl_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
@@ -311,7 +344,7 @@
 		uint32_t	rt_table;
 		uint32_t	rt_prio;
 		char 		rt_addr[0];
-	} __attribute__((packed)) *rkey = NULL;
+	} _nl_packed *rkey = NULL;
 #ifdef NL_DEBUG
 	char buf[INET6_ADDRSTRLEN+5];
 #endif
@@ -368,22 +401,21 @@
 	int i, found;
 	uint64_t diff = 0;
 
-#define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= ROUTE_DIFF(FAMILY,	a->rt_family != b->rt_family);
-	diff |= ROUTE_DIFF(TOS,		a->rt_tos != b->rt_tos);
-	diff |= ROUTE_DIFF(TABLE,	a->rt_table != b->rt_table);
-	diff |= ROUTE_DIFF(PROTOCOL,	a->rt_protocol != b->rt_protocol);
-	diff |= ROUTE_DIFF(SCOPE,	a->rt_scope != b->rt_scope);
-	diff |= ROUTE_DIFF(TYPE,	a->rt_type != b->rt_type);
-	diff |= ROUTE_DIFF(PRIO,	a->rt_prio != b->rt_prio);
-	diff |= ROUTE_DIFF(DST,		nl_addr_cmp(a->rt_dst, b->rt_dst));
-	diff |= ROUTE_DIFF(SRC,		nl_addr_cmp(a->rt_src, b->rt_src));
-	diff |= ROUTE_DIFF(IIF,		a->rt_iif != b->rt_iif);
-	diff |= ROUTE_DIFF(PREF_SRC,	nl_addr_cmp(a->rt_pref_src,
-						    b->rt_pref_src));
-	diff |= ROUTE_DIFF(TTL_PROPAGATE,
-			   a->rt_ttl_propagate != b->rt_ttl_propagate);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(ROUTE_ATTR_FAMILY, a->rt_family != b->rt_family);
+	diff |= _DIFF(ROUTE_ATTR_TOS, a->rt_tos != b->rt_tos);
+	diff |= _DIFF(ROUTE_ATTR_TABLE, a->rt_table != b->rt_table);
+	diff |= _DIFF(ROUTE_ATTR_PROTOCOL, a->rt_protocol != b->rt_protocol);
+	diff |= _DIFF(ROUTE_ATTR_SCOPE, a->rt_scope != b->rt_scope);
+	diff |= _DIFF(ROUTE_ATTR_TYPE, a->rt_type != b->rt_type);
+	diff |= _DIFF(ROUTE_ATTR_PRIO, a->rt_prio != b->rt_prio);
+	diff |= _DIFF(ROUTE_ATTR_DST, nl_addr_cmp(a->rt_dst, b->rt_dst));
+	diff |= _DIFF(ROUTE_ATTR_SRC, nl_addr_cmp(a->rt_src, b->rt_src));
+	diff |= _DIFF(ROUTE_ATTR_IIF, a->rt_iif != b->rt_iif);
+	diff |= _DIFF(ROUTE_ATTR_PREF_SRC,
+		      nl_addr_cmp(a->rt_pref_src, b->rt_pref_src));
+	diff |= _DIFF(ROUTE_ATTR_TTL_PROPAGATE,
+		      a->rt_ttl_propagate != b->rt_ttl_propagate);
 
 	if (flags & LOOSE_COMPARISON) {
 		nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) {
@@ -405,10 +437,10 @@
 			if (a->rt_metrics_mask & (1 << i) &&
 			    (!(b->rt_metrics_mask & (1 << i)) ||
 			     a->rt_metrics[i] != b->rt_metrics[i]))
-				diff |= ROUTE_DIFF(METRICS, 1);
+				diff |= _DIFF(ROUTE_ATTR_METRICS, 1);
 		}
 
-		diff |= ROUTE_DIFF(FLAGS,
+		diff |= _DIFF(ROUTE_ATTR_FLAGS,
 			  (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask);
 	} else {
 		if (a->rt_nr_nh != b->rt_nr_nh)
@@ -446,23 +478,22 @@
 		for (i = 0; i < RTAX_MAX - 1; i++) {
 			if ((a->rt_metrics_mask & (1 << i)) ^
 			    (b->rt_metrics_mask & (1 << i)))
-				diff |= ROUTE_DIFF(METRICS, 1);
+				diff |= _DIFF(ROUTE_ATTR_METRICS, 1);
 			else
-				diff |= ROUTE_DIFF(METRICS,
+				diff |= _DIFF(ROUTE_ATTR_METRICS,
 					a->rt_metrics[i] != b->rt_metrics[i]);
 		}
 
-		diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags);
+		diff |= _DIFF(ROUTE_ATTR_FLAGS, a->rt_flags != b->rt_flags);
 	}
 
 out:
 	return diff;
 
 nh_mismatch:
-	diff |= ROUTE_DIFF(MULTIPATH, 1);
+	diff |= _DIFF(ROUTE_ATTR_MULTIPATH, 1);
 	goto out;
-
-#undef ROUTE_DIFF
+#undef _DIFF
 }
 
 static int route_update(struct nl_object *old_obj, struct nl_object *new_obj)
@@ -1156,9 +1187,23 @@
 		if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family)))
 			return -NLE_NOMEM;
 	} else {
-		if (!(dst = nl_addr_alloc(0)))
+		int len;
+
+		switch (family) {
+			case AF_INET:
+				len = 4;
+				break;
+
+			case AF_INET6:
+				len = 16;
+				break;
+			default:
+				len = 0;
+				break;
+		}
+
+		if (!(dst = nl_addr_build(family, NULL, len)))
 			return -NLE_NOMEM;
-		nl_addr_set_family(dst, rtm->rtm_family);
 	}
 
 	nl_addr_set_prefixlen(dst, rtm->rtm_dst_len);
diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c
index 2a196f2..04e52b4 100644
--- a/lib/route/route_utils.c
+++ b/lib/route/route_utils.c
@@ -31,12 +31,15 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/route.h>
-	
+
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /**
  * @name Routing Table Identifier Translations
  * @{
@@ -49,7 +52,7 @@
 	return __trans_list_add(id, name, &table_names);
 }
 
-static void __init init_routing_table_names(void)
+static void _nl_init init_routing_table_names(void)
 {
 	add_routing_table_name(RT_TABLE_UNSPEC, "unspec");
 	add_routing_table_name(RT_TABLE_COMPAT, "compat");
@@ -58,7 +61,7 @@
 	add_routing_table_name(RT_TABLE_LOCAL, "local");
 }
 
-static void __exit release_routing_table_names(void)
+static void _nl_exit release_routing_table_names(void)
 {
 	__trans_list_clear(&table_names);
 }
@@ -95,7 +98,7 @@
 	return __trans_list_add(id, name, &proto_names);
 }
 
-static void __init init_proto_names(void)
+static void _nl_init init_proto_names(void)
 {
 	add_proto_name(RTPROT_UNSPEC, "unspec");
 	add_proto_name(RTPROT_REDIRECT, "redirect");
@@ -104,7 +107,7 @@
 	add_proto_name(RTPROT_STATIC, "static");
 }
 
-static void __exit release_proto_names(void)
+static void _nl_exit release_proto_names(void)
 {
 	__trans_list_clear(&proto_names);
 }
diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c
index f28ebf3..142c4c4 100644
--- a/lib/route/rtnl.c
+++ b/lib/route/rtnl.c
@@ -8,11 +8,14 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 
+#include "nl-priv-dynamic-core/nl-core.h"
+
 /**
  * @name Sending
  * @{
diff --git a/lib/route/rule.c b/lib/route/rule.c
index b3a60e1..6e7c084 100644
--- a/lib/route/rule.c
+++ b/lib/route/rule.c
@@ -10,15 +10,44 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/fib_rules.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/rule.h>
-#include <inttypes.h>
-#include <linux/fib_rules.h>
+
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
 
 /** @cond SKIP */
+struct rtnl_rule {
+	NLHDR_COMMON
+	uint8_t r_family;
+	uint8_t r_action;
+	uint8_t r_dsfield; /* ipv4 only */
+	uint8_t r_l3mdev;
+	uint8_t r_protocol; /* protocol that installed rule */
+	uint8_t r_ip_proto; /* IP/IPv6 protocol */
+	uint32_t r_table;
+	uint32_t r_flags;
+	uint32_t r_prio;
+	uint32_t r_mark;
+	uint32_t r_mask;
+	uint32_t r_goto;
+	uint32_t r_flow; /* ipv4 only */
+	struct nl_addr *r_src;
+	struct nl_addr *r_dst;
+	char r_iifname[IFNAMSIZ];
+	char r_oifname[IFNAMSIZ];
+
+	struct fib_rule_port_range r_sport;
+	struct fib_rule_port_range r_dport;
+};
+
 #define RULE_ATTR_FAMILY	0x000001
 #define RULE_ATTR_TABLE		0x000002
 #define RULE_ATTR_ACTION	0x000004
@@ -320,23 +349,21 @@
 	struct rtnl_rule *b = (struct rtnl_rule *) _b;
 	uint64_t diff = 0;
 
-#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= RULE_DIFF(FAMILY,	a->r_family != b->r_family);
-	diff |= RULE_DIFF(TABLE,	a->r_table != b->r_table);
-	diff |= RULE_DIFF(ACTION,	a->r_action != b->r_action);
-	diff |= RULE_DIFF(IIFNAME,	strcmp(a->r_iifname, b->r_iifname));
-	diff |= RULE_DIFF(OIFNAME,	strcmp(a->r_oifname, b->r_oifname));
-	diff |= RULE_DIFF(PRIO,		a->r_prio != b->r_prio);
-	diff |= RULE_DIFF(MARK,		a->r_mark != b->r_mark);
-	diff |= RULE_DIFF(MASK,		a->r_mask != b->r_mask);
-	diff |= RULE_DIFF(GOTO,		a->r_goto != b->r_goto);
-	diff |= RULE_DIFF(SRC,		nl_addr_cmp(a->r_src, b->r_src));
-	diff |= RULE_DIFF(DST,		nl_addr_cmp(a->r_dst, b->r_dst));
-	diff |= RULE_DIFF(DSFIELD,	a->r_dsfield != b->r_dsfield);
-	diff |= RULE_DIFF(FLOW,		a->r_flow != b->r_flow);
-	
-#undef RULE_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(RULE_ATTR_FAMILY, a->r_family != b->r_family);
+	diff |= _DIFF(RULE_ATTR_TABLE, a->r_table != b->r_table);
+	diff |= _DIFF(RULE_ATTR_ACTION, a->r_action != b->r_action);
+	diff |= _DIFF(RULE_ATTR_IIFNAME, strcmp(a->r_iifname, b->r_iifname));
+	diff |= _DIFF(RULE_ATTR_OIFNAME, strcmp(a->r_oifname, b->r_oifname));
+	diff |= _DIFF(RULE_ATTR_PRIO, a->r_prio != b->r_prio);
+	diff |= _DIFF(RULE_ATTR_MARK, a->r_mark != b->r_mark);
+	diff |= _DIFF(RULE_ATTR_MASK, a->r_mask != b->r_mask);
+	diff |= _DIFF(RULE_ATTR_GOTO, a->r_goto != b->r_goto);
+	diff |= _DIFF(RULE_ATTR_SRC, nl_addr_cmp(a->r_src, b->r_src));
+	diff |= _DIFF(RULE_ATTR_DST, nl_addr_cmp(a->r_dst, b->r_dst));
+	diff |= _DIFF(RULE_ATTR_DSFIELD, a->r_dsfield != b->r_dsfield);
+	diff |= _DIFF(RULE_ATTR_FLOW, a->r_flow != b->r_flow);
+#undef _DIFF
 
 	return diff;
 }
@@ -538,7 +565,7 @@
  * sends the request to the kernel and waits for the next ACK to be
  * received and thus blocks until the request has been fullfilled.
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
 {
@@ -593,7 +620,7 @@
  * sends the request to the kernel and waits for the next ACK to be
  * received and thus blocks until the request has been fullfilled.
  *
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
  */
 int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
 {
@@ -981,12 +1008,12 @@
 	.co_groups		= rule_groups,
 };
 
-static void __init rule_init(void)
+static void _nl_init rule_init(void)
 {
 	nl_cache_mngt_register(&rtnl_rule_ops);
 }
 
-static void __exit rule_exit(void)
+static void _nl_exit rule_exit(void)
 {
 	nl_cache_mngt_unregister(&rtnl_rule_ops);
 }
diff --git a/lib/route/tc-api.h b/lib/route/tc-api.h
new file mode 100644
index 0000000..43c4a28
--- /dev/null
+++ b/lib/route/tc-api.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2011-2013 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_TC_API_H_
+#define NETLINK_TC_API_H_
+
+#include <netlink/netlink.h>
+#include <netlink/msg.h>
+#include <netlink/route/tc.h>
+
+#include "nl-route.h"
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+/*****************************************************************************/
+
+#define TCA_ATTR_HANDLE		0x0001
+#define TCA_ATTR_PARENT		0x0002
+#define TCA_ATTR_IFINDEX	0x0004
+#define TCA_ATTR_KIND		0x0008
+#define TCA_ATTR_FAMILY		0x0010
+#define TCA_ATTR_INFO		0x0020
+#define TCA_ATTR_OPTS		0x0040
+#define TCA_ATTR_STATS		0x0080
+#define TCA_ATTR_XSTATS		0x0100
+#define TCA_ATTR_LINK		0x0200
+#define TCA_ATTR_MTU		0x0400
+#define TCA_ATTR_MPU		0x0800
+#define TCA_ATTR_OVERHEAD	0x1000
+#define TCA_ATTR_LINKTYPE	0x2000
+#define TCA_ATTR_CHAIN          0x4000
+#define TCA_ATTR_MAX            TCA_ATTR_CHAIN
+
+extern int tca_parse(struct nlattr **, int, struct rtnl_tc *,
+                     const struct nla_policy *);
+
+#define RTNL_TC_RTABLE_SIZE	256
+
+static inline void *tca_xstats(struct rtnl_tc *tca)
+{
+	return tca->tc_xstats->d_data;
+}
+
+extern struct nl_af_group tc_groups[];
+
+/*****************************************************************************/
+
+struct rtnl_tc_type_ops
+{
+	enum rtnl_tc_type tt_type;
+
+	char *tt_dump_prefix;
+
+	/**
+	 * Dump callbacks
+	 */
+	void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *,
+				        struct nl_dump_params *);
+};
+
+void *rtnl_tc_data_peek(struct rtnl_tc *tc);
+
+/*****************************************************************************/
+
+/* WARNING: the following symbols are wrongly exported in libnl-route-3
+ * library. They are private API, but leaked. */
+extern int			rtnl_tc_msg_parse(struct nlmsghdr *,
+						  struct rtnl_tc *);
+extern int			rtnl_tc_msg_build(struct rtnl_tc *, int,
+						  int, struct nl_msg **);
+
+extern void			rtnl_tc_free_data(struct nl_object *);
+extern int			rtnl_tc_clone(struct nl_object *,
+					      struct nl_object *);
+extern void			rtnl_tc_dump_line(struct nl_object *,
+						  struct nl_dump_params *);
+extern void			rtnl_tc_dump_details(struct nl_object *,
+						     struct nl_dump_params *);
+extern void			rtnl_tc_dump_stats(struct nl_object *,
+						   struct nl_dump_params *);
+extern uint64_t			rtnl_tc_compare(struct nl_object *,
+						struct nl_object *,
+						uint64_t, int);
+
+extern void *			rtnl_tc_data(struct rtnl_tc *);
+extern void *			rtnl_tc_data_check(struct rtnl_tc *,
+						   struct rtnl_tc_ops *, int *);
+
+extern int 			rtnl_tc_register(struct rtnl_tc_ops *);
+extern void 			rtnl_tc_unregister(struct rtnl_tc_ops *);
+
+extern void			rtnl_tc_type_register(struct rtnl_tc_type_ops *);
+extern void			rtnl_tc_type_unregister(struct rtnl_tc_type_ops *);
+
+
+extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *,
+				    uint32_t *);
+
+/*****************************************************************************/
+
+#endif
diff --git a/lib/route/tc.c b/lib/route/tc.c
index a06a478..a2fd567 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -9,16 +9,20 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/if_arp.h>
+#include <linux/gen_stats.h>
+
+#include <linux/atm.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/route/rtnl.h>
 #include <netlink/route/link.h>
 #include <netlink/route/tc.h>
-#include <netlink-private/route/tc-api.h>
 
-#include "netlink-private/utils.h"
+#include "tc-api.h"
 
 /** @cond SKIP */
 
@@ -105,11 +109,11 @@
 			return err;
 
 		if (tbs[TCA_STATS_BASIC]) {
-			struct gnet_stats_basic *bs;
+			struct gnet_stats_basic bs;
 			
-			bs = nla_data(tbs[TCA_STATS_BASIC]);
-			tc->tc_stats[RTNL_TC_BYTES]	= bs->bytes;
-			tc->tc_stats[RTNL_TC_PACKETS]	= bs->packets;
+			memcpy(&bs, nla_data(tbs[TCA_STATS_BASIC]), sizeof(bs));
+			tc->tc_stats[RTNL_TC_BYTES]	= bs.bytes;
+			tc->tc_stats[RTNL_TC_PACKETS]	= bs.packets;
 		}
 
 		if (tbs[TCA_STATS_RATE_EST]) {
@@ -142,16 +146,17 @@
 			goto compat_xstats;
 	} else {
 		if (tb[TCA_STATS]) {
-			struct tc_stats *st = nla_data(tb[TCA_STATS]);
+			struct tc_stats st;
 
-			tc->tc_stats[RTNL_TC_BYTES]	= st->bytes;
-			tc->tc_stats[RTNL_TC_PACKETS]	= st->packets;
-			tc->tc_stats[RTNL_TC_RATE_BPS]	= st->bps;
-			tc->tc_stats[RTNL_TC_RATE_PPS]	= st->pps;
-			tc->tc_stats[RTNL_TC_QLEN]	= st->qlen;
-			tc->tc_stats[RTNL_TC_BACKLOG]	= st->backlog;
-			tc->tc_stats[RTNL_TC_DROPS]	= st->drops;
-			tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits;
+			memcpy(&st, nla_data(tb[TCA_STATS]), sizeof(st));
+			tc->tc_stats[RTNL_TC_BYTES]	= st.bytes;
+			tc->tc_stats[RTNL_TC_PACKETS]	= st.packets;
+			tc->tc_stats[RTNL_TC_RATE_BPS]	= st.bps;
+			tc->tc_stats[RTNL_TC_RATE_PPS]	= st.pps;
+			tc->tc_stats[RTNL_TC_QLEN]	= st.qlen;
+			tc->tc_stats[RTNL_TC_BACKLOG]	= st.backlog;
+			tc->tc_stats[RTNL_TC_DROPS]	= st.drops;
+			tc->tc_stats[RTNL_TC_OVERLIMITS]= st.overlimits;
 
 			tc->ce_mask |= TCA_ATTR_STATS;
 		}
@@ -666,14 +671,14 @@
 /**
  * Calculate the binary logarithm for a specific cell size
  * @arg cell_size	Size of cell, must be a power of two.
- * @return Binary logirhtm of cell size or a negative error code.
+ * @return Binary logarithm of cell size or a negative error code.
  */
 int rtnl_tc_calc_cell_log(int cell_size)
 {
 	int i;
 
 	for (i = 0; i < 32; i++)
-		if ((1 << i) == cell_size)
+		if ((((uint32_t)1u) << i) == cell_size)
 			return i;
 
 	return -NLE_INVAL;
@@ -971,14 +976,12 @@
 	struct rtnl_tc *b = TC_CAST(bobj);
 	uint64_t diff = 0;
 
-#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
-
-	diff |= TC_DIFF(HANDLE,		a->tc_handle != b->tc_handle);
-	diff |= TC_DIFF(PARENT,		a->tc_parent != b->tc_parent);
-	diff |= TC_DIFF(IFINDEX,	a->tc_ifindex != b->tc_ifindex);
-	diff |= TC_DIFF(KIND,		strcmp(a->tc_kind, b->tc_kind));
-
-#undef TC_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(TCA_ATTR_HANDLE, a->tc_handle != b->tc_handle);
+	diff |= _DIFF(TCA_ATTR_PARENT, a->tc_parent != b->tc_parent);
+	diff |= _DIFF(TCA_ATTR_IFINDEX, a->tc_ifindex != b->tc_ifindex);
+	diff |= _DIFF(TCA_ATTR_KIND, strcmp(a->tc_kind, b->tc_kind));
+#undef _DIFF
 
 	return diff;
 }
@@ -1019,7 +1022,7 @@
 	/*
 	 * Initialiation hack, make sure list is initialized when
 	 * the first tc module registers. Putting this in a
-	 * separate __init would required correct ordering of init
+	 * separate _nl_init would required correct ordering of init
 	 * functions
 	 */
 	if (!init) {
diff --git a/lib/socket.c b/lib/socket.c
index 99cd36d..9b42f67 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -21,22 +21,28 @@
  * ~~~~
  */
 
-#include "defs.h"
+#include "nl-default.h"
 
-#include "sys/socket.h"
+#include <fcntl.h>
+#include <sys/socket.h>
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/socket.h>
-#include <netlink-private/utils.h>
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
 #include <netlink/handlers.h>
 #include <netlink/msg.h>
 #include <netlink/attr.h>
 
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-aux-core/nl-core.h"
+
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
 static int default_cb = NL_CB_DEFAULT;
 
-static void __init init_default_cb(void)
+static void _nl_init init_default_cb(void)
 {
 	char *nlcb;
 
@@ -54,6 +60,24 @@
 	}
 }
 
+static uint32_t _badrandom_from_time(void)
+{
+	uint32_t result;
+	uint64_t v64;
+	time_t t;
+
+	t = time(NULL);
+	v64 = (uint64_t)t;
+	result = (uint32_t)v64;
+
+	/* XOR with the upper bits. Otherwise, coverity warns about only
+	 * considering 32 bit from time_t.  Use the inverse, so that for the
+	 * most part the bits don't change.  */
+	result ^= (~(v64 >> 32));
+
+	return result;
+}
+
 static uint32_t used_ports_map[32];
 static NL_RW_LOCK(port_map_lock);
 
@@ -67,7 +91,7 @@
 	nl_write_lock(&port_map_lock);
 
 	if (idx_state == 0) {
-		uint32_t t = time(NULL);
+		uint32_t t = _badrandom_from_time();
 
 		/* from time to time (on average each 2^15 calls), the idx_state will
 		 * be zero again. No problem, just "seed" anew with time(). */
@@ -184,7 +208,8 @@
 	sk->s_cb = nl_cb_get(cb);
 	sk->s_local.nl_family = AF_NETLINK;
 	sk->s_peer.nl_family = AF_NETLINK;
-	sk->s_seq_expect = sk->s_seq_next = time(NULL);
+	sk->s_seq_next = _badrandom_from_time();
+	sk->s_seq_expect = sk->s_seq_next;
 
 	/* the port is 0 (unspecified), meaning NL_OWN_PORT */
 	sk->s_flags = NL_OWN_PORT;
@@ -424,7 +449,7 @@
  * bitmask definitions for nl_join_groups() are likely to still
  * be present for backward compatibility reasons.
  *
- * @return 0 on sucess or a negative error code.
+ * @return 0 on success or a negative error code.
  */
 int nl_socket_add_memberships(struct nl_sock *sk, int group, ...)
 {
@@ -802,7 +827,7 @@
  * good default value.
  *
  * @note It is not required to call this function prior to nl_connect().
- * @return 0 on sucess or a negative error code.
+ * @return 0 on success or a negative error code.
  */
 int nl_socket_set_buffer_size(struct nl_sock *sk, int rxbuf, int txbuf)
 {
diff --git a/lib/utils.c b/lib/utils.c
index a20f36c..4f5fd1a 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -18,15 +18,20 @@
  * ~~~~
  */
 
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
+#include <locale.h>
+
+#include <linux/socket.h>
+#include <linux/if_arp.h>
+
 #include <netlink/netlink.h>
 #include <netlink/utils.h>
-#include <linux/socket.h>
-#include <stdlib.h> /* exit() */
-#ifdef HAVE_STRERROR_L
-#include <locale.h>
-#endif
+
+#include "nl-core.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-aux-core/nl-core.h"
 
 /**
  * Global variable indicating the desired level of debugging output.
@@ -52,7 +57,7 @@
 	.dp_type = NL_DUMP_DETAILS,
 };
 
-static void __init nl_debug_init(void)
+static void _nl_init nl_debug_init(void)
 {
 	char *nldbg, *end;
 
@@ -117,6 +122,63 @@
 	return 0;
 }
 
+struct trans_list {
+	int i;
+	char *a;
+	struct nl_list_head list;
+};
+
+int nl_getprotobyname(const char *name)
+{
+	const struct protoent *result;
+
+#if HAVE_DECL_GETPROTOBYNAME_R
+	struct protoent result_buf;
+	char buf[2048];
+	int r;
+
+	r = getprotobyname_r(name, &result_buf, buf, sizeof(buf),
+			     (struct protoent **)&result);
+	if (r != 0 || result != &result_buf)
+		result = NULL;
+#else
+	result = getprotobyname(name);
+#endif
+
+	if (!result)
+		return -1;
+
+	if (result->p_proto < 0 || result->p_proto > UINT8_MAX)
+		return -1;
+	return (uint8_t)result->p_proto;
+}
+
+bool nl_getprotobynumber(int proto, char *out_name, size_t name_len)
+{
+	const struct protoent *result;
+
+#if HAVE_DECL_GETPROTOBYNUMBER_R
+	struct protoent result_buf;
+	char buf[2048];
+	int r;
+
+	r = getprotobynumber_r(proto, &result_buf, buf, sizeof(buf),
+			       (struct protoent **)&result);
+	if (r != 0 || result != &result_buf)
+		result = NULL;
+#else
+	result = getprotobynumber(proto);
+#endif
+
+	if (!result)
+		return false;
+
+	if (strlen(result->p_name) >= name_len)
+		return false;
+	strcpy(out_name, result->p_name);
+	return true;
+}
+
 const char *nl_strerror_l(int err)
 {
 	const char *buf;
@@ -859,12 +921,8 @@
 
 char *nl_ip_proto2str(int proto, char *buf, size_t len)
 {
-	struct protoent *p = getprotobynumber(proto);
-
-	if (p) {
-		snprintf(buf, len, "%s", p->p_name);
+	if (nl_getprotobynumber(proto, buf, len))
 		return buf;
-	}
 
 	snprintf(buf, len, "0x%x", proto);
 	return buf;
@@ -872,15 +930,19 @@
 
 int nl_str2ip_proto(const char *name)
 {
-	struct protoent *p = getprotobyname(name);
 	unsigned long l;
 	char *end;
+	int p;
 
-	if (p)
-		return p->p_proto;
+	if (!name)
+		return -NLE_INVAL;
+
+	p = nl_getprotobyname(name);
+	if (p >= 0)
+		return p;
 
 	l = strtoul(name, &end, 0);
-	if (l == ULONG_MAX || *end != '\0')
+	if (name == end || *end != '\0' || l > (unsigned long)INT_MAX)
 		return -NLE_OBJ_NOTFOUND;
 
 	return (int) l;
@@ -1221,8 +1283,8 @@
 			NL_CAPABILITY_VERSION_3_6_0),
 		_NL_SET (4,
 			NL_CAPABILITY_VERSION_3_7_0,
-			0,
-			0,
+			NL_CAPABILITY_VERSION_3_8_0,
+			NL_CAPABILITY_VERSION_3_9_0,
 			0,
 			0,
 			0,
diff --git a/lib/version.c b/lib/version.c
index ffde260..da4bd25 100644
--- a/lib/version.c
+++ b/lib/version.c
@@ -18,6 +18,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/version.h>
 
 const int      nl_ver_num = LIBNL_VER_NUM;
diff --git a/lib/xfrm/ae.c b/lib/xfrm/ae.c
index 3af872f..9af73a8 100644
--- a/lib/xfrm/ae.c
+++ b/lib/xfrm/ae.c
@@ -120,14 +120,46 @@
  * @{
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/xfrm.h>
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
 #include <netlink/xfrm/ae.h>
-#include <linux/xfrm.h>
+
+#include "nl-xfrm.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-aux-xfrm/nl-xfrm.h"
 
 /** @cond SKIP */
+
+struct xfrmnl_sa_id {
+	struct nl_addr* daddr;
+	uint32_t        spi;
+	uint16_t        family;
+	uint8_t         proto;
+};
+
+struct xfrmnl_ae {
+	NLHDR_COMMON
+
+	struct xfrmnl_sa_id             sa_id;
+	struct nl_addr*                 saddr;
+	uint32_t                        flags;
+	uint32_t                        reqid;
+	struct xfrmnl_mark              mark;
+	struct xfrmnl_lifetime_cur      lifetime_cur;
+	uint32_t                        replay_maxage;
+	uint32_t                        replay_maxdiff;
+	struct xfrmnl_replay_state      replay_state;
+	struct xfrmnl_replay_state_esn* replay_state_esn;
+};
+
 #define XFRM_AE_ATTR_DADDR          0x01
 #define XFRM_AE_ATTR_SPI            0x02
 #define XFRM_AE_ATTR_PROTO          0x04
@@ -197,16 +229,20 @@
 	uint64_t diff = 0;
 	int found = 0;
 
-#define XFRM_AE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_AE_ATTR_##ATTR, a, b, EXPR)
-	diff |= XFRM_AE_DIFF(DADDR,	nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr));
-	diff |= XFRM_AE_DIFF(SPI,	a->sa_id.spi != b->sa_id.spi);
-	diff |= XFRM_AE_DIFF(PROTO,	a->sa_id.proto != b->sa_id.proto);
-	diff |= XFRM_AE_DIFF(SADDR,	nl_addr_cmp(a->saddr, b->saddr));
-	diff |= XFRM_AE_DIFF(FLAGS, a->flags != b->flags);
-	diff |= XFRM_AE_DIFF(REQID, a->reqid != b->reqid);
-	diff |= XFRM_AE_DIFF(MARK, (a->mark.v & a->mark.m) != (b->mark.v & b->mark.m));
-	diff |= XFRM_AE_DIFF(REPLAY_MAXAGE, a->replay_maxage != b->replay_maxage);
-	diff |= XFRM_AE_DIFF(REPLAY_MAXDIFF, a->replay_maxdiff != b->replay_maxdiff);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(XFRM_AE_ATTR_DADDR,
+		      nl_addr_cmp(a->sa_id.daddr, b->sa_id.daddr));
+	diff |= _DIFF(XFRM_AE_ATTR_SPI, a->sa_id.spi != b->sa_id.spi);
+	diff |= _DIFF(XFRM_AE_ATTR_PROTO, a->sa_id.proto != b->sa_id.proto);
+	diff |= _DIFF(XFRM_AE_ATTR_SADDR, nl_addr_cmp(a->saddr, b->saddr));
+	diff |= _DIFF(XFRM_AE_ATTR_FLAGS, a->flags != b->flags);
+	diff |= _DIFF(XFRM_AE_ATTR_REQID, a->reqid != b->reqid);
+	diff |= _DIFF(XFRM_AE_ATTR_MARK,
+		      (a->mark.v & a->mark.m) != (b->mark.v & b->mark.m));
+	diff |= _DIFF(XFRM_AE_ATTR_REPLAY_MAXAGE,
+		      a->replay_maxage != b->replay_maxage);
+	diff |= _DIFF(XFRM_AE_ATTR_REPLAY_MAXDIFF,
+		      a->replay_maxdiff != b->replay_maxdiff);
 
 	/* Compare replay states */
 	found = AVAILABLE_MISMATCH (a, b, XFRM_AE_ATTR_REPLAY_STATE);
@@ -237,7 +273,7 @@
 			}
 		}
 	}
-#undef XFRM_AE_DIFF
+#undef _DIFF
 
 	return diff;
 }
@@ -301,6 +337,7 @@
 	char                flags[128], buf[128];
 	time_t              add_time, use_time;
 	struct tm           *add_time_tm, *use_time_tm;
+	struct tm           tm_buf;
 
 	nl_dump_line(p, "src %s dst %s \n", nl_addr2str(ae->saddr, src, sizeof(src)),
 				nl_addr2str(ae->sa_id.daddr, dst, sizeof(dst)));
@@ -320,7 +357,7 @@
 	if (ae->lifetime_cur.add_time != 0)
 	{
 		add_time = ae->lifetime_cur.add_time;
-		add_time_tm = gmtime (&add_time);
+		add_time_tm = gmtime_r (&add_time, &tm_buf);
 		strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm);
 	}
 	else
@@ -331,7 +368,7 @@
 	if (ae->lifetime_cur.use_time != 0)
 	{
 		use_time = ae->lifetime_cur.use_time;
-		use_time_tm = gmtime (&use_time);
+		use_time_tm = gmtime_r (&use_time, &tm_buf);
 		strftime (buf, 128, "%Y-%m-%d %H-%M-%S", use_time_tm);
 	}
 	else
@@ -487,29 +524,30 @@
 
 int xfrmnl_ae_parse(struct nlmsghdr *n, struct xfrmnl_ae **result)
 {
-	struct xfrmnl_ae*    ae;
+	_nl_auto_xfrmnl_ae struct xfrmnl_ae *ae = NULL;
 	struct nlattr           *tb[XFRMA_MAX + 1];
 	struct xfrm_aevent_id*  ae_id;
 	int err;
 
 	ae = xfrmnl_ae_alloc();
-	if (!ae) {
-		err = -NLE_NOMEM;
-		goto errout;
-	}
+	if (!ae)
+		return -NLE_NOMEM;
 
 	ae->ce_msgtype = n->nlmsg_type;
 	ae_id = nlmsg_data(n);
 
 	err = nlmsg_parse(n, sizeof(struct xfrm_aevent_id), tb, XFRMA_MAX, xfrm_ae_policy);
 	if (err < 0)
-		goto errout;
+		return err;
 
-	ae->sa_id.daddr = nl_addr_build(ae_id->sa_id.family, &ae_id->sa_id.daddr, sizeof (ae_id->sa_id.daddr));
+	if (!(ae->sa_id.daddr =
+		      _nl_addr_build(ae_id->sa_id.family, &ae_id->sa_id.daddr)))
+		return -NLE_NOMEM;
 	ae->sa_id.family= ae_id->sa_id.family;
 	ae->sa_id.spi   = ntohl(ae_id->sa_id.spi);
 	ae->sa_id.proto = ae_id->sa_id.proto;
-	ae->saddr       = nl_addr_build(ae_id->sa_id.family, &ae_id->saddr, sizeof (ae_id->saddr));
+	if (!(ae->saddr = _nl_addr_build(ae_id->sa_id.family, &ae_id->saddr)))
+		return -NLE_NOMEM;
 	ae->reqid       = ae_id->reqid;
 	ae->flags       = ae_id->flags;
 	ae->ce_mask |= (XFRM_AE_ATTR_DADDR | XFRM_AE_ATTR_FAMILY | XFRM_AE_ATTR_SPI |
@@ -525,6 +563,7 @@
 
 	if (tb[XFRMA_LTIME_VAL]) {
 		struct xfrm_lifetime_cur* cur =   nla_data(tb[XFRMA_LTIME_VAL]);
+
 		ae->lifetime_cur.bytes      =   cur->bytes;
 		ae->lifetime_cur.packets    =   cur->packets;
 		ae->lifetime_cur.add_time   =   cur->add_time;
@@ -546,10 +585,8 @@
 		struct xfrm_replay_state_esn* esn =  nla_data (tb[XFRMA_REPLAY_ESN_VAL]);
 		uint32_t len = sizeof (struct xfrmnl_replay_state_esn) +  (sizeof (uint32_t) * esn->bmp_len);
 
-		if ((ae->replay_state_esn = calloc (1, len)) == NULL) {
-			err = -ENOMEM;
-			goto errout;
-		}
+		if ((ae->replay_state_esn = calloc (1, len)) == NULL)
+			return -NLE_NOMEM;
 		ae->replay_state_esn->oseq       =  esn->oseq;
 		ae->replay_state_esn->seq        =  esn->seq;
 		ae->replay_state_esn->oseq_hi    =  esn->oseq_hi;
@@ -570,12 +607,8 @@
 		ae->replay_state_esn = NULL;
 	}
 
-	*result = ae;
+	*result = _nl_steal_pointer(&ae);
 	return 0;
-
-errout:
-	xfrmnl_ae_put(ae);
-	return err;
 }
 
 static int xfrm_ae_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
diff --git a/lib/xfrm/lifetime.c b/lib/xfrm/lifetime.c
index db761d6..17c9883 100644
--- a/lib/xfrm/lifetime.c
+++ b/lib/xfrm/lifetime.c
@@ -47,8 +47,11 @@
  * ~~~~
  */
 
+#include "nl-default.h"
+
 #include <netlink/xfrm/lifetime.h>
-#include <netlink-private/netlink.h>
+
+#include "nl-xfrm.h"
 
 static void ltime_cfg_destroy(struct xfrmnl_ltime_cfg* ltime)
 {
diff --git a/lib/xfrm/nl-xfrm.h b/lib/xfrm/nl-xfrm.h
new file mode 100644
index 0000000..0469c63
--- /dev/null
+++ b/lib/xfrm/nl-xfrm.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __LIB_XFRM_NL_XFRM_H__
+#define __LIB_XFRM_NL_XFRM_H__
+
+/* Lifetime configuration, used for both policy rules (SPD) and SAs. */
+struct xfrmnl_ltime_cfg {
+	uint32_t refcnt;
+	uint64_t soft_byte_limit;
+	uint64_t hard_byte_limit;
+	uint64_t soft_packet_limit;
+	uint64_t hard_packet_limit;
+	uint64_t soft_add_expires_seconds;
+	uint64_t hard_add_expires_seconds;
+	uint64_t soft_use_expires_seconds;
+	uint64_t hard_use_expires_seconds;
+};
+
+/* Current lifetime, used for both policy rules (SPD) and SAs. */
+struct xfrmnl_lifetime_cur {
+	uint64_t bytes;
+	uint64_t packets;
+	uint64_t add_time;
+	uint64_t use_time;
+};
+
+struct xfrmnl_replay_state {
+	uint32_t oseq;
+	uint32_t seq;
+	uint32_t bitmap;
+};
+
+struct xfrmnl_replay_state_esn {
+	uint32_t bmp_len;
+	uint32_t oseq;
+	uint32_t seq;
+	uint32_t oseq_hi;
+	uint32_t seq_hi;
+	uint32_t replay_window;
+	uint32_t bmp[0];
+};
+
+struct xfrmnl_mark {
+	uint32_t v; /* value */
+	uint32_t m; /* mask */
+};
+
+struct xfrmnl_id {
+	struct nl_addr *daddr;
+	uint32_t spi;
+	uint8_t proto;
+};
+
+struct xfrmnl_user_sec_ctx {
+	uint16_t len;
+	uint16_t exttype;
+	uint8_t ctx_alg;
+	uint8_t ctx_doi;
+	uint16_t ctx_len;
+	char ctx[0];
+};
+
+struct xfrmnl_user_tmpl {
+	struct xfrmnl_id id;
+	uint16_t family;
+	struct nl_addr *saddr;
+	uint32_t reqid;
+	uint8_t mode;
+	uint8_t share;
+	uint8_t optional;
+	uint32_t aalgos;
+	uint32_t ealgos;
+	uint32_t calgos;
+	struct nl_list_head utmpl_list;
+};
+
+#endif /* __LIB_XFRM_NL_XFRM_H__  */
diff --git a/lib/xfrm/sa.c b/lib/xfrm/sa.c
index a8bbced..0c89c71 100644
--- a/lib/xfrm/sa.c
+++ b/lib/xfrm/sa.c
@@ -39,18 +39,96 @@
  * @brief
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <time.h>
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
 #include <netlink/xfrm/sa.h>
 #include <netlink/xfrm/selector.h>
 #include <netlink/xfrm/lifetime.h>
-#include <time.h>
 
-#include "netlink-private/utils.h"
+#include "nl-xfrm.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-aux-xfrm/nl-xfrm.h"
 
 /** @cond SKIP */
+
+struct xfrmnl_stats {
+	uint32_t        replay_window;
+	uint32_t        replay;
+	uint32_t        integrity_failed;
+};
+
+struct xfrmnl_algo_aead {
+	char            alg_name[64];
+	uint32_t        alg_key_len;    /* in bits */
+	uint32_t        alg_icv_len;    /* in bits */
+	char            alg_key[0];
+};
+
+struct xfrmnl_algo_auth {
+	char            alg_name[64];
+	uint32_t        alg_key_len;    /* in bits */
+	uint32_t        alg_trunc_len;  /* in bits */
+	char            alg_key[0];
+};
+
+struct xfrmnl_algo {
+	char            alg_name[64];
+	uint32_t        alg_key_len;    /* in bits */
+	char            alg_key[0];
+};
+
+struct xfrmnl_encap_tmpl {
+	uint16_t        encap_type;
+	uint16_t        encap_sport;
+	uint16_t        encap_dport;
+	struct nl_addr* encap_oa;
+};
+
+struct xfrmnl_user_offload {
+	int             ifindex;
+	uint8_t         flags;
+};
+
+struct xfrmnl_sa {
+	NLHDR_COMMON
+
+	struct xfrmnl_sel*              sel;
+	struct xfrmnl_id                id;
+	struct nl_addr*                 saddr;
+	struct xfrmnl_ltime_cfg*        lft;
+	struct xfrmnl_lifetime_cur      curlft;
+	struct xfrmnl_stats             stats;
+	uint32_t                        seq;
+	uint32_t                        reqid;
+	uint16_t                        family;
+	uint8_t                         mode;        /* XFRM_MODE_xxx */
+	uint8_t                         replay_window;
+	uint8_t                         flags;
+	struct xfrmnl_algo_aead*        aead;
+	struct xfrmnl_algo_auth*        auth;
+	struct xfrmnl_algo*             crypt;
+	struct xfrmnl_algo*             comp;
+	struct xfrmnl_encap_tmpl*       encap;
+	uint32_t                        tfcpad;
+	struct nl_addr*                 coaddr;
+	struct xfrmnl_mark              mark;
+	struct xfrmnl_user_sec_ctx*     sec_ctx;
+	uint32_t                        replay_maxage;
+	uint32_t                        replay_maxdiff;
+	struct xfrmnl_replay_state      replay_state;
+	struct xfrmnl_replay_state_esn* replay_state_esn;
+	uint8_t                         hard;
+	struct xfrmnl_user_offload*     user_offload;
+};
+
 #define XFRM_SA_ATTR_SEL            0x01
 #define XFRM_SA_ATTR_DADDR          0x02
 #define XFRM_SA_ATTR_SPI            0x04
@@ -236,51 +314,62 @@
 	uint64_t diff = 0;
 	int found = 0;
 
-#define XFRM_SA_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SA_ATTR_##ATTR, a, b, EXPR)
-	diff |= XFRM_SA_DIFF(SEL,	xfrmnl_sel_cmp(a->sel, b->sel));
-	diff |= XFRM_SA_DIFF(DADDR,	nl_addr_cmp(a->id.daddr, b->id.daddr));
-	diff |= XFRM_SA_DIFF(SPI,	a->id.spi != b->id.spi);
-	diff |= XFRM_SA_DIFF(PROTO,	a->id.proto != b->id.proto);
-	diff |= XFRM_SA_DIFF(SADDR,	nl_addr_cmp(a->saddr, b->saddr));
-	diff |= XFRM_SA_DIFF(LTIME_CFG,	xfrmnl_ltime_cfg_cmp(a->lft, b->lft));
-	diff |= XFRM_SA_DIFF(REQID,	a->reqid != b->reqid);
-	diff |= XFRM_SA_DIFF(FAMILY,a->family != b->family);
-	diff |= XFRM_SA_DIFF(MODE,a->mode != b->mode);
-	diff |= XFRM_SA_DIFF(REPLAY_WIN,a->replay_window != b->replay_window);
-	diff |= XFRM_SA_DIFF(FLAGS,a->flags != b->flags);
-	diff |= XFRM_SA_DIFF(ALG_AEAD,(strcmp(a->aead->alg_name, b->aead->alg_name) ||
-	                              (a->aead->alg_key_len != b->aead->alg_key_len) ||
-	                              (a->aead->alg_icv_len != b->aead->alg_icv_len) ||
-	                              memcmp(a->aead->alg_key, b->aead->alg_key,
-	                              ((a->aead->alg_key_len + 7)/8))));
-	diff |= XFRM_SA_DIFF(ALG_AUTH,(strcmp(a->auth->alg_name, b->auth->alg_name) ||
-	                              (a->auth->alg_key_len != b->auth->alg_key_len) ||
-	                              (a->auth->alg_trunc_len != b->auth->alg_trunc_len) ||
-	                              memcmp(a->auth->alg_key, b->auth->alg_key,
-	                              ((a->auth->alg_key_len + 7)/8))));
-	diff |= XFRM_SA_DIFF(ALG_CRYPT,(strcmp(a->crypt->alg_name, b->crypt->alg_name) ||
-	                              (a->crypt->alg_key_len != b->crypt->alg_key_len) ||
-	                              memcmp(a->crypt->alg_key, b->crypt->alg_key,
-	                              ((a->crypt->alg_key_len + 7)/8))));
-	diff |= XFRM_SA_DIFF(ALG_COMP,(strcmp(a->comp->alg_name, b->comp->alg_name) ||
-	                              (a->comp->alg_key_len != b->comp->alg_key_len) ||
-	                              memcmp(a->comp->alg_key, b->comp->alg_key,
-	                              ((a->comp->alg_key_len + 7)/8))));
-	diff |= XFRM_SA_DIFF(ENCAP,((a->encap->encap_type != b->encap->encap_type) ||
-	                            (a->encap->encap_sport != b->encap->encap_sport) ||
-	                            (a->encap->encap_dport != b->encap->encap_dport) ||
-	                            nl_addr_cmp(a->encap->encap_oa, b->encap->encap_oa)));
-	diff |= XFRM_SA_DIFF(TFCPAD,a->tfcpad != b->tfcpad);
-	diff |= XFRM_SA_DIFF(COADDR,nl_addr_cmp(a->coaddr, b->coaddr));
-	diff |= XFRM_SA_DIFF(MARK,(a->mark.m != b->mark.m) ||
-	                          (a->mark.v != b->mark.v));
-	diff |= XFRM_SA_DIFF(SECCTX,((a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) ||
-	                            (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) ||
-	                            (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) ||
-	                            strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx)));
-	diff |= XFRM_SA_DIFF(REPLAY_MAXAGE,a->replay_maxage != b->replay_maxage);
-	diff |= XFRM_SA_DIFF(REPLAY_MAXDIFF,a->replay_maxdiff != b->replay_maxdiff);
-	diff |= XFRM_SA_DIFF(EXPIRE,a->hard != b->hard);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(XFRM_SA_ATTR_SEL, xfrmnl_sel_cmp(a->sel, b->sel));
+	diff |= _DIFF(XFRM_SA_ATTR_DADDR,
+		      nl_addr_cmp(a->id.daddr, b->id.daddr));
+	diff |= _DIFF(XFRM_SA_ATTR_SPI, a->id.spi != b->id.spi);
+	diff |= _DIFF(XFRM_SA_ATTR_PROTO, a->id.proto != b->id.proto);
+	diff |= _DIFF(XFRM_SA_ATTR_SADDR, nl_addr_cmp(a->saddr, b->saddr));
+	diff |= _DIFF(XFRM_SA_ATTR_LTIME_CFG,
+		      xfrmnl_ltime_cfg_cmp(a->lft, b->lft));
+	diff |= _DIFF(XFRM_SA_ATTR_REQID, a->reqid != b->reqid);
+	diff |= _DIFF(XFRM_SA_ATTR_FAMILY, a->family != b->family);
+	diff |= _DIFF(XFRM_SA_ATTR_MODE, a->mode != b->mode);
+	diff |= _DIFF(XFRM_SA_ATTR_REPLAY_WIN,
+		      a->replay_window != b->replay_window);
+	diff |= _DIFF(XFRM_SA_ATTR_FLAGS, a->flags != b->flags);
+	diff |= _DIFF(XFRM_SA_ATTR_ALG_AEAD,
+		      (strcmp(a->aead->alg_name, b->aead->alg_name) ||
+		       (a->aead->alg_key_len != b->aead->alg_key_len) ||
+		       (a->aead->alg_icv_len != b->aead->alg_icv_len) ||
+		       memcmp(a->aead->alg_key, b->aead->alg_key,
+			      ((a->aead->alg_key_len + 7) / 8))));
+	diff |= _DIFF(XFRM_SA_ATTR_ALG_AUTH,
+		      (strcmp(a->auth->alg_name, b->auth->alg_name) ||
+		       (a->auth->alg_key_len != b->auth->alg_key_len) ||
+		       (a->auth->alg_trunc_len != b->auth->alg_trunc_len) ||
+		       memcmp(a->auth->alg_key, b->auth->alg_key,
+			      ((a->auth->alg_key_len + 7) / 8))));
+	diff |= _DIFF(XFRM_SA_ATTR_ALG_CRYPT,
+		      (strcmp(a->crypt->alg_name, b->crypt->alg_name) ||
+		       (a->crypt->alg_key_len != b->crypt->alg_key_len) ||
+		       memcmp(a->crypt->alg_key, b->crypt->alg_key,
+			      ((a->crypt->alg_key_len + 7) / 8))));
+	diff |= _DIFF(XFRM_SA_ATTR_ALG_COMP,
+		      (strcmp(a->comp->alg_name, b->comp->alg_name) ||
+		       (a->comp->alg_key_len != b->comp->alg_key_len) ||
+		       memcmp(a->comp->alg_key, b->comp->alg_key,
+			      ((a->comp->alg_key_len + 7) / 8))));
+	diff |= _DIFF(XFRM_SA_ATTR_ENCAP,
+		      ((a->encap->encap_type != b->encap->encap_type) ||
+		       (a->encap->encap_sport != b->encap->encap_sport) ||
+		       (a->encap->encap_dport != b->encap->encap_dport) ||
+		       nl_addr_cmp(a->encap->encap_oa, b->encap->encap_oa)));
+	diff |= _DIFF(XFRM_SA_ATTR_TFCPAD, a->tfcpad != b->tfcpad);
+	diff |= _DIFF(XFRM_SA_ATTR_COADDR, nl_addr_cmp(a->coaddr, b->coaddr));
+	diff |= _DIFF(XFRM_SA_ATTR_MARK,
+		      (a->mark.m != b->mark.m) || (a->mark.v != b->mark.v));
+	diff |= _DIFF(XFRM_SA_ATTR_SECCTX,
+		      ((a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) ||
+		       (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) ||
+		       (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) ||
+		       strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx)));
+	diff |= _DIFF(XFRM_SA_ATTR_REPLAY_MAXAGE,
+		      a->replay_maxage != b->replay_maxage);
+	diff |= _DIFF(XFRM_SA_ATTR_REPLAY_MAXDIFF,
+		      a->replay_maxdiff != b->replay_maxdiff);
+	diff |= _DIFF(XFRM_SA_ATTR_EXPIRE, a->hard != b->hard);
 
 	/* Compare replay states */
 	found = AVAILABLE_MISMATCH (a, b, XFRM_SA_ATTR_REPLAY_STATE);
@@ -312,7 +401,7 @@
 			}
 		}
 	}
-#undef XFRM_SA_DIFF
+#undef _DIFF
 
 	return diff;
 }
@@ -415,6 +504,7 @@
 	char                flags[128], mode[128];
 	time_t              add_time, use_time;
 	struct tm           *add_time_tm, *use_time_tm;
+	struct tm           tm_buf;
 
 	nl_dump_line(p, "src %s dst %s family: %s\n", nl_addr2str(sa->saddr, src, sizeof(src)),
 	             nl_addr2str(sa->id.daddr, dst, sizeof(dst)),
@@ -467,7 +557,7 @@
 	if (sa->curlft.add_time != 0)
 	{
 		add_time = sa->curlft.add_time;
-		add_time_tm = gmtime (&add_time);
+		add_time_tm = gmtime_r (&add_time, &tm_buf);
 		strftime (flags, 128, "%Y-%m-%d %H-%M-%S", add_time_tm);
 	}
 	else
@@ -478,7 +568,7 @@
 	if (sa->curlft.use_time != 0)
 	{
 		use_time = sa->curlft.use_time;
-		use_time_tm = gmtime (&use_time);
+		use_time_tm = gmtime_r (&use_time, &tm_buf);
 		strftime (mode, 128, "%Y-%m-%d %H-%M-%S", use_time_tm);
 	}
 	else
@@ -682,18 +772,17 @@
 
 int xfrmnl_sa_parse(struct nlmsghdr *n, struct xfrmnl_sa **result)
 {
-	struct xfrmnl_sa*           sa;
+	_nl_auto_nl_addr struct nl_addr *addr1 = NULL;
+	_nl_auto_nl_addr struct nl_addr *addr2 = NULL;
+	_nl_auto_xfrmnl_sa struct xfrmnl_sa *sa = NULL;
 	struct nlattr               *tb[XFRMA_MAX + 1];
 	struct xfrm_usersa_info*    sa_info;
 	struct xfrm_user_expire*    ue;
 	int                         len, err;
-	struct nl_addr*             addr;
 
 	sa = xfrmnl_sa_alloc();
-	if (!sa) {
-		err = -NLE_NOMEM;
-		goto errout;
-	}
+	if (!sa)
+		return -NLE_NOMEM;
 
 	sa->ce_msgtype = n->nlmsg_type;
 	if (n->nlmsg_type == XFRM_MSG_EXPIRE)
@@ -714,26 +803,18 @@
 
 	err = nlmsg_parse(n, sizeof(struct xfrm_usersa_info), tb, XFRMA_MAX, xfrm_sa_policy);
 	if (err < 0)
-		goto errout;
+		return err;
 
-	if (sa_info->sel.family == AF_INET)
-		addr    = nl_addr_build (sa_info->sel.family, &sa_info->sel.daddr.a4, sizeof (sa_info->sel.daddr.a4));
-	else
-		addr    = nl_addr_build (sa_info->sel.family, &sa_info->sel.daddr.a6, sizeof (sa_info->sel.daddr.a6));
-	nl_addr_set_prefixlen (addr, sa_info->sel.prefixlen_d);
-	xfrmnl_sel_set_daddr (sa->sel, addr);
-	/* Drop the reference count from the above set operation */
-	nl_addr_put(addr);
+	if (!(addr1 = _nl_addr_build(sa_info->sel.family, &sa_info->sel.daddr)))
+		return -NLE_NOMEM;
+	nl_addr_set_prefixlen (addr1, sa_info->sel.prefixlen_d);
+	xfrmnl_sel_set_daddr (sa->sel, addr1);
 	xfrmnl_sel_set_prefixlen_d (sa->sel, sa_info->sel.prefixlen_d);
 
-	if (sa_info->sel.family == AF_INET)
-		addr    = nl_addr_build (sa_info->sel.family, &sa_info->sel.saddr.a4, sizeof (sa_info->sel.saddr.a4));
-	else
-		addr    = nl_addr_build (sa_info->sel.family, &sa_info->sel.saddr.a6, sizeof (sa_info->sel.saddr.a6));
-	nl_addr_set_prefixlen (addr, sa_info->sel.prefixlen_s);
-	xfrmnl_sel_set_saddr (sa->sel, addr);
-	/* Drop the reference count from the above set operation */
-	nl_addr_put(addr);
+	if (!(addr2 = _nl_addr_build(sa_info->sel.family, &sa_info->sel.saddr)))
+		return -NLE_NOMEM;
+	nl_addr_set_prefixlen (addr2, sa_info->sel.prefixlen_s);
+	xfrmnl_sel_set_saddr (sa->sel, addr2);
 	xfrmnl_sel_set_prefixlen_s (sa->sel, sa_info->sel.prefixlen_s);
 
 	xfrmnl_sel_set_dport (sa->sel, ntohs(sa_info->sel.dport));
@@ -746,18 +827,14 @@
 	xfrmnl_sel_set_userid (sa->sel, sa_info->sel.user);
 	sa->ce_mask             |= XFRM_SA_ATTR_SEL;
 
-	if (sa_info->family == AF_INET)
-		sa->id.daddr        = nl_addr_build (sa_info->family, &sa_info->id.daddr.a4, sizeof (sa_info->id.daddr.a4));
-	else
-		sa->id.daddr        = nl_addr_build (sa_info->family, &sa_info->id.daddr.a6, sizeof (sa_info->id.daddr.a6));
+	if (!(sa->id.daddr = _nl_addr_build(sa_info->family, &sa_info->id.daddr)))
+		return -NLE_NOMEM;
 	sa->id.spi              = ntohl(sa_info->id.spi);
 	sa->id.proto            = sa_info->id.proto;
 	sa->ce_mask             |= (XFRM_SA_ATTR_DADDR | XFRM_SA_ATTR_SPI | XFRM_SA_ATTR_PROTO);
 
-	if (sa_info->family == AF_INET)
-		sa->saddr           = nl_addr_build (sa_info->family, &sa_info->saddr.a4, sizeof (sa_info->saddr.a4));
-	else
-		sa->saddr           = nl_addr_build (sa_info->family, &sa_info->saddr.a6, sizeof (sa_info->saddr.a6));
+	if (!(sa->saddr = _nl_addr_build(sa_info->family, &sa_info->saddr)))
+		return -NLE_NOMEM;
 	sa->ce_mask             |= XFRM_SA_ATTR_SADDR;
 
 	sa->lft->soft_byte_limit    =   sa_info->lft.soft_byte_limit;
@@ -793,36 +870,30 @@
 
 	if (tb[XFRMA_ALG_AEAD]) {
 		struct xfrm_algo_aead* aead = nla_data(tb[XFRMA_ALG_AEAD]);
+
 		len = sizeof (struct xfrmnl_algo_aead) + ((aead->alg_key_len + 7) / 8);
 		if ((sa->aead = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sa->aead, (void *)aead, len);
 		sa->ce_mask     |= XFRM_SA_ATTR_ALG_AEAD;
 	}
 
 	if (tb[XFRMA_ALG_AUTH_TRUNC]) {
 		struct xfrm_algo_auth* auth = nla_data(tb[XFRMA_ALG_AUTH_TRUNC]);
+
 		len = sizeof (struct xfrmnl_algo_auth) + ((auth->alg_key_len + 7) / 8);
 		if ((sa->auth = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sa->auth, (void *)auth, len);
 		sa->ce_mask     |= XFRM_SA_ATTR_ALG_AUTH;
 	}
 
 	if (tb[XFRMA_ALG_AUTH] && !sa->auth) {
 		struct xfrm_algo* auth = nla_data(tb[XFRMA_ALG_AUTH]);
+
 		len = sizeof (struct xfrmnl_algo_auth) + ((auth->alg_key_len + 7) / 8);
 		if ((sa->auth = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		strcpy(sa->auth->alg_name, auth->alg_name);
 		memcpy(sa->auth->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
 		sa->auth->alg_key_len = auth->alg_key_len;
@@ -831,43 +902,36 @@
 
 	if (tb[XFRMA_ALG_CRYPT]) {
 		struct xfrm_algo* crypt = nla_data(tb[XFRMA_ALG_CRYPT]);
+
 		len = sizeof (struct xfrmnl_algo) + ((crypt->alg_key_len + 7) / 8);
 		if ((sa->crypt = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sa->crypt, (void *)crypt, len);
 		sa->ce_mask     |= XFRM_SA_ATTR_ALG_CRYPT;
 	}
 
 	if (tb[XFRMA_ALG_COMP]) {
 		struct xfrm_algo* comp = nla_data(tb[XFRMA_ALG_COMP]);
+
 		len = sizeof (struct xfrmnl_algo) + ((comp->alg_key_len + 7) / 8);
 		if ((sa->comp = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sa->comp, (void *)comp, len);
 		sa->ce_mask     |= XFRM_SA_ATTR_ALG_COMP;
 	}
 
 	if (tb[XFRMA_ENCAP]) {
 		struct xfrm_encap_tmpl* encap = nla_data(tb[XFRMA_ENCAP]);
+
 		len = sizeof (struct xfrmnl_encap_tmpl);
 		if ((sa->encap = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		sa->encap->encap_type   =   encap->encap_type;
 		sa->encap->encap_sport  =   ntohs(encap->encap_sport);
 		sa->encap->encap_dport  =   ntohs(encap->encap_dport);
-		if (sa_info->family == AF_INET)
-			sa->encap->encap_oa =   nl_addr_build (sa_info->family, &encap->encap_oa.a4, sizeof (encap->encap_oa.a4));
-		else
-			sa->encap->encap_oa =   nl_addr_build (sa_info->family, &encap->encap_oa.a6, sizeof (encap->encap_oa.a6));
+		if (!(sa->encap->encap_oa = _nl_addr_build(sa_info->family,
+							   &encap->encap_oa)))
+			return -NLE_NOMEM;
 		sa->ce_mask     |= XFRM_SA_ATTR_ENCAP;
 	}
 
@@ -877,21 +941,15 @@
 	}
 
 	if (tb[XFRMA_COADDR]) {
-		if (sa_info->family == AF_INET)
-		{
-			sa->coaddr  = nl_addr_build(sa_info->family, nla_data(tb[XFRMA_COADDR]),
-			                            sizeof (uint32_t));
-		}
-		else
-		{
-			sa->coaddr  = nl_addr_build(sa_info->family, nla_data(tb[XFRMA_COADDR]),
-			                            sizeof (uint32_t) * 4);
-		}
+		if (!(sa->coaddr = _nl_addr_build(
+			      sa_info->family, nla_data(tb[XFRMA_COADDR]))))
+			return -NLE_NOMEM;
 		sa->ce_mask         |= XFRM_SA_ATTR_COADDR;
 	}
 
 	if (tb[XFRMA_MARK]) {
 		struct xfrm_mark* m =   nla_data(tb[XFRMA_MARK]);
+
 		sa->mark.m  =   m->m;
 		sa->mark.v  =   m->v;
 		sa->ce_mask |= XFRM_SA_ATTR_MARK;
@@ -899,12 +957,10 @@
 
 	if (tb[XFRMA_SEC_CTX]) {
 		struct xfrm_user_sec_ctx* sec_ctx = nla_data(tb[XFRMA_SEC_CTX]);
+
 		len = sizeof (struct xfrmnl_user_sec_ctx) + sec_ctx->ctx_len;
 		if ((sa->sec_ctx = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy (sa->sec_ctx, sec_ctx, len);
 		sa->ce_mask     |= XFRM_SA_ATTR_SECCTX;
 	}
@@ -921,12 +977,10 @@
 
 	if (tb[XFRMA_REPLAY_ESN_VAL]) {
 		struct xfrm_replay_state_esn* esn = nla_data (tb[XFRMA_REPLAY_ESN_VAL]);
+
 		len =   sizeof (struct xfrmnl_replay_state_esn) + (sizeof (uint32_t) * esn->bmp_len);
 		if ((sa->replay_state_esn = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sa->replay_state_esn, (void *)esn, len);
 		sa->ce_mask |= XFRM_SA_ATTR_REPLAY_STATE;
 	}
@@ -944,24 +998,16 @@
 		struct xfrm_user_offload *offload;
 
 		len = sizeof(struct xfrmnl_user_offload);
-
-		if ((sa->user_offload = calloc(1, len)) == NULL) {
-			err = -NLE_NOMEM;
-			goto errout;
-		}
-
+		if ((sa->user_offload = calloc(1, len)) == NULL)
+			return -NLE_NOMEM;
 		offload = nla_data(tb[XFRMA_OFFLOAD_DEV]);
 		sa->user_offload->ifindex = offload->ifindex;
 		sa->user_offload->flags = offload->flags;
 		sa->ce_mask |= XFRM_SA_ATTR_OFFLOAD_DEV;
 	}
 
-	*result = sa;
+	*result = _nl_steal_pointer(&sa);
 	return 0;
-
-errout:
-	xfrmnl_sa_put(sa);
-	return err;
 }
 
 static int xfrm_sa_update_cache (struct nl_cache *cache, struct nl_object *obj,
@@ -1780,20 +1826,17 @@
  */
 int xfrmnl_sa_get_auth_params (struct xfrmnl_sa* sa, char* alg_name, unsigned int* key_len, unsigned int* trunc_len, char* key)
 {
-	if (sa->ce_mask & XFRM_SA_ATTR_ALG_AUTH)
-	{
-		if (alg_name)
-			strcpy (alg_name, sa->auth->alg_name);
-		if (key_len)
-			*key_len = sa->auth->alg_key_len;
-		if (trunc_len)
-			*trunc_len = sa->auth->alg_trunc_len;
-		if (key)
-			memcpy (key, sa->auth->alg_key, (sa->auth->alg_key_len + 7)/8);
-	}
-	else
-		return -1;
+	if (!(sa->ce_mask & XFRM_SA_ATTR_ALG_AUTH))
+		return -NLE_MISSING_ATTR;
 
+	if (alg_name)
+		strcpy(alg_name, sa->auth->alg_name);
+	if (key_len)
+		*key_len = sa->auth->alg_key_len;
+	if (trunc_len)
+		*trunc_len = sa->auth->alg_trunc_len;
+	if (key)
+		memcpy(key, sa->auth->alg_key, (sa->auth->alg_key_len + 7) / 8);
 	return 0;
 }
 
diff --git a/lib/xfrm/selector.c b/lib/xfrm/selector.c
index 04d30c3..4f14b7b 100644
--- a/lib/xfrm/selector.c
+++ b/lib/xfrm/selector.c
@@ -47,8 +47,26 @@
  * ~~~~
  */
 
+#include "nl-default.h"
+
 #include <netlink/xfrm/selector.h>
-#include <netlink-private/netlink.h>
+
+/* Selector, used as selector both on policy rules (SPD) and SAs. */
+struct xfrmnl_sel {
+	uint32_t        refcnt;
+	struct nl_addr* daddr;
+	struct nl_addr* saddr;
+	uint16_t        dport;
+	uint16_t        dport_mask;
+	uint16_t        sport;
+	uint16_t        sport_mask;
+	uint16_t        family;
+	uint8_t         prefixlen_d;
+	uint8_t         prefixlen_s;
+	uint8_t         proto;
+	int32_t         ifindex;
+	uint32_t        user;
+};
 
 static void sel_destroy(struct xfrmnl_sel* sel)
 {
diff --git a/lib/xfrm/sp.c b/lib/xfrm/sp.c
index df9e2fb..a996455 100644
--- a/lib/xfrm/sp.c
+++ b/lib/xfrm/sp.c
@@ -39,7 +39,8 @@
  * @brief
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
 #include <netlink/cache.h>
 #include <netlink/object.h>
@@ -48,6 +49,38 @@
 #include <netlink/xfrm/template.h>
 #include <netlink/xfrm/sp.h>
 
+#include "nl-xfrm.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-aux-xfrm/nl-xfrm.h"
+
+struct xfrmnl_userpolicy_type {
+	uint8_t                         type;
+	uint16_t                        reserved1;
+	uint16_t                        reserved2;
+};
+
+struct xfrmnl_sp {
+	NLHDR_COMMON
+
+	struct xfrmnl_sel*              sel;
+	struct xfrmnl_ltime_cfg*        lft;
+	struct xfrmnl_lifetime_cur      curlft;
+	uint32_t                        priority;
+	uint32_t                        index;
+	uint8_t                         dir;
+	uint8_t                         action;
+	uint8_t                         flags;
+	uint8_t                         share;
+	struct xfrmnl_user_sec_ctx*     sec_ctx;
+	struct xfrmnl_userpolicy_type   uptype;
+	uint32_t                        nr_user_tmpl;
+	struct nl_list_head             usertmpl_list;
+	struct xfrmnl_mark              mark;
+};
+
 /** @cond SKIP */
 #define XFRM_SP_ATTR_SEL            0x01
 #define XFRM_SP_ATTR_LTIME_CFG      0x02
@@ -151,31 +184,33 @@
 	struct xfrmnl_user_tmpl *tmpl_a, *tmpl_b;
 	uint64_t diff = 0;
 
-#define XFRM_SP_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, XFRM_SP_ATTR_##ATTR, a, b, EXPR)
-	diff |= XFRM_SP_DIFF(SEL,	xfrmnl_sel_cmp(a->sel, b->sel));
-	diff |= XFRM_SP_DIFF(LTIME_CFG,	xfrmnl_ltime_cfg_cmp(a->lft, b->lft));
-	diff |= XFRM_SP_DIFF(PRIO,	a->priority != b->priority);
-	diff |= XFRM_SP_DIFF(INDEX,	a->index != b->index);
-	diff |= XFRM_SP_DIFF(DIR,	a->dir != b->dir);
-	diff |= XFRM_SP_DIFF(ACTION,	a->action != b->action);
-	diff |= XFRM_SP_DIFF(FLAGS,	a->flags != b->flags);
-	diff |= XFRM_SP_DIFF(SHARE,	a->share != b->share);
-	diff |= XFRM_SP_DIFF(SECCTX,((a->sec_ctx->len != b->sec_ctx->len) ||
-	                            (a->sec_ctx->exttype != b->sec_ctx->exttype) ||
-	                            (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) ||
-	                            (a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) ||
-	                            (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) ||
-	                            strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx)));
-	diff |= XFRM_SP_DIFF(POLTYPE,(a->uptype.type != b->uptype.type));
-	diff |= XFRM_SP_DIFF(TMPL,(a->nr_user_tmpl != b->nr_user_tmpl));
-	diff |= XFRM_SP_DIFF(MARK,(a->mark.m != b->mark.m) ||
-	                          (a->mark.v != b->mark.v));
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+	diff |= _DIFF(XFRM_SP_ATTR_SEL, xfrmnl_sel_cmp(a->sel, b->sel));
+	diff |= _DIFF(XFRM_SP_ATTR_LTIME_CFG,
+		      xfrmnl_ltime_cfg_cmp(a->lft, b->lft));
+	diff |= _DIFF(XFRM_SP_ATTR_PRIO, a->priority != b->priority);
+	diff |= _DIFF(XFRM_SP_ATTR_INDEX, a->index != b->index);
+	diff |= _DIFF(XFRM_SP_ATTR_DIR, a->dir != b->dir);
+	diff |= _DIFF(XFRM_SP_ATTR_ACTION, a->action != b->action);
+	diff |= _DIFF(XFRM_SP_ATTR_FLAGS, a->flags != b->flags);
+	diff |= _DIFF(XFRM_SP_ATTR_SHARE, a->share != b->share);
+	diff |= _DIFF(XFRM_SP_ATTR_SECCTX,
+		      ((a->sec_ctx->len != b->sec_ctx->len) ||
+		       (a->sec_ctx->exttype != b->sec_ctx->exttype) ||
+		       (a->sec_ctx->ctx_alg != b->sec_ctx->ctx_alg) ||
+		       (a->sec_ctx->ctx_doi != b->sec_ctx->ctx_doi) ||
+		       (a->sec_ctx->ctx_len != b->sec_ctx->ctx_len) ||
+		       strcmp(a->sec_ctx->ctx, b->sec_ctx->ctx)));
+	diff |= _DIFF(XFRM_SP_ATTR_POLTYPE, (a->uptype.type != b->uptype.type));
+	diff |= _DIFF(XFRM_SP_ATTR_TMPL, (a->nr_user_tmpl != b->nr_user_tmpl));
+	diff |= _DIFF(XFRM_SP_ATTR_MARK,
+		      (a->mark.m != b->mark.m) || (a->mark.v != b->mark.v));
 
 	/* Compare the templates */
 	nl_list_for_each_entry(tmpl_b, &b->usertmpl_list, utmpl_list)
 	nl_list_for_each_entry(tmpl_a, &a->usertmpl_list, utmpl_list)
 	diff |= xfrmnl_user_tmpl_cmp (tmpl_a, tmpl_b);
-#undef XFRM_SP_DIFF
+#undef _DIFF
 
 	return diff;
 }
@@ -324,6 +359,7 @@
 	char                dst[INET6_ADDRSTRLEN+5], src[INET6_ADDRSTRLEN+5];
 	time_t              add_time, use_time;
 	struct tm           *add_time_tm, *use_time_tm;
+	struct tm           tm_buf;
 
 	nl_addr2str(xfrmnl_sel_get_saddr (sp->sel), src, sizeof(src));
 	nl_addr2str (xfrmnl_sel_get_daddr (sp->sel), dst, sizeof (dst));
@@ -384,7 +420,7 @@
 	if (sp->curlft.add_time != 0)
 	{
 		add_time = sp->curlft.add_time;
-		add_time_tm = gmtime (&add_time);
+		add_time_tm = gmtime_r (&add_time, &tm_buf);
 		strftime (dst, INET6_ADDRSTRLEN+5, "%Y-%m-%d %H-%M-%S", add_time_tm);
 	}
 	else
@@ -395,7 +431,7 @@
 	if (sp->curlft.use_time != 0)
 	{
 		use_time = sp->curlft.use_time;
-		use_time_tm = gmtime (&use_time);
+		use_time_tm = gmtime_r (&use_time, &tm_buf);
 		strftime (src, INET6_ADDRSTRLEN+5, "%Y-%m-%d %H-%M-%S", use_time_tm);
 	}
 	else
@@ -527,49 +563,37 @@
 
 int xfrmnl_sp_parse(struct nlmsghdr *n, struct xfrmnl_sp **result)
 {
-	struct xfrmnl_sp                *sp;
+	_nl_auto_nl_addr struct nl_addr *addr1 = NULL;
+	_nl_auto_nl_addr struct nl_addr *addr2 = NULL;
+	_nl_auto_xfrmnl_sp struct xfrmnl_sp *sp = NULL;
 	struct nlattr                   *tb[XFRMA_MAX + 1];
 	struct xfrm_userpolicy_info     *sp_info;
 	int                             len, err;
-	struct nl_addr*                 addr;
 
 	sp = xfrmnl_sp_alloc();
-	if (!sp) {
-		err = -NLE_NOMEM;
-		goto errout;
-	}
+	if (!sp)
+		return -NLE_NOMEM;
 
 	sp->ce_msgtype = n->nlmsg_type;
 	if (n->nlmsg_type == XFRM_MSG_DELPOLICY)
-	{
 		sp_info = (struct xfrm_userpolicy_info*)((char *)nlmsg_data(n) + sizeof (struct xfrm_userpolicy_id) + NLA_HDRLEN);
-	}
 	else
-	{
 		sp_info = nlmsg_data(n);
-	}
 
 	err = nlmsg_parse(n, sizeof(struct xfrm_userpolicy_info), tb, XFRMA_MAX, xfrm_sp_policy);
 	if (err < 0)
-	{
-		printf ("parse error: %d \n", err);
-		goto errout;
-	}
+		return err;
 
-	if (sp_info->sel.family == AF_INET)
-		addr    = nl_addr_build (sp_info->sel.family, &sp_info->sel.daddr.a4, sizeof (sp_info->sel.daddr.a4));
-	else
-		addr    = nl_addr_build (sp_info->sel.family, &sp_info->sel.daddr.a6, sizeof (sp_info->sel.daddr.a6));
-	nl_addr_set_prefixlen (addr, sp_info->sel.prefixlen_d);
-	xfrmnl_sel_set_daddr (sp->sel, addr);
+	if (!(addr1 = _nl_addr_build(sp_info->sel.family, &sp_info->sel.daddr)))
+		return -NLE_NOMEM;
+	nl_addr_set_prefixlen (addr1, sp_info->sel.prefixlen_d);
+	xfrmnl_sel_set_daddr (sp->sel, addr1);
 	xfrmnl_sel_set_prefixlen_d (sp->sel, sp_info->sel.prefixlen_d);
 
-	if (sp_info->sel.family == AF_INET)
-		addr    = nl_addr_build (sp_info->sel.family, &sp_info->sel.saddr.a4, sizeof (sp_info->sel.saddr.a4));
-	else
-		addr    = nl_addr_build (sp_info->sel.family, &sp_info->sel.saddr.a6, sizeof (sp_info->sel.saddr.a6));
-	nl_addr_set_prefixlen (addr, sp_info->sel.prefixlen_s);
-	xfrmnl_sel_set_saddr (sp->sel, addr);
+	if (!(addr2 = _nl_addr_build(sp_info->sel.family, &sp_info->sel.saddr)))
+		return -NLE_NOMEM;
+	nl_addr_set_prefixlen (addr2, sp_info->sel.prefixlen_s);
+	xfrmnl_sel_set_saddr (sp->sel, addr2);
 	xfrmnl_sel_set_prefixlen_s (sp->sel, sp_info->sel.prefixlen_s);
 
 	xfrmnl_sel_set_dport (sp->sel, ntohs (sp_info->sel.dport));
@@ -610,51 +634,45 @@
 
 	if (tb[XFRMA_SEC_CTX]) {
 		struct xfrm_user_sec_ctx* ctx = nla_data(tb[XFRMA_SEC_CTX]);
+
 		len = sizeof (struct xfrmnl_user_sec_ctx) + ctx->ctx_len;
 		if ((sp->sec_ctx = calloc (1, len)) == NULL)
-		{
-			err = -NLE_NOMEM;
-			goto errout;
-		}
+			return -NLE_NOMEM;
 		memcpy ((void *)sp->sec_ctx, (void *)ctx, len);
 		sp->ce_mask     |= XFRM_SP_ATTR_SECCTX;
 	}
 
 	if (tb[XFRMA_POLICY_TYPE]) {
 		struct xfrm_userpolicy_type* up = nla_data(tb[XFRMA_POLICY_TYPE]);
+
 		memcpy ((void *)&sp->uptype, (void *)up, sizeof (struct xfrm_userpolicy_type));
 		sp->ce_mask     |= XFRM_SP_ATTR_POLTYPE;
 	}
 
 	if (tb[XFRMA_TMPL]) {
 		struct xfrm_user_tmpl*      tmpl = nla_data(tb[XFRMA_TMPL]);
-		struct xfrmnl_user_tmpl*    sputmpl;
 		uint32_t                    i;
 		uint32_t                    num_tmpls = nla_len(tb[XFRMA_TMPL]) / sizeof (*tmpl);
-		struct  nl_addr*            addr;
 
 		for (i = 0; (i < num_tmpls) && (tmpl); i ++, tmpl++)
 		{
-			if ((sputmpl = xfrmnl_user_tmpl_alloc ()) == NULL)
-			{
-				err = -NLE_NOMEM;
-				goto errout;
-			}
+			_nl_auto_xfrmnl_user_tmpl struct xfrmnl_user_tmpl *sputmpl = NULL;
+			_nl_auto_nl_addr struct nl_addr *addr1 = NULL;
+			_nl_auto_nl_addr struct nl_addr *addr2 = NULL;
 
-			if (tmpl->family == AF_INET)
-				addr = nl_addr_build(tmpl->family, &tmpl->id.daddr.a4, sizeof (tmpl->id.daddr.a4));
-			else
-				addr = nl_addr_build(tmpl->family, &tmpl->id.daddr.a6, sizeof (tmpl->id.daddr.a6));
-			xfrmnl_user_tmpl_set_daddr (sputmpl, addr);
+			if ((sputmpl = xfrmnl_user_tmpl_alloc ()) == NULL)
+				return -NLE_NOMEM;
+
+			if (!(addr1 = _nl_addr_build(tmpl->family, &tmpl->id.daddr)))
+				return -NLE_NOMEM;
+			xfrmnl_user_tmpl_set_daddr (sputmpl, addr1);
 			xfrmnl_user_tmpl_set_spi (sputmpl, ntohl(tmpl->id.spi));
 			xfrmnl_user_tmpl_set_proto (sputmpl, tmpl->id.proto);
 			xfrmnl_user_tmpl_set_family (sputmpl, tmpl->family);
 
-			if (tmpl->family == AF_INET)
-				addr = nl_addr_build(tmpl->family, &tmpl->saddr.a4, sizeof (tmpl->saddr.a4));
-			else
-				addr = nl_addr_build(tmpl->family, &tmpl->saddr.a6, sizeof (tmpl->saddr.a6));
-			xfrmnl_user_tmpl_set_saddr (sputmpl, addr);
+			if (!(addr2 = _nl_addr_build(tmpl->family, &tmpl->saddr)))
+				return -NLE_NOMEM;
+			xfrmnl_user_tmpl_set_saddr (sputmpl, addr2);
 
 			xfrmnl_user_tmpl_set_reqid (sputmpl, tmpl->reqid);
 			xfrmnl_user_tmpl_set_mode (sputmpl, tmpl->mode);
@@ -663,7 +681,7 @@
 			xfrmnl_user_tmpl_set_aalgos (sputmpl, tmpl->aalgos);
 			xfrmnl_user_tmpl_set_ealgos (sputmpl, tmpl->ealgos);
 			xfrmnl_user_tmpl_set_calgos (sputmpl, tmpl->calgos);
-			xfrmnl_sp_add_usertemplate (sp, sputmpl);
+			xfrmnl_sp_add_usertemplate (sp, _nl_steal_pointer(&sputmpl));
 
 			sp->ce_mask     |=  XFRM_SP_ATTR_TMPL;
 		}
@@ -676,12 +694,8 @@
 		sp->ce_mask |= XFRM_SP_ATTR_MARK;
 	}
 
-	*result = sp;
+	*result = _nl_steal_pointer(&sp);
 	return 0;
-
-errout:
-	xfrmnl_sp_put(sp);
-	return err;
 }
 
 static int xfrm_sp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
@@ -1316,6 +1330,8 @@
 	if (sp->ce_mask & XFRM_SP_ATTR_TMPL) {
 		sp->nr_user_tmpl--;
 		nl_list_del(&utmpl->utmpl_list);
+		if (sp->nr_user_tmpl == 0)
+			sp->ce_mask &= ~XFRM_SP_ATTR_TMPL;
 	}
 }
 
diff --git a/lib/xfrm/template.c b/lib/xfrm/template.c
index 0561869..2a42b28 100644
--- a/lib/xfrm/template.c
+++ b/lib/xfrm/template.c
@@ -47,8 +47,12 @@
  * ~~~~
  */
 
+#include "nl-default.h"
+
 #include <netlink/xfrm/template.h>
-#include <netlink-private/netlink.h>
+
+#include "nl-xfrm.h"
+#include "nl-priv-dynamic-core/nl-core.h"
 
 void xfrmnl_user_tmpl_free(struct xfrmnl_user_tmpl* utmpl)
 {
diff --git a/libnl-3.sym b/libnl-3.sym
index 95100b1..bac4fcd 100644
--- a/libnl-3.sym
+++ b/libnl-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	# these functions are in private header files and should have never
@@ -365,6 +371,4 @@
 } libnl_3_2_29;
 
 libnl_3_6 {
-global:
-	rtnl_link_info_ops_get;
 } libnl_3_5;
diff --git a/libnl-cli-3.sym b/libnl-cli-3.sym
index 71ff2eb..75f03cd 100644
--- a/libnl-cli-3.sym
+++ b/libnl-cli-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	nl_cli_addr_alloc;
@@ -115,3 +121,9 @@
 	nl_cli_link_alloc_cache_flags;
 	nl_cli_link_alloc_cache_family_flags;
 } libnl_3;
+
+libnl_3_8 {
+global:
+	nl_cli_nh_alloc;
+	nl_cli_nh_alloc_cache;
+} libnl_3_2_28;
diff --git a/libnl-genl-3.sym b/libnl-genl-3.sym
index 0f9616d..1b26127 100644
--- a/libnl-genl-3.sym
+++ b/libnl-genl-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	# these functions are in private header files and should have never
diff --git a/libnl-idiag-3.sym b/libnl-idiag-3.sym
index c56cef5..3391f19 100644
--- a/libnl-idiag-3.sym
+++ b/libnl-idiag-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	# ops structure
diff --git a/libnl-nf-3.sym b/libnl-nf-3.sym
index 013c1ee..7563624 100644
--- a/libnl-nf-3.sym
+++ b/libnl-nf-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	# ops structure
diff --git a/libnl-route-3.sym b/libnl-route-3.sym
index e54bc6d..fa7af45 100644
--- a/libnl-route-3.sym
+++ b/libnl-route-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	# these functions are in private header files and should have never
@@ -13,6 +19,10 @@
 	rtnl_link_info_ops_put;
 	rtnl_link_register_info;
 	rtnl_link_unregister_info;
+
+	# these functions are in private header files and should have never
+	# been exported.
+	# declared in "lib/route/tc-api.h".
 	rtnl_tc_build_rate_table;
 	rtnl_tc_clone;
 	rtnl_tc_compare;
@@ -30,7 +40,8 @@
 	rtnl_tc_unregister;
 
 	# these functions are in private header files and should have never
-	# been exported. They are used by libnl internals
+	# been exported. They are used by libnl internals.
+	# declared in "include/nl-priv-dynamic-route/nl-priv-dynamic-route.h".
 	rtnl_tc_get_ops;
 	rtnl_tc_lookup_ops;
 
@@ -1268,3 +1279,38 @@
 	rtnl_nat_set_new_addr;
 	rtnl_nat_set_old_addr;
 } libnl_3_6;
+
+libnl_3_8 {
+global:
+	rtnl_link_bond_set_activeslave;
+	rtnl_link_bond_set_mode;
+	rtnl_link_bridge_get_vlan_filtering;
+	rtnl_link_bridge_get_vlan_protocol;
+	rtnl_link_bridge_get_vlan_stats_enabled;
+	rtnl_link_bridge_set_vlan_filtering;
+	rtnl_link_bridge_set_vlan_protocol;
+	rtnl_link_bridge_set_vlan_stats_enabled;
+	rtnl_link_inet6_get_conf;
+	rtnl_link_info_ops_get;
+	rtnl_neigh_get_nhid;
+	rtnl_neigh_set_nhid;
+	rtnl_nh_alloc;
+	rtnl_nh_alloc_cache;
+	rtnl_nh_get;
+	rtnl_nh_get_fdb;
+	rtnl_nh_get_gateway;
+	rtnl_nh_get_group_entry;
+	rtnl_nh_get_group_size;
+	rtnl_nh_get_id;
+	rtnl_nh_put;
+	rtnl_nh_set_fdb;
+	rtnl_nh_set_gateway;
+} libnl_3_7;
+
+libnl_3_9 {
+global:
+	rtnl_link_bond_set_hashing_type;
+	rtnl_link_bond_set_miimon;
+	rtnl_link_bond_set_min_links;
+	rtnl_link_can_get_device_stats;
+} libnl_3_8;
diff --git a/libnl-xfrm-3.sym b/libnl-xfrm-3.sym
index 7f5858f..ed7c7ad 100644
--- a/libnl-xfrm-3.sym
+++ b/libnl-xfrm-3.sym
@@ -1,3 +1,9 @@
+# The linker version script controls which symbols are exported.
+# Version tags that correspond to past releases group the symbols
+# that were part of that release. Hence, such a version tag is sealed
+# and MUST not be extended.
+# Any new symbols MUST only be added to the bottom of the file, in
+# the version tag for the next upcoming release.
 libnl_3 {
 global:
 	xfrmnl_ae_alloc;
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..bce61cb
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,8 @@
+[tool.black]
+target-versions = ["py37", "py38", "py39", "py310"]
+include = '''
+    (
+        \.py$
+        | \.py\.in$
+    )
+    '''
diff --git a/python/doc/conf.py b/python/doc/conf.py
index 74041f0..dfa53ab 100644
--- a/python/doc/conf.py
+++ b/python/doc/conf.py
@@ -11,199 +11,202 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
-
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
 # documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+# sys.path.insert(0, os.path.abspath('.'))
 
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
-#needs_sphinx = '1.0'
+# needs_sphinx = '1.0'
 
 # Add any Sphinx extension module names here, as strings. They can be extensions
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
+extensions = ["sphinx.ext.todo", "sphinx.ext.ifconfig", "sphinx.ext.viewcode"]
 
 # Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
 
 # The suffix of source filenames.
-source_suffix = '.rst'
+source_suffix = ".rst"
 
 # The encoding of source files.
-#source_encoding = 'utf-8-sig'
+# source_encoding = 'utf-8-sig'
 
 # The master toctree document.
-master_doc = 'index'
+master_doc = "index"
 
 # General information about the project.
-project = u'libnl-python'
-copyright = u'2011, Thomas Graf <tgraf@suug.ch>'
+project = "libnl-python"
+copyright = "2011, Thomas Graf <tgraf@suug.ch>"
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '1.0'
+version = "1.0"
 # The full version, including alpha/beta/rc tags.
-release = '1.0'
+release = "1.0"
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
-#language = None
+# language = None
 
 # There are two options for replacing |today|: either, you set today to some
 # non-false value, then it is used:
-#today = ''
+# today = ''
 # Else, today_fmt is used as the format for a strftime call.
-#today_fmt = '%B %d, %Y'
+# today_fmt = '%B %d, %Y'
 
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ["_build"]
 
 # The reST default role (used for this markup: `text`) to use for all documents.
-#default_role = None
+# default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+# add_function_parentheses = True
 
 # If true, the current module name will be prepended to all description
 # unit titles (such as .. function::).
-#add_module_names = True
+# add_module_names = True
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
-#show_authors = False
+# show_authors = False
 
 # The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+# modindex_common_prefix = []
 
 
 # -- Options for HTML output ---------------------------------------------------
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'default'
+html_theme = "default"
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
 # documentation.
-#html_theme_options = {}
+# html_theme_options = {}
 
 # Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
+# html_theme_path = []
 
 # The name for this set of Sphinx documents.  If None, it defaults to
 # "<project> v<release> documentation".
-#html_title = None
+# html_title = None
 
 # A shorter title for the navigation bar.  Default is the same as html_title.
-#html_short_title = None
+# html_short_title = None
 
 # The name of an image file (relative to this directory) to place at the top
 # of the sidebar.
-#html_logo = None
+# html_logo = None
 
 # The name of an image file (within the static path) to use as favicon of the
 # docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 # pixels large.
-#html_favicon = None
+# html_favicon = None
 
 # Add any paths that contain custom static files (such as style sheets) here,
 # relative to this directory. They are copied after the builtin static files,
 # so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = ["_static"]
 
 # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 # using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
+# html_last_updated_fmt = '%b %d, %Y'
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+# html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+# html_sidebars = {}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.
-#html_additional_pages = {}
+# html_additional_pages = {}
 
 # If false, no module index is generated.
-#html_domain_indices = True
+# html_domain_indices = True
 
 # If false, no index is generated.
-#html_use_index = True
+# html_use_index = True
 
 # If true, the index is split into individual pages for each letter.
-#html_split_index = False
+# html_split_index = False
 
 # If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
+# html_show_sourcelink = True
 
 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+# html_show_sphinx = True
 
 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+# html_show_copyright = True
 
 # If true, an OpenSearch description file will be output, and all pages will
 # contain a <link> tag referring to it.  The value of this option must be the
 # base URL from which the finished HTML is served.
-#html_use_opensearch = ''
+# html_use_opensearch = ''
 
 # This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
+# html_file_suffix = None
 
 # Output file base name for HTML help builder.
-htmlhelp_basename = 'libnl-pythondoc'
+htmlhelp_basename = "libnl-pythondoc"
 
 
 # -- Options for LaTeX output --------------------------------------------------
 
 # The paper size ('letter' or 'a4').
-#latex_paper_size = 'letter'
+# latex_paper_size = 'letter'
 
 # The font size ('10pt', '11pt' or '12pt').
-#latex_font_size = '10pt'
+# latex_font_size = '10pt'
 
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, documentclass [howto/manual]).
 latex_documents = [
-  ('index', 'libnl-python.tex', u'libnl-python Documentation',
-   u'Thomas Graf \\textless{}tgraf@suug.ch\\textgreater{}', 'manual'),
+    (
+        "index",
+        "libnl-python.tex",
+        "libnl-python Documentation",
+        "Thomas Graf \\textless{}tgraf@suug.ch\\textgreater{}",
+        "manual",
+    ),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
-#latex_logo = None
+# latex_logo = None
 
 # For "manual" documents, if this is true, then toplevel headings are parts,
 # not chapters.
-#latex_use_parts = False
+# latex_use_parts = False
 
 # If true, show page references after internal links.
-#latex_show_pagerefs = False
+# latex_show_pagerefs = False
 
 # If true, show URL addresses after external links.
-#latex_show_urls = False
+# latex_show_urls = False
 
 # Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
+# latex_preamble = ''
 
 # Documents to append as an appendix to all manuals.
-#latex_appendices = []
+# latex_appendices = []
 
 # If false, no module index is generated.
-#latex_domain_indices = True
+# latex_domain_indices = True
 
 
 # -- Options for manual page output --------------------------------------------
@@ -211,6 +214,11 @@
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
 man_pages = [
-    ('index', 'libnl-python', u'libnl-python Documentation',
-     [u'Thomas Graf <tgraf@suug.ch>'], 1)
+    (
+        "index",
+        "libnl-python",
+        "libnl-python Documentation",
+        ["Thomas Graf <tgraf@suug.ch>"],
+        1,
+    )
 ]
diff --git a/python/examples/iface.py b/python/examples/iface.py
index ddf5f12..afeafff 100644
--- a/python/examples/iface.py
+++ b/python/examples/iface.py
@@ -5,90 +5,108 @@
 import sys
 import traceback
 
+
 class test_class:
-	def __init__(self):
-		self.done = 1
+    def __init__(self):
+        self.done = 1
+
 
 def msg_handler(m, a):
-	try:
-		e, attr = genl.py_genlmsg_parse(nl.nlmsg_hdr(m), 0,
-						nl80211.NL80211_ATTR_MAX, None)
-		if nl80211.NL80211_ATTR_WIPHY in attr:
-			thiswiphy = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY])
-			print("phy#%d" % thiswiphy)
-		if nl80211.NL80211_ATTR_IFNAME in attr:
-			print("\tinterface %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_IFNAME]))
-		if nl80211.NL80211_ATTR_IFINDEX in attr:
-			print("\tifindex %d" % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFINDEX]))
-		if nl80211.NL80211_ATTR_WDEV in attr:
-			print("\twdev 0x%lx" % nl.nla_get_u64(attr[nl80211.NL80211_ATTR_WDEV]))
-		if nl80211.NL80211_ATTR_MAC in attr:
-			print("\tmac %02x:%02x:%02x:%02x:%02x:%02x" % tuple(nl.nla_data(attr[nl80211.NL80211_ATTR_MAC])))
-		if nl80211.NL80211_ATTR_SSID in attr:
-			print("\tssid ", nl.nla_data(attr[nl80211.NL80211_ATTR_SSID]))
-		if nl80211.NL80211_ATTR_IFTYPE in attr:
-			iftype = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFTYPE])
-			print("\ttype %s" % nl80211.nl80211_iftype2str[iftype])
-		if nl80211.NL80211_ATTR_WIPHY_FREQ in attr:
-			freq = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY_FREQ])
+    try:
+        e, attr = genl.py_genlmsg_parse(
+            nl.nlmsg_hdr(m), 0, nl80211.NL80211_ATTR_MAX, None
+        )
+        if nl80211.NL80211_ATTR_WIPHY in attr:
+            thiswiphy = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY])
+            print("phy#%d" % thiswiphy)
+        if nl80211.NL80211_ATTR_IFNAME in attr:
+            print(
+                "\tinterface %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_IFNAME])
+            )
+        if nl80211.NL80211_ATTR_IFINDEX in attr:
+            print("\tifindex %d" % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFINDEX]))
+        if nl80211.NL80211_ATTR_WDEV in attr:
+            print("\twdev 0x%lx" % nl.nla_get_u64(attr[nl80211.NL80211_ATTR_WDEV]))
+        if nl80211.NL80211_ATTR_MAC in attr:
+            print(
+                "\tmac %02x:%02x:%02x:%02x:%02x:%02x"
+                % tuple(nl.nla_data(attr[nl80211.NL80211_ATTR_MAC]))
+            )
+        if nl80211.NL80211_ATTR_SSID in attr:
+            print("\tssid ", nl.nla_data(attr[nl80211.NL80211_ATTR_SSID]))
+        if nl80211.NL80211_ATTR_IFTYPE in attr:
+            iftype = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_IFTYPE])
+            print("\ttype %s" % nl80211.nl80211_iftype2str[iftype])
+        if nl80211.NL80211_ATTR_WIPHY_FREQ in attr:
+            freq = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY_FREQ])
 
-			sys.stdout.write("\tfreq %d MHz" % freq)
+            sys.stdout.write("\tfreq %d MHz" % freq)
 
-			if nl80211.NL80211_ATTR_CHANNEL_WIDTH in attr:
-				chanw = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CHANNEL_WIDTH])
-				sys.stdout.write(", width: %s" % nl80211.nl80211_chan_width2str[chanw])
-				if nl80211.NL80211_ATTR_CENTER_FREQ1 in attr:
-					sys.stdout.write(", center1: %d MHz" %
-						nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ1]))
-				if nl80211.NL80211_ATTR_CENTER_FREQ2 in attr:
-					sys.stdout.write(", center2: %d MHz" %
-						nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ2]))
-			elif nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE in attr:
-				channel_type = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE])
-				sys.stdout.write(" %s" % nl80211.nl80211_channel_type2str(channel_type))
+            if nl80211.NL80211_ATTR_CHANNEL_WIDTH in attr:
+                chanw = nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CHANNEL_WIDTH])
+                sys.stdout.write(", width: %s" % nl80211.nl80211_chan_width2str[chanw])
+                if nl80211.NL80211_ATTR_CENTER_FREQ1 in attr:
+                    sys.stdout.write(
+                        ", center1: %d MHz"
+                        % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ1])
+                    )
+                if nl80211.NL80211_ATTR_CENTER_FREQ2 in attr:
+                    sys.stdout.write(
+                        ", center2: %d MHz"
+                        % nl.nla_get_u32(attr[nl80211.NL80211_ATTR_CENTER_FREQ2])
+                    )
+            elif nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE in attr:
+                channel_type = nl.nla_get_u32(
+                    attr[nl80211.NL80211_ATTR_WIPHY_CHANNEL_TYPE]
+                )
+                sys.stdout.write(" %s" % nl80211.nl80211_channel_type2str(channel_type))
 
-			sys.stdout.write("\n")
-		return nl.NL_SKIP
-	except Exception as e:
-		(t,v,tb) = sys.exc_info()
-		print(v.message)
-		traceback.print_tb(tb)
+            sys.stdout.write("\n")
+        return nl.NL_SKIP
+    except Exception:
+        (t, v, tb) = sys.exc_info()
+        print(v.message)
+        traceback.print_tb(tb)
+
 
 def error_handler(err, a):
-	a.done = err.error
-	return nl.NL_STOP
+    a.done = err.error
+    return nl.NL_STOP
+
 
 def finish_handler(m, a):
-	return nl.NL_SKIP
+    return nl.NL_SKIP
+
 
 def ack_handler(m, a):
-	a.done = 0
-	return nl.NL_STOP
+    a.done = 0
+    return nl.NL_STOP
+
 
 try:
-	cbd = test_class()
-	tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT)
-	rx_cb = nl.nl_cb_clone(tx_cb)
-	s = nl.nl_socket_alloc_cb(tx_cb)
-	nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd)
+    cbd = test_class()
+    tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT)
+    rx_cb = nl.nl_cb_clone(tx_cb)
+    s = nl.nl_socket_alloc_cb(tx_cb)
+    nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd)
 
-	genl.genl_connect(s)
-	family = genl.genl_ctrl_resolve(s, 'nl80211')
-	m = nl.nlmsg_alloc()
-	genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_INTERFACE, 0)
-	nl.nla_put_u32(m, nl80211.NL80211_ATTR_IFINDEX, nl.if_nametoindex('wlan0'))
+    genl.genl_connect(s)
+    family = genl.genl_ctrl_resolve(s, "nl80211")
+    m = nl.nlmsg_alloc()
+    genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_INTERFACE, 0)
+    nl.nla_put_u32(m, nl80211.NL80211_ATTR_IFINDEX, nl.if_nametoindex("wlan0"))
 
-	err = nl.nl_send_auto_complete(s, m)
-	if err < 0:
-		nl.nlmsg_free(m)
+    err = nl.nl_send_auto_complete(s, m)
+    if err < 0:
+        nl.nlmsg_free(m)
 
-	while cbd.done > 0 and not err < 0:
-		err = nl.nl_recvmsgs(s, rx_cb)
+    while cbd.done > 0 and not err < 0:
+        err = nl.nl_recvmsgs(s, rx_cb)
 
-except Exception as e:
-	(t, v, tb) = sys.exc_info()
-	print(v.message)
-	traceback.print_tb(tb)
+except Exception:
+    (t, v, tb) = sys.exc_info()
+    print(v.message)
+    traceback.print_tb(tb)
diff --git a/python/examples/nl80211.py b/python/examples/nl80211.py
index 7434bef..88ea535 100644
--- a/python/examples/nl80211.py
+++ b/python/examples/nl80211.py
@@ -3,7 +3,7 @@
 # ---------------------------------------------------------
 # This file is generated using extract.py using pycparser
 ###########################################################
-NL80211_GENL_FAMILY = 'nl80211'
+NL80211_GENL_FAMILY = "nl80211"
 
 NL80211_CMD_UNSPEC = 0
 NL80211_CMD_GET_WIPHY = 1
@@ -750,828 +750,826 @@
 NL80211_CRIT_PROTO_APIPA = 3
 NUM_NL80211_CRIT_PROTO = 4
 nl80211_commands2str = {
-	NL80211_CMD_UNSPEC: "NL80211_CMD_UNSPEC",
-	NL80211_CMD_GET_WIPHY: "NL80211_CMD_GET_WIPHY",
-	NL80211_CMD_SET_WIPHY: "NL80211_CMD_SET_WIPHY",
-	NL80211_CMD_NEW_WIPHY: "NL80211_CMD_NEW_WIPHY",
-	NL80211_CMD_DEL_WIPHY: "NL80211_CMD_DEL_WIPHY",
-	NL80211_CMD_GET_INTERFACE: "NL80211_CMD_GET_INTERFACE",
-	NL80211_CMD_SET_INTERFACE: "NL80211_CMD_SET_INTERFACE",
-	NL80211_CMD_NEW_INTERFACE: "NL80211_CMD_NEW_INTERFACE",
-	NL80211_CMD_DEL_INTERFACE: "NL80211_CMD_DEL_INTERFACE",
-	NL80211_CMD_GET_KEY: "NL80211_CMD_GET_KEY",
-	NL80211_CMD_SET_KEY: "NL80211_CMD_SET_KEY",
-	NL80211_CMD_NEW_KEY: "NL80211_CMD_NEW_KEY",
-	NL80211_CMD_DEL_KEY: "NL80211_CMD_DEL_KEY",
-	NL80211_CMD_GET_BEACON: "NL80211_CMD_GET_BEACON",
-	NL80211_CMD_SET_BEACON: "NL80211_CMD_SET_BEACON",
-	NL80211_CMD_START_AP: "NL80211_CMD_START_AP",
-	NL80211_CMD_STOP_AP: "NL80211_CMD_STOP_AP",
-	NL80211_CMD_GET_STATION: "NL80211_CMD_GET_STATION",
-	NL80211_CMD_SET_STATION: "NL80211_CMD_SET_STATION",
-	NL80211_CMD_NEW_STATION: "NL80211_CMD_NEW_STATION",
-	NL80211_CMD_DEL_STATION: "NL80211_CMD_DEL_STATION",
-	NL80211_CMD_GET_MPATH: "NL80211_CMD_GET_MPATH",
-	NL80211_CMD_SET_MPATH: "NL80211_CMD_SET_MPATH",
-	NL80211_CMD_NEW_MPATH: "NL80211_CMD_NEW_MPATH",
-	NL80211_CMD_DEL_MPATH: "NL80211_CMD_DEL_MPATH",
-	NL80211_CMD_SET_BSS: "NL80211_CMD_SET_BSS",
-	NL80211_CMD_SET_REG: "NL80211_CMD_SET_REG",
-	NL80211_CMD_REQ_SET_REG: "NL80211_CMD_REQ_SET_REG",
-	NL80211_CMD_GET_MESH_CONFIG: "NL80211_CMD_GET_MESH_CONFIG",
-	NL80211_CMD_SET_MESH_CONFIG: "NL80211_CMD_SET_MESH_CONFIG",
-	NL80211_CMD_SET_MGMT_EXTRA_IE: "NL80211_CMD_SET_MGMT_EXTRA_IE",
-	NL80211_CMD_GET_REG: "NL80211_CMD_GET_REG",
-	NL80211_CMD_GET_SCAN: "NL80211_CMD_GET_SCAN",
-	NL80211_CMD_TRIGGER_SCAN: "NL80211_CMD_TRIGGER_SCAN",
-	NL80211_CMD_NEW_SCAN_RESULTS: "NL80211_CMD_NEW_SCAN_RESULTS",
-	NL80211_CMD_SCAN_ABORTED: "NL80211_CMD_SCAN_ABORTED",
-	NL80211_CMD_REG_CHANGE: "NL80211_CMD_REG_CHANGE",
-	NL80211_CMD_AUTHENTICATE: "NL80211_CMD_AUTHENTICATE",
-	NL80211_CMD_ASSOCIATE: "NL80211_CMD_ASSOCIATE",
-	NL80211_CMD_DEAUTHENTICATE: "NL80211_CMD_DEAUTHENTICATE",
-	NL80211_CMD_DISASSOCIATE: "NL80211_CMD_DISASSOCIATE",
-	NL80211_CMD_MICHAEL_MIC_FAILURE: "NL80211_CMD_MICHAEL_MIC_FAILURE",
-	NL80211_CMD_REG_BEACON_HINT: "NL80211_CMD_REG_BEACON_HINT",
-	NL80211_CMD_JOIN_IBSS: "NL80211_CMD_JOIN_IBSS",
-	NL80211_CMD_LEAVE_IBSS: "NL80211_CMD_LEAVE_IBSS",
-	NL80211_CMD_TESTMODE: "NL80211_CMD_TESTMODE",
-	NL80211_CMD_CONNECT: "NL80211_CMD_CONNECT",
-	NL80211_CMD_ROAM: "NL80211_CMD_ROAM",
-	NL80211_CMD_DISCONNECT: "NL80211_CMD_DISCONNECT",
-	NL80211_CMD_SET_WIPHY_NETNS: "NL80211_CMD_SET_WIPHY_NETNS",
-	NL80211_CMD_GET_SURVEY: "NL80211_CMD_GET_SURVEY",
-	NL80211_CMD_NEW_SURVEY_RESULTS: "NL80211_CMD_NEW_SURVEY_RESULTS",
-	NL80211_CMD_SET_PMKSA: "NL80211_CMD_SET_PMKSA",
-	NL80211_CMD_DEL_PMKSA: "NL80211_CMD_DEL_PMKSA",
-	NL80211_CMD_FLUSH_PMKSA: "NL80211_CMD_FLUSH_PMKSA",
-	NL80211_CMD_REMAIN_ON_CHANNEL: "NL80211_CMD_REMAIN_ON_CHANNEL",
-	NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL",
-	NL80211_CMD_SET_TX_BITRATE_MASK: "NL80211_CMD_SET_TX_BITRATE_MASK",
-	NL80211_CMD_REGISTER_FRAME: "NL80211_CMD_REGISTER_FRAME",
-	NL80211_CMD_FRAME: "NL80211_CMD_FRAME",
-	NL80211_CMD_FRAME_TX_STATUS: "NL80211_CMD_FRAME_TX_STATUS",
-	NL80211_CMD_SET_POWER_SAVE: "NL80211_CMD_SET_POWER_SAVE",
-	NL80211_CMD_GET_POWER_SAVE: "NL80211_CMD_GET_POWER_SAVE",
-	NL80211_CMD_SET_CQM: "NL80211_CMD_SET_CQM",
-	NL80211_CMD_NOTIFY_CQM: "NL80211_CMD_NOTIFY_CQM",
-	NL80211_CMD_SET_CHANNEL: "NL80211_CMD_SET_CHANNEL",
-	NL80211_CMD_SET_WDS_PEER: "NL80211_CMD_SET_WDS_PEER",
-	NL80211_CMD_FRAME_WAIT_CANCEL: "NL80211_CMD_FRAME_WAIT_CANCEL",
-	NL80211_CMD_JOIN_MESH: "NL80211_CMD_JOIN_MESH",
-	NL80211_CMD_LEAVE_MESH: "NL80211_CMD_LEAVE_MESH",
-	NL80211_CMD_UNPROT_DEAUTHENTICATE: "NL80211_CMD_UNPROT_DEAUTHENTICATE",
-	NL80211_CMD_UNPROT_DISASSOCIATE: "NL80211_CMD_UNPROT_DISASSOCIATE",
-	NL80211_CMD_NEW_PEER_CANDIDATE: "NL80211_CMD_NEW_PEER_CANDIDATE",
-	NL80211_CMD_GET_WOWLAN: "NL80211_CMD_GET_WOWLAN",
-	NL80211_CMD_SET_WOWLAN: "NL80211_CMD_SET_WOWLAN",
-	NL80211_CMD_START_SCHED_SCAN: "NL80211_CMD_START_SCHED_SCAN",
-	NL80211_CMD_STOP_SCHED_SCAN: "NL80211_CMD_STOP_SCHED_SCAN",
-	NL80211_CMD_SCHED_SCAN_RESULTS: "NL80211_CMD_SCHED_SCAN_RESULTS",
-	NL80211_CMD_SCHED_SCAN_STOPPED: "NL80211_CMD_SCHED_SCAN_STOPPED",
-	NL80211_CMD_SET_REKEY_OFFLOAD: "NL80211_CMD_SET_REKEY_OFFLOAD",
-	NL80211_CMD_PMKSA_CANDIDATE: "NL80211_CMD_PMKSA_CANDIDATE",
-	NL80211_CMD_TDLS_OPER: "NL80211_CMD_TDLS_OPER",
-	NL80211_CMD_TDLS_MGMT: "NL80211_CMD_TDLS_MGMT",
-	NL80211_CMD_UNEXPECTED_FRAME: "NL80211_CMD_UNEXPECTED_FRAME",
-	NL80211_CMD_PROBE_CLIENT: "NL80211_CMD_PROBE_CLIENT",
-	NL80211_CMD_REGISTER_BEACONS: "NL80211_CMD_REGISTER_BEACONS",
-	NL80211_CMD_UNEXPECTED_4ADDR_FRAME: "NL80211_CMD_UNEXPECTED_4ADDR_FRAME",
-	NL80211_CMD_SET_NOACK_MAP: "NL80211_CMD_SET_NOACK_MAP",
-	NL80211_CMD_CH_SWITCH_NOTIFY: "NL80211_CMD_CH_SWITCH_NOTIFY",
-	NL80211_CMD_START_P2P_DEVICE: "NL80211_CMD_START_P2P_DEVICE",
-	NL80211_CMD_STOP_P2P_DEVICE: "NL80211_CMD_STOP_P2P_DEVICE",
-	NL80211_CMD_CONN_FAILED: "NL80211_CMD_CONN_FAILED",
-	NL80211_CMD_SET_MCAST_RATE: "NL80211_CMD_SET_MCAST_RATE",
-	NL80211_CMD_SET_MAC_ACL: "NL80211_CMD_SET_MAC_ACL",
-	NL80211_CMD_RADAR_DETECT: "NL80211_CMD_RADAR_DETECT",
-	NL80211_CMD_GET_PROTOCOL_FEATURES: "NL80211_CMD_GET_PROTOCOL_FEATURES",
-	NL80211_CMD_UPDATE_FT_IES: "NL80211_CMD_UPDATE_FT_IES",
-	NL80211_CMD_FT_EVENT: "NL80211_CMD_FT_EVENT",
-	NL80211_CMD_CRIT_PROTOCOL_START: "NL80211_CMD_CRIT_PROTOCOL_START",
-	NL80211_CMD_CRIT_PROTOCOL_STOP: "NL80211_CMD_CRIT_PROTOCOL_STOP",
-	__NL80211_CMD_AFTER_LAST: "__NL80211_CMD_AFTER_LAST",
+    NL80211_CMD_UNSPEC: "NL80211_CMD_UNSPEC",
+    NL80211_CMD_GET_WIPHY: "NL80211_CMD_GET_WIPHY",
+    NL80211_CMD_SET_WIPHY: "NL80211_CMD_SET_WIPHY",
+    NL80211_CMD_NEW_WIPHY: "NL80211_CMD_NEW_WIPHY",
+    NL80211_CMD_DEL_WIPHY: "NL80211_CMD_DEL_WIPHY",
+    NL80211_CMD_GET_INTERFACE: "NL80211_CMD_GET_INTERFACE",
+    NL80211_CMD_SET_INTERFACE: "NL80211_CMD_SET_INTERFACE",
+    NL80211_CMD_NEW_INTERFACE: "NL80211_CMD_NEW_INTERFACE",
+    NL80211_CMD_DEL_INTERFACE: "NL80211_CMD_DEL_INTERFACE",
+    NL80211_CMD_GET_KEY: "NL80211_CMD_GET_KEY",
+    NL80211_CMD_SET_KEY: "NL80211_CMD_SET_KEY",
+    NL80211_CMD_NEW_KEY: "NL80211_CMD_NEW_KEY",
+    NL80211_CMD_DEL_KEY: "NL80211_CMD_DEL_KEY",
+    NL80211_CMD_GET_BEACON: "NL80211_CMD_GET_BEACON",
+    NL80211_CMD_SET_BEACON: "NL80211_CMD_SET_BEACON",
+    NL80211_CMD_START_AP: "NL80211_CMD_START_AP",
+    NL80211_CMD_STOP_AP: "NL80211_CMD_STOP_AP",
+    NL80211_CMD_GET_STATION: "NL80211_CMD_GET_STATION",
+    NL80211_CMD_SET_STATION: "NL80211_CMD_SET_STATION",
+    NL80211_CMD_NEW_STATION: "NL80211_CMD_NEW_STATION",
+    NL80211_CMD_DEL_STATION: "NL80211_CMD_DEL_STATION",
+    NL80211_CMD_GET_MPATH: "NL80211_CMD_GET_MPATH",
+    NL80211_CMD_SET_MPATH: "NL80211_CMD_SET_MPATH",
+    NL80211_CMD_NEW_MPATH: "NL80211_CMD_NEW_MPATH",
+    NL80211_CMD_DEL_MPATH: "NL80211_CMD_DEL_MPATH",
+    NL80211_CMD_SET_BSS: "NL80211_CMD_SET_BSS",
+    NL80211_CMD_SET_REG: "NL80211_CMD_SET_REG",
+    NL80211_CMD_REQ_SET_REG: "NL80211_CMD_REQ_SET_REG",
+    NL80211_CMD_GET_MESH_CONFIG: "NL80211_CMD_GET_MESH_CONFIG",
+    NL80211_CMD_SET_MESH_CONFIG: "NL80211_CMD_SET_MESH_CONFIG",
+    NL80211_CMD_SET_MGMT_EXTRA_IE: "NL80211_CMD_SET_MGMT_EXTRA_IE",
+    NL80211_CMD_GET_REG: "NL80211_CMD_GET_REG",
+    NL80211_CMD_GET_SCAN: "NL80211_CMD_GET_SCAN",
+    NL80211_CMD_TRIGGER_SCAN: "NL80211_CMD_TRIGGER_SCAN",
+    NL80211_CMD_NEW_SCAN_RESULTS: "NL80211_CMD_NEW_SCAN_RESULTS",
+    NL80211_CMD_SCAN_ABORTED: "NL80211_CMD_SCAN_ABORTED",
+    NL80211_CMD_REG_CHANGE: "NL80211_CMD_REG_CHANGE",
+    NL80211_CMD_AUTHENTICATE: "NL80211_CMD_AUTHENTICATE",
+    NL80211_CMD_ASSOCIATE: "NL80211_CMD_ASSOCIATE",
+    NL80211_CMD_DEAUTHENTICATE: "NL80211_CMD_DEAUTHENTICATE",
+    NL80211_CMD_DISASSOCIATE: "NL80211_CMD_DISASSOCIATE",
+    NL80211_CMD_MICHAEL_MIC_FAILURE: "NL80211_CMD_MICHAEL_MIC_FAILURE",
+    NL80211_CMD_REG_BEACON_HINT: "NL80211_CMD_REG_BEACON_HINT",
+    NL80211_CMD_JOIN_IBSS: "NL80211_CMD_JOIN_IBSS",
+    NL80211_CMD_LEAVE_IBSS: "NL80211_CMD_LEAVE_IBSS",
+    NL80211_CMD_TESTMODE: "NL80211_CMD_TESTMODE",
+    NL80211_CMD_CONNECT: "NL80211_CMD_CONNECT",
+    NL80211_CMD_ROAM: "NL80211_CMD_ROAM",
+    NL80211_CMD_DISCONNECT: "NL80211_CMD_DISCONNECT",
+    NL80211_CMD_SET_WIPHY_NETNS: "NL80211_CMD_SET_WIPHY_NETNS",
+    NL80211_CMD_GET_SURVEY: "NL80211_CMD_GET_SURVEY",
+    NL80211_CMD_NEW_SURVEY_RESULTS: "NL80211_CMD_NEW_SURVEY_RESULTS",
+    NL80211_CMD_SET_PMKSA: "NL80211_CMD_SET_PMKSA",
+    NL80211_CMD_DEL_PMKSA: "NL80211_CMD_DEL_PMKSA",
+    NL80211_CMD_FLUSH_PMKSA: "NL80211_CMD_FLUSH_PMKSA",
+    NL80211_CMD_REMAIN_ON_CHANNEL: "NL80211_CMD_REMAIN_ON_CHANNEL",
+    NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: "NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL",
+    NL80211_CMD_SET_TX_BITRATE_MASK: "NL80211_CMD_SET_TX_BITRATE_MASK",
+    NL80211_CMD_REGISTER_FRAME: "NL80211_CMD_REGISTER_FRAME",
+    NL80211_CMD_FRAME: "NL80211_CMD_FRAME",
+    NL80211_CMD_FRAME_TX_STATUS: "NL80211_CMD_FRAME_TX_STATUS",
+    NL80211_CMD_SET_POWER_SAVE: "NL80211_CMD_SET_POWER_SAVE",
+    NL80211_CMD_GET_POWER_SAVE: "NL80211_CMD_GET_POWER_SAVE",
+    NL80211_CMD_SET_CQM: "NL80211_CMD_SET_CQM",
+    NL80211_CMD_NOTIFY_CQM: "NL80211_CMD_NOTIFY_CQM",
+    NL80211_CMD_SET_CHANNEL: "NL80211_CMD_SET_CHANNEL",
+    NL80211_CMD_SET_WDS_PEER: "NL80211_CMD_SET_WDS_PEER",
+    NL80211_CMD_FRAME_WAIT_CANCEL: "NL80211_CMD_FRAME_WAIT_CANCEL",
+    NL80211_CMD_JOIN_MESH: "NL80211_CMD_JOIN_MESH",
+    NL80211_CMD_LEAVE_MESH: "NL80211_CMD_LEAVE_MESH",
+    NL80211_CMD_UNPROT_DEAUTHENTICATE: "NL80211_CMD_UNPROT_DEAUTHENTICATE",
+    NL80211_CMD_UNPROT_DISASSOCIATE: "NL80211_CMD_UNPROT_DISASSOCIATE",
+    NL80211_CMD_NEW_PEER_CANDIDATE: "NL80211_CMD_NEW_PEER_CANDIDATE",
+    NL80211_CMD_GET_WOWLAN: "NL80211_CMD_GET_WOWLAN",
+    NL80211_CMD_SET_WOWLAN: "NL80211_CMD_SET_WOWLAN",
+    NL80211_CMD_START_SCHED_SCAN: "NL80211_CMD_START_SCHED_SCAN",
+    NL80211_CMD_STOP_SCHED_SCAN: "NL80211_CMD_STOP_SCHED_SCAN",
+    NL80211_CMD_SCHED_SCAN_RESULTS: "NL80211_CMD_SCHED_SCAN_RESULTS",
+    NL80211_CMD_SCHED_SCAN_STOPPED: "NL80211_CMD_SCHED_SCAN_STOPPED",
+    NL80211_CMD_SET_REKEY_OFFLOAD: "NL80211_CMD_SET_REKEY_OFFLOAD",
+    NL80211_CMD_PMKSA_CANDIDATE: "NL80211_CMD_PMKSA_CANDIDATE",
+    NL80211_CMD_TDLS_OPER: "NL80211_CMD_TDLS_OPER",
+    NL80211_CMD_TDLS_MGMT: "NL80211_CMD_TDLS_MGMT",
+    NL80211_CMD_UNEXPECTED_FRAME: "NL80211_CMD_UNEXPECTED_FRAME",
+    NL80211_CMD_PROBE_CLIENT: "NL80211_CMD_PROBE_CLIENT",
+    NL80211_CMD_REGISTER_BEACONS: "NL80211_CMD_REGISTER_BEACONS",
+    NL80211_CMD_UNEXPECTED_4ADDR_FRAME: "NL80211_CMD_UNEXPECTED_4ADDR_FRAME",
+    NL80211_CMD_SET_NOACK_MAP: "NL80211_CMD_SET_NOACK_MAP",
+    NL80211_CMD_CH_SWITCH_NOTIFY: "NL80211_CMD_CH_SWITCH_NOTIFY",
+    NL80211_CMD_START_P2P_DEVICE: "NL80211_CMD_START_P2P_DEVICE",
+    NL80211_CMD_STOP_P2P_DEVICE: "NL80211_CMD_STOP_P2P_DEVICE",
+    NL80211_CMD_CONN_FAILED: "NL80211_CMD_CONN_FAILED",
+    NL80211_CMD_SET_MCAST_RATE: "NL80211_CMD_SET_MCAST_RATE",
+    NL80211_CMD_SET_MAC_ACL: "NL80211_CMD_SET_MAC_ACL",
+    NL80211_CMD_RADAR_DETECT: "NL80211_CMD_RADAR_DETECT",
+    NL80211_CMD_GET_PROTOCOL_FEATURES: "NL80211_CMD_GET_PROTOCOL_FEATURES",
+    NL80211_CMD_UPDATE_FT_IES: "NL80211_CMD_UPDATE_FT_IES",
+    NL80211_CMD_FT_EVENT: "NL80211_CMD_FT_EVENT",
+    NL80211_CMD_CRIT_PROTOCOL_START: "NL80211_CMD_CRIT_PROTOCOL_START",
+    NL80211_CMD_CRIT_PROTOCOL_STOP: "NL80211_CMD_CRIT_PROTOCOL_STOP",
+    __NL80211_CMD_AFTER_LAST: "__NL80211_CMD_AFTER_LAST",
 }
 nl80211_attrs2str = {
-	NL80211_ATTR_UNSPEC: "NL80211_ATTR_UNSPEC",
-	NL80211_ATTR_WIPHY: "NL80211_ATTR_WIPHY",
-	NL80211_ATTR_WIPHY_NAME: "NL80211_ATTR_WIPHY_NAME",
-	NL80211_ATTR_IFINDEX: "NL80211_ATTR_IFINDEX",
-	NL80211_ATTR_IFNAME: "NL80211_ATTR_IFNAME",
-	NL80211_ATTR_IFTYPE: "NL80211_ATTR_IFTYPE",
-	NL80211_ATTR_MAC: "NL80211_ATTR_MAC",
-	NL80211_ATTR_KEY_DATA: "NL80211_ATTR_KEY_DATA",
-	NL80211_ATTR_KEY_IDX: "NL80211_ATTR_KEY_IDX",
-	NL80211_ATTR_KEY_CIPHER: "NL80211_ATTR_KEY_CIPHER",
-	NL80211_ATTR_KEY_SEQ: "NL80211_ATTR_KEY_SEQ",
-	NL80211_ATTR_KEY_DEFAULT: "NL80211_ATTR_KEY_DEFAULT",
-	NL80211_ATTR_BEACON_INTERVAL: "NL80211_ATTR_BEACON_INTERVAL",
-	NL80211_ATTR_DTIM_PERIOD: "NL80211_ATTR_DTIM_PERIOD",
-	NL80211_ATTR_BEACON_HEAD: "NL80211_ATTR_BEACON_HEAD",
-	NL80211_ATTR_BEACON_TAIL: "NL80211_ATTR_BEACON_TAIL",
-	NL80211_ATTR_STA_AID: "NL80211_ATTR_STA_AID",
-	NL80211_ATTR_STA_FLAGS: "NL80211_ATTR_STA_FLAGS",
-	NL80211_ATTR_STA_LISTEN_INTERVAL: "NL80211_ATTR_STA_LISTEN_INTERVAL",
-	NL80211_ATTR_STA_SUPPORTED_RATES: "NL80211_ATTR_STA_SUPPORTED_RATES",
-	NL80211_ATTR_STA_VLAN: "NL80211_ATTR_STA_VLAN",
-	NL80211_ATTR_STA_INFO: "NL80211_ATTR_STA_INFO",
-	NL80211_ATTR_WIPHY_BANDS: "NL80211_ATTR_WIPHY_BANDS",
-	NL80211_ATTR_MNTR_FLAGS: "NL80211_ATTR_MNTR_FLAGS",
-	NL80211_ATTR_MESH_ID: "NL80211_ATTR_MESH_ID",
-	NL80211_ATTR_STA_PLINK_ACTION: "NL80211_ATTR_STA_PLINK_ACTION",
-	NL80211_ATTR_MPATH_NEXT_HOP: "NL80211_ATTR_MPATH_NEXT_HOP",
-	NL80211_ATTR_MPATH_INFO: "NL80211_ATTR_MPATH_INFO",
-	NL80211_ATTR_BSS_CTS_PROT: "NL80211_ATTR_BSS_CTS_PROT",
-	NL80211_ATTR_BSS_SHORT_PREAMBLE: "NL80211_ATTR_BSS_SHORT_PREAMBLE",
-	NL80211_ATTR_BSS_SHORT_SLOT_TIME: "NL80211_ATTR_BSS_SHORT_SLOT_TIME",
-	NL80211_ATTR_HT_CAPABILITY: "NL80211_ATTR_HT_CAPABILITY",
-	NL80211_ATTR_SUPPORTED_IFTYPES: "NL80211_ATTR_SUPPORTED_IFTYPES",
-	NL80211_ATTR_REG_ALPHA2: "NL80211_ATTR_REG_ALPHA2",
-	NL80211_ATTR_REG_RULES: "NL80211_ATTR_REG_RULES",
-	NL80211_ATTR_MESH_CONFIG: "NL80211_ATTR_MESH_CONFIG",
-	NL80211_ATTR_BSS_BASIC_RATES: "NL80211_ATTR_BSS_BASIC_RATES",
-	NL80211_ATTR_WIPHY_TXQ_PARAMS: "NL80211_ATTR_WIPHY_TXQ_PARAMS",
-	NL80211_ATTR_WIPHY_FREQ: "NL80211_ATTR_WIPHY_FREQ",
-	NL80211_ATTR_WIPHY_CHANNEL_TYPE: "NL80211_ATTR_WIPHY_CHANNEL_TYPE",
-	NL80211_ATTR_KEY_DEFAULT_MGMT: "NL80211_ATTR_KEY_DEFAULT_MGMT",
-	NL80211_ATTR_MGMT_SUBTYPE: "NL80211_ATTR_MGMT_SUBTYPE",
-	NL80211_ATTR_IE: "NL80211_ATTR_IE",
-	NL80211_ATTR_MAX_NUM_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCAN_SSIDS",
-	NL80211_ATTR_SCAN_FREQUENCIES: "NL80211_ATTR_SCAN_FREQUENCIES",
-	NL80211_ATTR_SCAN_SSIDS: "NL80211_ATTR_SCAN_SSIDS",
-	NL80211_ATTR_GENERATION: "NL80211_ATTR_GENERATION",
-	NL80211_ATTR_BSS: "NL80211_ATTR_BSS",
-	NL80211_ATTR_REG_INITIATOR: "NL80211_ATTR_REG_INITIATOR",
-	NL80211_ATTR_REG_TYPE: "NL80211_ATTR_REG_TYPE",
-	NL80211_ATTR_SUPPORTED_COMMANDS: "NL80211_ATTR_SUPPORTED_COMMANDS",
-	NL80211_ATTR_FRAME: "NL80211_ATTR_FRAME",
-	NL80211_ATTR_SSID: "NL80211_ATTR_SSID",
-	NL80211_ATTR_AUTH_TYPE: "NL80211_ATTR_AUTH_TYPE",
-	NL80211_ATTR_REASON_CODE: "NL80211_ATTR_REASON_CODE",
-	NL80211_ATTR_KEY_TYPE: "NL80211_ATTR_KEY_TYPE",
-	NL80211_ATTR_MAX_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCAN_IE_LEN",
-	NL80211_ATTR_CIPHER_SUITES: "NL80211_ATTR_CIPHER_SUITES",
-	NL80211_ATTR_FREQ_BEFORE: "NL80211_ATTR_FREQ_BEFORE",
-	NL80211_ATTR_FREQ_AFTER: "NL80211_ATTR_FREQ_AFTER",
-	NL80211_ATTR_FREQ_FIXED: "NL80211_ATTR_FREQ_FIXED",
-	NL80211_ATTR_WIPHY_RETRY_SHORT: "NL80211_ATTR_WIPHY_RETRY_SHORT",
-	NL80211_ATTR_WIPHY_RETRY_LONG: "NL80211_ATTR_WIPHY_RETRY_LONG",
-	NL80211_ATTR_WIPHY_FRAG_THRESHOLD: "NL80211_ATTR_WIPHY_FRAG_THRESHOLD",
-	NL80211_ATTR_WIPHY_RTS_THRESHOLD: "NL80211_ATTR_WIPHY_RTS_THRESHOLD",
-	NL80211_ATTR_TIMED_OUT: "NL80211_ATTR_TIMED_OUT",
-	NL80211_ATTR_USE_MFP: "NL80211_ATTR_USE_MFP",
-	NL80211_ATTR_STA_FLAGS2: "NL80211_ATTR_STA_FLAGS2",
-	NL80211_ATTR_CONTROL_PORT: "NL80211_ATTR_CONTROL_PORT",
-	NL80211_ATTR_TESTDATA: "NL80211_ATTR_TESTDATA",
-	NL80211_ATTR_PRIVACY: "NL80211_ATTR_PRIVACY",
-	NL80211_ATTR_DISCONNECTED_BY_AP: "NL80211_ATTR_DISCONNECTED_BY_AP",
-	NL80211_ATTR_STATUS_CODE: "NL80211_ATTR_STATUS_CODE",
-	NL80211_ATTR_CIPHER_SUITES_PAIRWISE: "NL80211_ATTR_CIPHER_SUITES_PAIRWISE",
-	NL80211_ATTR_CIPHER_SUITE_GROUP: "NL80211_ATTR_CIPHER_SUITE_GROUP",
-	NL80211_ATTR_WPA_VERSIONS: "NL80211_ATTR_WPA_VERSIONS",
-	NL80211_ATTR_AKM_SUITES: "NL80211_ATTR_AKM_SUITES",
-	NL80211_ATTR_REQ_IE: "NL80211_ATTR_REQ_IE",
-	NL80211_ATTR_RESP_IE: "NL80211_ATTR_RESP_IE",
-	NL80211_ATTR_PREV_BSSID: "NL80211_ATTR_PREV_BSSID",
-	NL80211_ATTR_KEY: "NL80211_ATTR_KEY",
-	NL80211_ATTR_KEYS: "NL80211_ATTR_KEYS",
-	NL80211_ATTR_PID: "NL80211_ATTR_PID",
-	NL80211_ATTR_4ADDR: "NL80211_ATTR_4ADDR",
-	NL80211_ATTR_SURVEY_INFO: "NL80211_ATTR_SURVEY_INFO",
-	NL80211_ATTR_PMKID: "NL80211_ATTR_PMKID",
-	NL80211_ATTR_MAX_NUM_PMKIDS: "NL80211_ATTR_MAX_NUM_PMKIDS",
-	NL80211_ATTR_DURATION: "NL80211_ATTR_DURATION",
-	NL80211_ATTR_COOKIE: "NL80211_ATTR_COOKIE",
-	NL80211_ATTR_WIPHY_COVERAGE_CLASS: "NL80211_ATTR_WIPHY_COVERAGE_CLASS",
-	NL80211_ATTR_TX_RATES: "NL80211_ATTR_TX_RATES",
-	NL80211_ATTR_FRAME_MATCH: "NL80211_ATTR_FRAME_MATCH",
-	NL80211_ATTR_ACK: "NL80211_ATTR_ACK",
-	NL80211_ATTR_PS_STATE: "NL80211_ATTR_PS_STATE",
-	NL80211_ATTR_CQM: "NL80211_ATTR_CQM",
-	NL80211_ATTR_LOCAL_STATE_CHANGE: "NL80211_ATTR_LOCAL_STATE_CHANGE",
-	NL80211_ATTR_AP_ISOLATE: "NL80211_ATTR_AP_ISOLATE",
-	NL80211_ATTR_WIPHY_TX_POWER_SETTING: "NL80211_ATTR_WIPHY_TX_POWER_SETTING",
-	NL80211_ATTR_WIPHY_TX_POWER_LEVEL: "NL80211_ATTR_WIPHY_TX_POWER_LEVEL",
-	NL80211_ATTR_TX_FRAME_TYPES: "NL80211_ATTR_TX_FRAME_TYPES",
-	NL80211_ATTR_RX_FRAME_TYPES: "NL80211_ATTR_RX_FRAME_TYPES",
-	NL80211_ATTR_FRAME_TYPE: "NL80211_ATTR_FRAME_TYPE",
-	NL80211_ATTR_CONTROL_PORT_ETHERTYPE: "NL80211_ATTR_CONTROL_PORT_ETHERTYPE",
-	NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: "NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT",
-	NL80211_ATTR_SUPPORT_IBSS_RSN: "NL80211_ATTR_SUPPORT_IBSS_RSN",
-	NL80211_ATTR_WIPHY_ANTENNA_TX: "NL80211_ATTR_WIPHY_ANTENNA_TX",
-	NL80211_ATTR_WIPHY_ANTENNA_RX: "NL80211_ATTR_WIPHY_ANTENNA_RX",
-	NL80211_ATTR_MCAST_RATE: "NL80211_ATTR_MCAST_RATE",
-	NL80211_ATTR_OFFCHANNEL_TX_OK: "NL80211_ATTR_OFFCHANNEL_TX_OK",
-	NL80211_ATTR_BSS_HT_OPMODE: "NL80211_ATTR_BSS_HT_OPMODE",
-	NL80211_ATTR_KEY_DEFAULT_TYPES: "NL80211_ATTR_KEY_DEFAULT_TYPES",
-	NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: "NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION",
-	NL80211_ATTR_MESH_SETUP: "NL80211_ATTR_MESH_SETUP",
-	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX",
-	NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX",
-	NL80211_ATTR_SUPPORT_MESH_AUTH: "NL80211_ATTR_SUPPORT_MESH_AUTH",
-	NL80211_ATTR_STA_PLINK_STATE: "NL80211_ATTR_STA_PLINK_STATE",
-	NL80211_ATTR_WOWLAN_TRIGGERS: "NL80211_ATTR_WOWLAN_TRIGGERS",
-	NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: "NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED",
-	NL80211_ATTR_SCHED_SCAN_INTERVAL: "NL80211_ATTR_SCHED_SCAN_INTERVAL",
-	NL80211_ATTR_INTERFACE_COMBINATIONS: "NL80211_ATTR_INTERFACE_COMBINATIONS",
-	NL80211_ATTR_SOFTWARE_IFTYPES: "NL80211_ATTR_SOFTWARE_IFTYPES",
-	NL80211_ATTR_REKEY_DATA: "NL80211_ATTR_REKEY_DATA",
-	NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS",
-	NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN",
-	NL80211_ATTR_SCAN_SUPP_RATES: "NL80211_ATTR_SCAN_SUPP_RATES",
-	NL80211_ATTR_HIDDEN_SSID: "NL80211_ATTR_HIDDEN_SSID",
-	NL80211_ATTR_IE_PROBE_RESP: "NL80211_ATTR_IE_PROBE_RESP",
-	NL80211_ATTR_IE_ASSOC_RESP: "NL80211_ATTR_IE_ASSOC_RESP",
-	NL80211_ATTR_STA_WME: "NL80211_ATTR_STA_WME",
-	NL80211_ATTR_SUPPORT_AP_UAPSD: "NL80211_ATTR_SUPPORT_AP_UAPSD",
-	NL80211_ATTR_ROAM_SUPPORT: "NL80211_ATTR_ROAM_SUPPORT",
-	NL80211_ATTR_SCHED_SCAN_MATCH: "NL80211_ATTR_SCHED_SCAN_MATCH",
-	NL80211_ATTR_MAX_MATCH_SETS: "NL80211_ATTR_MAX_MATCH_SETS",
-	NL80211_ATTR_PMKSA_CANDIDATE: "NL80211_ATTR_PMKSA_CANDIDATE",
-	NL80211_ATTR_TX_NO_CCK_RATE: "NL80211_ATTR_TX_NO_CCK_RATE",
-	NL80211_ATTR_TDLS_ACTION: "NL80211_ATTR_TDLS_ACTION",
-	NL80211_ATTR_TDLS_DIALOG_TOKEN: "NL80211_ATTR_TDLS_DIALOG_TOKEN",
-	NL80211_ATTR_TDLS_OPERATION: "NL80211_ATTR_TDLS_OPERATION",
-	NL80211_ATTR_TDLS_SUPPORT: "NL80211_ATTR_TDLS_SUPPORT",
-	NL80211_ATTR_TDLS_EXTERNAL_SETUP: "NL80211_ATTR_TDLS_EXTERNAL_SETUP",
-	NL80211_ATTR_DEVICE_AP_SME: "NL80211_ATTR_DEVICE_AP_SME",
-	NL80211_ATTR_DONT_WAIT_FOR_ACK: "NL80211_ATTR_DONT_WAIT_FOR_ACK",
-	NL80211_ATTR_FEATURE_FLAGS: "NL80211_ATTR_FEATURE_FLAGS",
-	NL80211_ATTR_PROBE_RESP_OFFLOAD: "NL80211_ATTR_PROBE_RESP_OFFLOAD",
-	NL80211_ATTR_PROBE_RESP: "NL80211_ATTR_PROBE_RESP",
-	NL80211_ATTR_DFS_REGION: "NL80211_ATTR_DFS_REGION",
-	NL80211_ATTR_DISABLE_HT: "NL80211_ATTR_DISABLE_HT",
-	NL80211_ATTR_HT_CAPABILITY_MASK: "NL80211_ATTR_HT_CAPABILITY_MASK",
-	NL80211_ATTR_NOACK_MAP: "NL80211_ATTR_NOACK_MAP",
-	NL80211_ATTR_INACTIVITY_TIMEOUT: "NL80211_ATTR_INACTIVITY_TIMEOUT",
-	NL80211_ATTR_RX_SIGNAL_DBM: "NL80211_ATTR_RX_SIGNAL_DBM",
-	NL80211_ATTR_BG_SCAN_PERIOD: "NL80211_ATTR_BG_SCAN_PERIOD",
-	NL80211_ATTR_WDEV: "NL80211_ATTR_WDEV",
-	NL80211_ATTR_USER_REG_HINT_TYPE: "NL80211_ATTR_USER_REG_HINT_TYPE",
-	NL80211_ATTR_CONN_FAILED_REASON: "NL80211_ATTR_CONN_FAILED_REASON",
-	NL80211_ATTR_SAE_DATA: "NL80211_ATTR_SAE_DATA",
-	NL80211_ATTR_VHT_CAPABILITY: "NL80211_ATTR_VHT_CAPABILITY",
-	NL80211_ATTR_SCAN_FLAGS: "NL80211_ATTR_SCAN_FLAGS",
-	NL80211_ATTR_CHANNEL_WIDTH: "NL80211_ATTR_CHANNEL_WIDTH",
-	NL80211_ATTR_CENTER_FREQ1: "NL80211_ATTR_CENTER_FREQ1",
-	NL80211_ATTR_CENTER_FREQ2: "NL80211_ATTR_CENTER_FREQ2",
-	NL80211_ATTR_P2P_CTWINDOW: "NL80211_ATTR_P2P_CTWINDOW",
-	NL80211_ATTR_P2P_OPPPS: "NL80211_ATTR_P2P_OPPPS",
-	NL80211_ATTR_LOCAL_MESH_POWER_MODE: "NL80211_ATTR_LOCAL_MESH_POWER_MODE",
-	NL80211_ATTR_ACL_POLICY: "NL80211_ATTR_ACL_POLICY",
-	NL80211_ATTR_MAC_ADDRS: "NL80211_ATTR_MAC_ADDRS",
-	NL80211_ATTR_MAC_ACL_MAX: "NL80211_ATTR_MAC_ACL_MAX",
-	NL80211_ATTR_RADAR_EVENT: "NL80211_ATTR_RADAR_EVENT",
-	NL80211_ATTR_EXT_CAPA: "NL80211_ATTR_EXT_CAPA",
-	NL80211_ATTR_EXT_CAPA_MASK: "NL80211_ATTR_EXT_CAPA_MASK",
-	NL80211_ATTR_STA_CAPABILITY: "NL80211_ATTR_STA_CAPABILITY",
-	NL80211_ATTR_STA_EXT_CAPABILITY: "NL80211_ATTR_STA_EXT_CAPABILITY",
-	NL80211_ATTR_PROTOCOL_FEATURES: "NL80211_ATTR_PROTOCOL_FEATURES",
-	NL80211_ATTR_SPLIT_WIPHY_DUMP: "NL80211_ATTR_SPLIT_WIPHY_DUMP",
-	NL80211_ATTR_DISABLE_VHT: "NL80211_ATTR_DISABLE_VHT",
-	NL80211_ATTR_VHT_CAPABILITY_MASK: "NL80211_ATTR_VHT_CAPABILITY_MASK",
-	NL80211_ATTR_MDID: "NL80211_ATTR_MDID",
-	NL80211_ATTR_IE_RIC: "NL80211_ATTR_IE_RIC",
-	NL80211_ATTR_CRIT_PROT_ID: "NL80211_ATTR_CRIT_PROT_ID",
-	NL80211_ATTR_MAX_CRIT_PROT_DURATION: "NL80211_ATTR_MAX_CRIT_PROT_DURATION",
-	NL80211_ATTR_PEER_AID: "NL80211_ATTR_PEER_AID",
-	__NL80211_ATTR_AFTER_LAST: "__NL80211_ATTR_AFTER_LAST",
+    NL80211_ATTR_UNSPEC: "NL80211_ATTR_UNSPEC",
+    NL80211_ATTR_WIPHY: "NL80211_ATTR_WIPHY",
+    NL80211_ATTR_WIPHY_NAME: "NL80211_ATTR_WIPHY_NAME",
+    NL80211_ATTR_IFINDEX: "NL80211_ATTR_IFINDEX",
+    NL80211_ATTR_IFNAME: "NL80211_ATTR_IFNAME",
+    NL80211_ATTR_IFTYPE: "NL80211_ATTR_IFTYPE",
+    NL80211_ATTR_MAC: "NL80211_ATTR_MAC",
+    NL80211_ATTR_KEY_DATA: "NL80211_ATTR_KEY_DATA",
+    NL80211_ATTR_KEY_IDX: "NL80211_ATTR_KEY_IDX",
+    NL80211_ATTR_KEY_CIPHER: "NL80211_ATTR_KEY_CIPHER",
+    NL80211_ATTR_KEY_SEQ: "NL80211_ATTR_KEY_SEQ",
+    NL80211_ATTR_KEY_DEFAULT: "NL80211_ATTR_KEY_DEFAULT",
+    NL80211_ATTR_BEACON_INTERVAL: "NL80211_ATTR_BEACON_INTERVAL",
+    NL80211_ATTR_DTIM_PERIOD: "NL80211_ATTR_DTIM_PERIOD",
+    NL80211_ATTR_BEACON_HEAD: "NL80211_ATTR_BEACON_HEAD",
+    NL80211_ATTR_BEACON_TAIL: "NL80211_ATTR_BEACON_TAIL",
+    NL80211_ATTR_STA_AID: "NL80211_ATTR_STA_AID",
+    NL80211_ATTR_STA_FLAGS: "NL80211_ATTR_STA_FLAGS",
+    NL80211_ATTR_STA_LISTEN_INTERVAL: "NL80211_ATTR_STA_LISTEN_INTERVAL",
+    NL80211_ATTR_STA_SUPPORTED_RATES: "NL80211_ATTR_STA_SUPPORTED_RATES",
+    NL80211_ATTR_STA_VLAN: "NL80211_ATTR_STA_VLAN",
+    NL80211_ATTR_STA_INFO: "NL80211_ATTR_STA_INFO",
+    NL80211_ATTR_WIPHY_BANDS: "NL80211_ATTR_WIPHY_BANDS",
+    NL80211_ATTR_MNTR_FLAGS: "NL80211_ATTR_MNTR_FLAGS",
+    NL80211_ATTR_MESH_ID: "NL80211_ATTR_MESH_ID",
+    NL80211_ATTR_STA_PLINK_ACTION: "NL80211_ATTR_STA_PLINK_ACTION",
+    NL80211_ATTR_MPATH_NEXT_HOP: "NL80211_ATTR_MPATH_NEXT_HOP",
+    NL80211_ATTR_MPATH_INFO: "NL80211_ATTR_MPATH_INFO",
+    NL80211_ATTR_BSS_CTS_PROT: "NL80211_ATTR_BSS_CTS_PROT",
+    NL80211_ATTR_BSS_SHORT_PREAMBLE: "NL80211_ATTR_BSS_SHORT_PREAMBLE",
+    NL80211_ATTR_BSS_SHORT_SLOT_TIME: "NL80211_ATTR_BSS_SHORT_SLOT_TIME",
+    NL80211_ATTR_HT_CAPABILITY: "NL80211_ATTR_HT_CAPABILITY",
+    NL80211_ATTR_SUPPORTED_IFTYPES: "NL80211_ATTR_SUPPORTED_IFTYPES",
+    NL80211_ATTR_REG_ALPHA2: "NL80211_ATTR_REG_ALPHA2",
+    NL80211_ATTR_REG_RULES: "NL80211_ATTR_REG_RULES",
+    NL80211_ATTR_MESH_CONFIG: "NL80211_ATTR_MESH_CONFIG",
+    NL80211_ATTR_BSS_BASIC_RATES: "NL80211_ATTR_BSS_BASIC_RATES",
+    NL80211_ATTR_WIPHY_TXQ_PARAMS: "NL80211_ATTR_WIPHY_TXQ_PARAMS",
+    NL80211_ATTR_WIPHY_FREQ: "NL80211_ATTR_WIPHY_FREQ",
+    NL80211_ATTR_WIPHY_CHANNEL_TYPE: "NL80211_ATTR_WIPHY_CHANNEL_TYPE",
+    NL80211_ATTR_KEY_DEFAULT_MGMT: "NL80211_ATTR_KEY_DEFAULT_MGMT",
+    NL80211_ATTR_MGMT_SUBTYPE: "NL80211_ATTR_MGMT_SUBTYPE",
+    NL80211_ATTR_IE: "NL80211_ATTR_IE",
+    NL80211_ATTR_MAX_NUM_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCAN_SSIDS",
+    NL80211_ATTR_SCAN_FREQUENCIES: "NL80211_ATTR_SCAN_FREQUENCIES",
+    NL80211_ATTR_SCAN_SSIDS: "NL80211_ATTR_SCAN_SSIDS",
+    NL80211_ATTR_GENERATION: "NL80211_ATTR_GENERATION",
+    NL80211_ATTR_BSS: "NL80211_ATTR_BSS",
+    NL80211_ATTR_REG_INITIATOR: "NL80211_ATTR_REG_INITIATOR",
+    NL80211_ATTR_REG_TYPE: "NL80211_ATTR_REG_TYPE",
+    NL80211_ATTR_SUPPORTED_COMMANDS: "NL80211_ATTR_SUPPORTED_COMMANDS",
+    NL80211_ATTR_FRAME: "NL80211_ATTR_FRAME",
+    NL80211_ATTR_SSID: "NL80211_ATTR_SSID",
+    NL80211_ATTR_AUTH_TYPE: "NL80211_ATTR_AUTH_TYPE",
+    NL80211_ATTR_REASON_CODE: "NL80211_ATTR_REASON_CODE",
+    NL80211_ATTR_KEY_TYPE: "NL80211_ATTR_KEY_TYPE",
+    NL80211_ATTR_MAX_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCAN_IE_LEN",
+    NL80211_ATTR_CIPHER_SUITES: "NL80211_ATTR_CIPHER_SUITES",
+    NL80211_ATTR_FREQ_BEFORE: "NL80211_ATTR_FREQ_BEFORE",
+    NL80211_ATTR_FREQ_AFTER: "NL80211_ATTR_FREQ_AFTER",
+    NL80211_ATTR_FREQ_FIXED: "NL80211_ATTR_FREQ_FIXED",
+    NL80211_ATTR_WIPHY_RETRY_SHORT: "NL80211_ATTR_WIPHY_RETRY_SHORT",
+    NL80211_ATTR_WIPHY_RETRY_LONG: "NL80211_ATTR_WIPHY_RETRY_LONG",
+    NL80211_ATTR_WIPHY_FRAG_THRESHOLD: "NL80211_ATTR_WIPHY_FRAG_THRESHOLD",
+    NL80211_ATTR_WIPHY_RTS_THRESHOLD: "NL80211_ATTR_WIPHY_RTS_THRESHOLD",
+    NL80211_ATTR_TIMED_OUT: "NL80211_ATTR_TIMED_OUT",
+    NL80211_ATTR_USE_MFP: "NL80211_ATTR_USE_MFP",
+    NL80211_ATTR_STA_FLAGS2: "NL80211_ATTR_STA_FLAGS2",
+    NL80211_ATTR_CONTROL_PORT: "NL80211_ATTR_CONTROL_PORT",
+    NL80211_ATTR_TESTDATA: "NL80211_ATTR_TESTDATA",
+    NL80211_ATTR_PRIVACY: "NL80211_ATTR_PRIVACY",
+    NL80211_ATTR_DISCONNECTED_BY_AP: "NL80211_ATTR_DISCONNECTED_BY_AP",
+    NL80211_ATTR_STATUS_CODE: "NL80211_ATTR_STATUS_CODE",
+    NL80211_ATTR_CIPHER_SUITES_PAIRWISE: "NL80211_ATTR_CIPHER_SUITES_PAIRWISE",
+    NL80211_ATTR_CIPHER_SUITE_GROUP: "NL80211_ATTR_CIPHER_SUITE_GROUP",
+    NL80211_ATTR_WPA_VERSIONS: "NL80211_ATTR_WPA_VERSIONS",
+    NL80211_ATTR_AKM_SUITES: "NL80211_ATTR_AKM_SUITES",
+    NL80211_ATTR_REQ_IE: "NL80211_ATTR_REQ_IE",
+    NL80211_ATTR_RESP_IE: "NL80211_ATTR_RESP_IE",
+    NL80211_ATTR_PREV_BSSID: "NL80211_ATTR_PREV_BSSID",
+    NL80211_ATTR_KEY: "NL80211_ATTR_KEY",
+    NL80211_ATTR_KEYS: "NL80211_ATTR_KEYS",
+    NL80211_ATTR_PID: "NL80211_ATTR_PID",
+    NL80211_ATTR_4ADDR: "NL80211_ATTR_4ADDR",
+    NL80211_ATTR_SURVEY_INFO: "NL80211_ATTR_SURVEY_INFO",
+    NL80211_ATTR_PMKID: "NL80211_ATTR_PMKID",
+    NL80211_ATTR_MAX_NUM_PMKIDS: "NL80211_ATTR_MAX_NUM_PMKIDS",
+    NL80211_ATTR_DURATION: "NL80211_ATTR_DURATION",
+    NL80211_ATTR_COOKIE: "NL80211_ATTR_COOKIE",
+    NL80211_ATTR_WIPHY_COVERAGE_CLASS: "NL80211_ATTR_WIPHY_COVERAGE_CLASS",
+    NL80211_ATTR_TX_RATES: "NL80211_ATTR_TX_RATES",
+    NL80211_ATTR_FRAME_MATCH: "NL80211_ATTR_FRAME_MATCH",
+    NL80211_ATTR_ACK: "NL80211_ATTR_ACK",
+    NL80211_ATTR_PS_STATE: "NL80211_ATTR_PS_STATE",
+    NL80211_ATTR_CQM: "NL80211_ATTR_CQM",
+    NL80211_ATTR_LOCAL_STATE_CHANGE: "NL80211_ATTR_LOCAL_STATE_CHANGE",
+    NL80211_ATTR_AP_ISOLATE: "NL80211_ATTR_AP_ISOLATE",
+    NL80211_ATTR_WIPHY_TX_POWER_SETTING: "NL80211_ATTR_WIPHY_TX_POWER_SETTING",
+    NL80211_ATTR_WIPHY_TX_POWER_LEVEL: "NL80211_ATTR_WIPHY_TX_POWER_LEVEL",
+    NL80211_ATTR_TX_FRAME_TYPES: "NL80211_ATTR_TX_FRAME_TYPES",
+    NL80211_ATTR_RX_FRAME_TYPES: "NL80211_ATTR_RX_FRAME_TYPES",
+    NL80211_ATTR_FRAME_TYPE: "NL80211_ATTR_FRAME_TYPE",
+    NL80211_ATTR_CONTROL_PORT_ETHERTYPE: "NL80211_ATTR_CONTROL_PORT_ETHERTYPE",
+    NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: "NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT",
+    NL80211_ATTR_SUPPORT_IBSS_RSN: "NL80211_ATTR_SUPPORT_IBSS_RSN",
+    NL80211_ATTR_WIPHY_ANTENNA_TX: "NL80211_ATTR_WIPHY_ANTENNA_TX",
+    NL80211_ATTR_WIPHY_ANTENNA_RX: "NL80211_ATTR_WIPHY_ANTENNA_RX",
+    NL80211_ATTR_MCAST_RATE: "NL80211_ATTR_MCAST_RATE",
+    NL80211_ATTR_OFFCHANNEL_TX_OK: "NL80211_ATTR_OFFCHANNEL_TX_OK",
+    NL80211_ATTR_BSS_HT_OPMODE: "NL80211_ATTR_BSS_HT_OPMODE",
+    NL80211_ATTR_KEY_DEFAULT_TYPES: "NL80211_ATTR_KEY_DEFAULT_TYPES",
+    NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: "NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION",
+    NL80211_ATTR_MESH_SETUP: "NL80211_ATTR_MESH_SETUP",
+    NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX",
+    NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: "NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX",
+    NL80211_ATTR_SUPPORT_MESH_AUTH: "NL80211_ATTR_SUPPORT_MESH_AUTH",
+    NL80211_ATTR_STA_PLINK_STATE: "NL80211_ATTR_STA_PLINK_STATE",
+    NL80211_ATTR_WOWLAN_TRIGGERS: "NL80211_ATTR_WOWLAN_TRIGGERS",
+    NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: "NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED",
+    NL80211_ATTR_SCHED_SCAN_INTERVAL: "NL80211_ATTR_SCHED_SCAN_INTERVAL",
+    NL80211_ATTR_INTERFACE_COMBINATIONS: "NL80211_ATTR_INTERFACE_COMBINATIONS",
+    NL80211_ATTR_SOFTWARE_IFTYPES: "NL80211_ATTR_SOFTWARE_IFTYPES",
+    NL80211_ATTR_REKEY_DATA: "NL80211_ATTR_REKEY_DATA",
+    NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: "NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS",
+    NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: "NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN",
+    NL80211_ATTR_SCAN_SUPP_RATES: "NL80211_ATTR_SCAN_SUPP_RATES",
+    NL80211_ATTR_HIDDEN_SSID: "NL80211_ATTR_HIDDEN_SSID",
+    NL80211_ATTR_IE_PROBE_RESP: "NL80211_ATTR_IE_PROBE_RESP",
+    NL80211_ATTR_IE_ASSOC_RESP: "NL80211_ATTR_IE_ASSOC_RESP",
+    NL80211_ATTR_STA_WME: "NL80211_ATTR_STA_WME",
+    NL80211_ATTR_SUPPORT_AP_UAPSD: "NL80211_ATTR_SUPPORT_AP_UAPSD",
+    NL80211_ATTR_ROAM_SUPPORT: "NL80211_ATTR_ROAM_SUPPORT",
+    NL80211_ATTR_SCHED_SCAN_MATCH: "NL80211_ATTR_SCHED_SCAN_MATCH",
+    NL80211_ATTR_MAX_MATCH_SETS: "NL80211_ATTR_MAX_MATCH_SETS",
+    NL80211_ATTR_PMKSA_CANDIDATE: "NL80211_ATTR_PMKSA_CANDIDATE",
+    NL80211_ATTR_TX_NO_CCK_RATE: "NL80211_ATTR_TX_NO_CCK_RATE",
+    NL80211_ATTR_TDLS_ACTION: "NL80211_ATTR_TDLS_ACTION",
+    NL80211_ATTR_TDLS_DIALOG_TOKEN: "NL80211_ATTR_TDLS_DIALOG_TOKEN",
+    NL80211_ATTR_TDLS_OPERATION: "NL80211_ATTR_TDLS_OPERATION",
+    NL80211_ATTR_TDLS_SUPPORT: "NL80211_ATTR_TDLS_SUPPORT",
+    NL80211_ATTR_TDLS_EXTERNAL_SETUP: "NL80211_ATTR_TDLS_EXTERNAL_SETUP",
+    NL80211_ATTR_DEVICE_AP_SME: "NL80211_ATTR_DEVICE_AP_SME",
+    NL80211_ATTR_DONT_WAIT_FOR_ACK: "NL80211_ATTR_DONT_WAIT_FOR_ACK",
+    NL80211_ATTR_FEATURE_FLAGS: "NL80211_ATTR_FEATURE_FLAGS",
+    NL80211_ATTR_PROBE_RESP_OFFLOAD: "NL80211_ATTR_PROBE_RESP_OFFLOAD",
+    NL80211_ATTR_PROBE_RESP: "NL80211_ATTR_PROBE_RESP",
+    NL80211_ATTR_DFS_REGION: "NL80211_ATTR_DFS_REGION",
+    NL80211_ATTR_DISABLE_HT: "NL80211_ATTR_DISABLE_HT",
+    NL80211_ATTR_HT_CAPABILITY_MASK: "NL80211_ATTR_HT_CAPABILITY_MASK",
+    NL80211_ATTR_NOACK_MAP: "NL80211_ATTR_NOACK_MAP",
+    NL80211_ATTR_INACTIVITY_TIMEOUT: "NL80211_ATTR_INACTIVITY_TIMEOUT",
+    NL80211_ATTR_RX_SIGNAL_DBM: "NL80211_ATTR_RX_SIGNAL_DBM",
+    NL80211_ATTR_BG_SCAN_PERIOD: "NL80211_ATTR_BG_SCAN_PERIOD",
+    NL80211_ATTR_WDEV: "NL80211_ATTR_WDEV",
+    NL80211_ATTR_USER_REG_HINT_TYPE: "NL80211_ATTR_USER_REG_HINT_TYPE",
+    NL80211_ATTR_CONN_FAILED_REASON: "NL80211_ATTR_CONN_FAILED_REASON",
+    NL80211_ATTR_SAE_DATA: "NL80211_ATTR_SAE_DATA",
+    NL80211_ATTR_VHT_CAPABILITY: "NL80211_ATTR_VHT_CAPABILITY",
+    NL80211_ATTR_SCAN_FLAGS: "NL80211_ATTR_SCAN_FLAGS",
+    NL80211_ATTR_CHANNEL_WIDTH: "NL80211_ATTR_CHANNEL_WIDTH",
+    NL80211_ATTR_CENTER_FREQ1: "NL80211_ATTR_CENTER_FREQ1",
+    NL80211_ATTR_CENTER_FREQ2: "NL80211_ATTR_CENTER_FREQ2",
+    NL80211_ATTR_P2P_CTWINDOW: "NL80211_ATTR_P2P_CTWINDOW",
+    NL80211_ATTR_P2P_OPPPS: "NL80211_ATTR_P2P_OPPPS",
+    NL80211_ATTR_LOCAL_MESH_POWER_MODE: "NL80211_ATTR_LOCAL_MESH_POWER_MODE",
+    NL80211_ATTR_ACL_POLICY: "NL80211_ATTR_ACL_POLICY",
+    NL80211_ATTR_MAC_ADDRS: "NL80211_ATTR_MAC_ADDRS",
+    NL80211_ATTR_MAC_ACL_MAX: "NL80211_ATTR_MAC_ACL_MAX",
+    NL80211_ATTR_RADAR_EVENT: "NL80211_ATTR_RADAR_EVENT",
+    NL80211_ATTR_EXT_CAPA: "NL80211_ATTR_EXT_CAPA",
+    NL80211_ATTR_EXT_CAPA_MASK: "NL80211_ATTR_EXT_CAPA_MASK",
+    NL80211_ATTR_STA_CAPABILITY: "NL80211_ATTR_STA_CAPABILITY",
+    NL80211_ATTR_STA_EXT_CAPABILITY: "NL80211_ATTR_STA_EXT_CAPABILITY",
+    NL80211_ATTR_PROTOCOL_FEATURES: "NL80211_ATTR_PROTOCOL_FEATURES",
+    NL80211_ATTR_SPLIT_WIPHY_DUMP: "NL80211_ATTR_SPLIT_WIPHY_DUMP",
+    NL80211_ATTR_DISABLE_VHT: "NL80211_ATTR_DISABLE_VHT",
+    NL80211_ATTR_VHT_CAPABILITY_MASK: "NL80211_ATTR_VHT_CAPABILITY_MASK",
+    NL80211_ATTR_MDID: "NL80211_ATTR_MDID",
+    NL80211_ATTR_IE_RIC: "NL80211_ATTR_IE_RIC",
+    NL80211_ATTR_CRIT_PROT_ID: "NL80211_ATTR_CRIT_PROT_ID",
+    NL80211_ATTR_MAX_CRIT_PROT_DURATION: "NL80211_ATTR_MAX_CRIT_PROT_DURATION",
+    NL80211_ATTR_PEER_AID: "NL80211_ATTR_PEER_AID",
+    __NL80211_ATTR_AFTER_LAST: "__NL80211_ATTR_AFTER_LAST",
 }
 nl80211_iftype2str = {
-	NL80211_IFTYPE_UNSPECIFIED: "NL80211_IFTYPE_UNSPECIFIED",
-	NL80211_IFTYPE_ADHOC: "NL80211_IFTYPE_ADHOC",
-	NL80211_IFTYPE_STATION: "NL80211_IFTYPE_STATION",
-	NL80211_IFTYPE_AP: "NL80211_IFTYPE_AP",
-	NL80211_IFTYPE_AP_VLAN: "NL80211_IFTYPE_AP_VLAN",
-	NL80211_IFTYPE_WDS: "NL80211_IFTYPE_WDS",
-	NL80211_IFTYPE_MONITOR: "NL80211_IFTYPE_MONITOR",
-	NL80211_IFTYPE_MESH_POINT: "NL80211_IFTYPE_MESH_POINT",
-	NL80211_IFTYPE_P2P_CLIENT: "NL80211_IFTYPE_P2P_CLIENT",
-	NL80211_IFTYPE_P2P_GO: "NL80211_IFTYPE_P2P_GO",
-	NL80211_IFTYPE_P2P_DEVICE: "NL80211_IFTYPE_P2P_DEVICE",
-	NUM_NL80211_IFTYPES: "NUM_NL80211_IFTYPES",
+    NL80211_IFTYPE_UNSPECIFIED: "NL80211_IFTYPE_UNSPECIFIED",
+    NL80211_IFTYPE_ADHOC: "NL80211_IFTYPE_ADHOC",
+    NL80211_IFTYPE_STATION: "NL80211_IFTYPE_STATION",
+    NL80211_IFTYPE_AP: "NL80211_IFTYPE_AP",
+    NL80211_IFTYPE_AP_VLAN: "NL80211_IFTYPE_AP_VLAN",
+    NL80211_IFTYPE_WDS: "NL80211_IFTYPE_WDS",
+    NL80211_IFTYPE_MONITOR: "NL80211_IFTYPE_MONITOR",
+    NL80211_IFTYPE_MESH_POINT: "NL80211_IFTYPE_MESH_POINT",
+    NL80211_IFTYPE_P2P_CLIENT: "NL80211_IFTYPE_P2P_CLIENT",
+    NL80211_IFTYPE_P2P_GO: "NL80211_IFTYPE_P2P_GO",
+    NL80211_IFTYPE_P2P_DEVICE: "NL80211_IFTYPE_P2P_DEVICE",
+    NUM_NL80211_IFTYPES: "NUM_NL80211_IFTYPES",
 }
 nl80211_sta_flags2str = {
-	__NL80211_STA_FLAG_INVALID: "__NL80211_STA_FLAG_INVALID",
-	NL80211_STA_FLAG_AUTHORIZED: "NL80211_STA_FLAG_AUTHORIZED",
-	NL80211_STA_FLAG_SHORT_PREAMBLE: "NL80211_STA_FLAG_SHORT_PREAMBLE",
-	NL80211_STA_FLAG_WME: "NL80211_STA_FLAG_WME",
-	NL80211_STA_FLAG_MFP: "NL80211_STA_FLAG_MFP",
-	NL80211_STA_FLAG_AUTHENTICATED: "NL80211_STA_FLAG_AUTHENTICATED",
-	NL80211_STA_FLAG_TDLS_PEER: "NL80211_STA_FLAG_TDLS_PEER",
-	NL80211_STA_FLAG_ASSOCIATED: "NL80211_STA_FLAG_ASSOCIATED",
-	__NL80211_STA_FLAG_AFTER_LAST: "__NL80211_STA_FLAG_AFTER_LAST",
+    __NL80211_STA_FLAG_INVALID: "__NL80211_STA_FLAG_INVALID",
+    NL80211_STA_FLAG_AUTHORIZED: "NL80211_STA_FLAG_AUTHORIZED",
+    NL80211_STA_FLAG_SHORT_PREAMBLE: "NL80211_STA_FLAG_SHORT_PREAMBLE",
+    NL80211_STA_FLAG_WME: "NL80211_STA_FLAG_WME",
+    NL80211_STA_FLAG_MFP: "NL80211_STA_FLAG_MFP",
+    NL80211_STA_FLAG_AUTHENTICATED: "NL80211_STA_FLAG_AUTHENTICATED",
+    NL80211_STA_FLAG_TDLS_PEER: "NL80211_STA_FLAG_TDLS_PEER",
+    NL80211_STA_FLAG_ASSOCIATED: "NL80211_STA_FLAG_ASSOCIATED",
+    __NL80211_STA_FLAG_AFTER_LAST: "__NL80211_STA_FLAG_AFTER_LAST",
 }
 nl80211_rate_info2str = {
-	__NL80211_RATE_INFO_INVALID: "__NL80211_RATE_INFO_INVALID",
-	NL80211_RATE_INFO_BITRATE: "NL80211_RATE_INFO_BITRATE",
-	NL80211_RATE_INFO_MCS: "NL80211_RATE_INFO_MCS",
-	NL80211_RATE_INFO_40_MHZ_WIDTH: "NL80211_RATE_INFO_40_MHZ_WIDTH",
-	NL80211_RATE_INFO_SHORT_GI: "NL80211_RATE_INFO_SHORT_GI",
-	NL80211_RATE_INFO_BITRATE32: "NL80211_RATE_INFO_BITRATE32",
-	NL80211_RATE_INFO_VHT_MCS: "NL80211_RATE_INFO_VHT_MCS",
-	NL80211_RATE_INFO_VHT_NSS: "NL80211_RATE_INFO_VHT_NSS",
-	NL80211_RATE_INFO_80_MHZ_WIDTH: "NL80211_RATE_INFO_80_MHZ_WIDTH",
-	NL80211_RATE_INFO_80P80_MHZ_WIDTH: "NL80211_RATE_INFO_80P80_MHZ_WIDTH",
-	NL80211_RATE_INFO_160_MHZ_WIDTH: "NL80211_RATE_INFO_160_MHZ_WIDTH",
-	__NL80211_RATE_INFO_AFTER_LAST: "__NL80211_RATE_INFO_AFTER_LAST",
+    __NL80211_RATE_INFO_INVALID: "__NL80211_RATE_INFO_INVALID",
+    NL80211_RATE_INFO_BITRATE: "NL80211_RATE_INFO_BITRATE",
+    NL80211_RATE_INFO_MCS: "NL80211_RATE_INFO_MCS",
+    NL80211_RATE_INFO_40_MHZ_WIDTH: "NL80211_RATE_INFO_40_MHZ_WIDTH",
+    NL80211_RATE_INFO_SHORT_GI: "NL80211_RATE_INFO_SHORT_GI",
+    NL80211_RATE_INFO_BITRATE32: "NL80211_RATE_INFO_BITRATE32",
+    NL80211_RATE_INFO_VHT_MCS: "NL80211_RATE_INFO_VHT_MCS",
+    NL80211_RATE_INFO_VHT_NSS: "NL80211_RATE_INFO_VHT_NSS",
+    NL80211_RATE_INFO_80_MHZ_WIDTH: "NL80211_RATE_INFO_80_MHZ_WIDTH",
+    NL80211_RATE_INFO_80P80_MHZ_WIDTH: "NL80211_RATE_INFO_80P80_MHZ_WIDTH",
+    NL80211_RATE_INFO_160_MHZ_WIDTH: "NL80211_RATE_INFO_160_MHZ_WIDTH",
+    __NL80211_RATE_INFO_AFTER_LAST: "__NL80211_RATE_INFO_AFTER_LAST",
 }
 nl80211_sta_bss_param2str = {
-	__NL80211_STA_BSS_PARAM_INVALID: "__NL80211_STA_BSS_PARAM_INVALID",
-	NL80211_STA_BSS_PARAM_CTS_PROT: "NL80211_STA_BSS_PARAM_CTS_PROT",
-	NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: "NL80211_STA_BSS_PARAM_SHORT_PREAMBLE",
-	NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: "NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME",
-	NL80211_STA_BSS_PARAM_DTIM_PERIOD: "NL80211_STA_BSS_PARAM_DTIM_PERIOD",
-	NL80211_STA_BSS_PARAM_BEACON_INTERVAL: "NL80211_STA_BSS_PARAM_BEACON_INTERVAL",
-	__NL80211_STA_BSS_PARAM_AFTER_LAST: "__NL80211_STA_BSS_PARAM_AFTER_LAST",
+    __NL80211_STA_BSS_PARAM_INVALID: "__NL80211_STA_BSS_PARAM_INVALID",
+    NL80211_STA_BSS_PARAM_CTS_PROT: "NL80211_STA_BSS_PARAM_CTS_PROT",
+    NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: "NL80211_STA_BSS_PARAM_SHORT_PREAMBLE",
+    NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: "NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME",
+    NL80211_STA_BSS_PARAM_DTIM_PERIOD: "NL80211_STA_BSS_PARAM_DTIM_PERIOD",
+    NL80211_STA_BSS_PARAM_BEACON_INTERVAL: "NL80211_STA_BSS_PARAM_BEACON_INTERVAL",
+    __NL80211_STA_BSS_PARAM_AFTER_LAST: "__NL80211_STA_BSS_PARAM_AFTER_LAST",
 }
 nl80211_sta_info2str = {
-	__NL80211_STA_INFO_INVALID: "__NL80211_STA_INFO_INVALID",
-	NL80211_STA_INFO_INACTIVE_TIME: "NL80211_STA_INFO_INACTIVE_TIME",
-	NL80211_STA_INFO_RX_BYTES: "NL80211_STA_INFO_RX_BYTES",
-	NL80211_STA_INFO_TX_BYTES: "NL80211_STA_INFO_TX_BYTES",
-	NL80211_STA_INFO_LLID: "NL80211_STA_INFO_LLID",
-	NL80211_STA_INFO_PLID: "NL80211_STA_INFO_PLID",
-	NL80211_STA_INFO_PLINK_STATE: "NL80211_STA_INFO_PLINK_STATE",
-	NL80211_STA_INFO_SIGNAL: "NL80211_STA_INFO_SIGNAL",
-	NL80211_STA_INFO_TX_BITRATE: "NL80211_STA_INFO_TX_BITRATE",
-	NL80211_STA_INFO_RX_PACKETS: "NL80211_STA_INFO_RX_PACKETS",
-	NL80211_STA_INFO_TX_PACKETS: "NL80211_STA_INFO_TX_PACKETS",
-	NL80211_STA_INFO_TX_RETRIES: "NL80211_STA_INFO_TX_RETRIES",
-	NL80211_STA_INFO_TX_FAILED: "NL80211_STA_INFO_TX_FAILED",
-	NL80211_STA_INFO_SIGNAL_AVG: "NL80211_STA_INFO_SIGNAL_AVG",
-	NL80211_STA_INFO_RX_BITRATE: "NL80211_STA_INFO_RX_BITRATE",
-	NL80211_STA_INFO_BSS_PARAM: "NL80211_STA_INFO_BSS_PARAM",
-	NL80211_STA_INFO_CONNECTED_TIME: "NL80211_STA_INFO_CONNECTED_TIME",
-	NL80211_STA_INFO_STA_FLAGS: "NL80211_STA_INFO_STA_FLAGS",
-	NL80211_STA_INFO_BEACON_LOSS: "NL80211_STA_INFO_BEACON_LOSS",
-	NL80211_STA_INFO_T_OFFSET: "NL80211_STA_INFO_T_OFFSET",
-	NL80211_STA_INFO_LOCAL_PM: "NL80211_STA_INFO_LOCAL_PM",
-	NL80211_STA_INFO_PEER_PM: "NL80211_STA_INFO_PEER_PM",
-	NL80211_STA_INFO_NONPEER_PM: "NL80211_STA_INFO_NONPEER_PM",
-	NL80211_STA_INFO_RX_BYTES64: "NL80211_STA_INFO_RX_BYTES64",
-	NL80211_STA_INFO_TX_BYTES64: "NL80211_STA_INFO_TX_BYTES64",
-	NL80211_STA_INFO_CHAIN_SIGNAL: "NL80211_STA_INFO_CHAIN_SIGNAL",
-	NL80211_STA_INFO_CHAIN_SIGNAL_AVG: "NL80211_STA_INFO_CHAIN_SIGNAL_AVG",
-	__NL80211_STA_INFO_AFTER_LAST: "__NL80211_STA_INFO_AFTER_LAST",
+    __NL80211_STA_INFO_INVALID: "__NL80211_STA_INFO_INVALID",
+    NL80211_STA_INFO_INACTIVE_TIME: "NL80211_STA_INFO_INACTIVE_TIME",
+    NL80211_STA_INFO_RX_BYTES: "NL80211_STA_INFO_RX_BYTES",
+    NL80211_STA_INFO_TX_BYTES: "NL80211_STA_INFO_TX_BYTES",
+    NL80211_STA_INFO_LLID: "NL80211_STA_INFO_LLID",
+    NL80211_STA_INFO_PLID: "NL80211_STA_INFO_PLID",
+    NL80211_STA_INFO_PLINK_STATE: "NL80211_STA_INFO_PLINK_STATE",
+    NL80211_STA_INFO_SIGNAL: "NL80211_STA_INFO_SIGNAL",
+    NL80211_STA_INFO_TX_BITRATE: "NL80211_STA_INFO_TX_BITRATE",
+    NL80211_STA_INFO_RX_PACKETS: "NL80211_STA_INFO_RX_PACKETS",
+    NL80211_STA_INFO_TX_PACKETS: "NL80211_STA_INFO_TX_PACKETS",
+    NL80211_STA_INFO_TX_RETRIES: "NL80211_STA_INFO_TX_RETRIES",
+    NL80211_STA_INFO_TX_FAILED: "NL80211_STA_INFO_TX_FAILED",
+    NL80211_STA_INFO_SIGNAL_AVG: "NL80211_STA_INFO_SIGNAL_AVG",
+    NL80211_STA_INFO_RX_BITRATE: "NL80211_STA_INFO_RX_BITRATE",
+    NL80211_STA_INFO_BSS_PARAM: "NL80211_STA_INFO_BSS_PARAM",
+    NL80211_STA_INFO_CONNECTED_TIME: "NL80211_STA_INFO_CONNECTED_TIME",
+    NL80211_STA_INFO_STA_FLAGS: "NL80211_STA_INFO_STA_FLAGS",
+    NL80211_STA_INFO_BEACON_LOSS: "NL80211_STA_INFO_BEACON_LOSS",
+    NL80211_STA_INFO_T_OFFSET: "NL80211_STA_INFO_T_OFFSET",
+    NL80211_STA_INFO_LOCAL_PM: "NL80211_STA_INFO_LOCAL_PM",
+    NL80211_STA_INFO_PEER_PM: "NL80211_STA_INFO_PEER_PM",
+    NL80211_STA_INFO_NONPEER_PM: "NL80211_STA_INFO_NONPEER_PM",
+    NL80211_STA_INFO_RX_BYTES64: "NL80211_STA_INFO_RX_BYTES64",
+    NL80211_STA_INFO_TX_BYTES64: "NL80211_STA_INFO_TX_BYTES64",
+    NL80211_STA_INFO_CHAIN_SIGNAL: "NL80211_STA_INFO_CHAIN_SIGNAL",
+    NL80211_STA_INFO_CHAIN_SIGNAL_AVG: "NL80211_STA_INFO_CHAIN_SIGNAL_AVG",
+    __NL80211_STA_INFO_AFTER_LAST: "__NL80211_STA_INFO_AFTER_LAST",
 }
 nl80211_mpath_flags2str = {
-	NL80211_MPATH_FLAG_ACTIVE: "NL80211_MPATH_FLAG_ACTIVE",
-	NL80211_MPATH_FLAG_RESOLVING: "NL80211_MPATH_FLAG_RESOLVING",
-	NL80211_MPATH_FLAG_SN_VALID: "NL80211_MPATH_FLAG_SN_VALID",
-	NL80211_MPATH_FLAG_FIXED: "NL80211_MPATH_FLAG_FIXED",
-	NL80211_MPATH_FLAG_RESOLVED: "NL80211_MPATH_FLAG_RESOLVED",
+    NL80211_MPATH_FLAG_ACTIVE: "NL80211_MPATH_FLAG_ACTIVE",
+    NL80211_MPATH_FLAG_RESOLVING: "NL80211_MPATH_FLAG_RESOLVING",
+    NL80211_MPATH_FLAG_SN_VALID: "NL80211_MPATH_FLAG_SN_VALID",
+    NL80211_MPATH_FLAG_FIXED: "NL80211_MPATH_FLAG_FIXED",
+    NL80211_MPATH_FLAG_RESOLVED: "NL80211_MPATH_FLAG_RESOLVED",
 }
 nl80211_mpath_info2str = {
-	__NL80211_MPATH_INFO_INVALID: "__NL80211_MPATH_INFO_INVALID",
-	NL80211_MPATH_INFO_FRAME_QLEN: "NL80211_MPATH_INFO_FRAME_QLEN",
-	NL80211_MPATH_INFO_SN: "NL80211_MPATH_INFO_SN",
-	NL80211_MPATH_INFO_METRIC: "NL80211_MPATH_INFO_METRIC",
-	NL80211_MPATH_INFO_EXPTIME: "NL80211_MPATH_INFO_EXPTIME",
-	NL80211_MPATH_INFO_FLAGS: "NL80211_MPATH_INFO_FLAGS",
-	NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: "NL80211_MPATH_INFO_DISCOVERY_TIMEOUT",
-	NL80211_MPATH_INFO_DISCOVERY_RETRIES: "NL80211_MPATH_INFO_DISCOVERY_RETRIES",
-	__NL80211_MPATH_INFO_AFTER_LAST: "__NL80211_MPATH_INFO_AFTER_LAST",
+    __NL80211_MPATH_INFO_INVALID: "__NL80211_MPATH_INFO_INVALID",
+    NL80211_MPATH_INFO_FRAME_QLEN: "NL80211_MPATH_INFO_FRAME_QLEN",
+    NL80211_MPATH_INFO_SN: "NL80211_MPATH_INFO_SN",
+    NL80211_MPATH_INFO_METRIC: "NL80211_MPATH_INFO_METRIC",
+    NL80211_MPATH_INFO_EXPTIME: "NL80211_MPATH_INFO_EXPTIME",
+    NL80211_MPATH_INFO_FLAGS: "NL80211_MPATH_INFO_FLAGS",
+    NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: "NL80211_MPATH_INFO_DISCOVERY_TIMEOUT",
+    NL80211_MPATH_INFO_DISCOVERY_RETRIES: "NL80211_MPATH_INFO_DISCOVERY_RETRIES",
+    __NL80211_MPATH_INFO_AFTER_LAST: "__NL80211_MPATH_INFO_AFTER_LAST",
 }
 nl80211_band_attr2str = {
-	__NL80211_BAND_ATTR_INVALID: "__NL80211_BAND_ATTR_INVALID",
-	NL80211_BAND_ATTR_FREQS: "NL80211_BAND_ATTR_FREQS",
-	NL80211_BAND_ATTR_RATES: "NL80211_BAND_ATTR_RATES",
-	NL80211_BAND_ATTR_HT_MCS_SET: "NL80211_BAND_ATTR_HT_MCS_SET",
-	NL80211_BAND_ATTR_HT_CAPA: "NL80211_BAND_ATTR_HT_CAPA",
-	NL80211_BAND_ATTR_HT_AMPDU_FACTOR: "NL80211_BAND_ATTR_HT_AMPDU_FACTOR",
-	NL80211_BAND_ATTR_HT_AMPDU_DENSITY: "NL80211_BAND_ATTR_HT_AMPDU_DENSITY",
-	NL80211_BAND_ATTR_VHT_MCS_SET: "NL80211_BAND_ATTR_VHT_MCS_SET",
-	NL80211_BAND_ATTR_VHT_CAPA: "NL80211_BAND_ATTR_VHT_CAPA",
-	__NL80211_BAND_ATTR_AFTER_LAST: "__NL80211_BAND_ATTR_AFTER_LAST",
+    __NL80211_BAND_ATTR_INVALID: "__NL80211_BAND_ATTR_INVALID",
+    NL80211_BAND_ATTR_FREQS: "NL80211_BAND_ATTR_FREQS",
+    NL80211_BAND_ATTR_RATES: "NL80211_BAND_ATTR_RATES",
+    NL80211_BAND_ATTR_HT_MCS_SET: "NL80211_BAND_ATTR_HT_MCS_SET",
+    NL80211_BAND_ATTR_HT_CAPA: "NL80211_BAND_ATTR_HT_CAPA",
+    NL80211_BAND_ATTR_HT_AMPDU_FACTOR: "NL80211_BAND_ATTR_HT_AMPDU_FACTOR",
+    NL80211_BAND_ATTR_HT_AMPDU_DENSITY: "NL80211_BAND_ATTR_HT_AMPDU_DENSITY",
+    NL80211_BAND_ATTR_VHT_MCS_SET: "NL80211_BAND_ATTR_VHT_MCS_SET",
+    NL80211_BAND_ATTR_VHT_CAPA: "NL80211_BAND_ATTR_VHT_CAPA",
+    __NL80211_BAND_ATTR_AFTER_LAST: "__NL80211_BAND_ATTR_AFTER_LAST",
 }
 nl80211_frequency_attr2str = {
-	__NL80211_FREQUENCY_ATTR_INVALID: "__NL80211_FREQUENCY_ATTR_INVALID",
-	NL80211_FREQUENCY_ATTR_FREQ: "NL80211_FREQUENCY_ATTR_FREQ",
-	NL80211_FREQUENCY_ATTR_DISABLED: "NL80211_FREQUENCY_ATTR_DISABLED",
-	NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: "NL80211_FREQUENCY_ATTR_PASSIVE_SCAN",
-	NL80211_FREQUENCY_ATTR_NO_IBSS: "NL80211_FREQUENCY_ATTR_NO_IBSS",
-	NL80211_FREQUENCY_ATTR_RADAR: "NL80211_FREQUENCY_ATTR_RADAR",
-	NL80211_FREQUENCY_ATTR_MAX_TX_POWER: "NL80211_FREQUENCY_ATTR_MAX_TX_POWER",
-	NL80211_FREQUENCY_ATTR_DFS_STATE: "NL80211_FREQUENCY_ATTR_DFS_STATE",
-	NL80211_FREQUENCY_ATTR_DFS_TIME: "NL80211_FREQUENCY_ATTR_DFS_TIME",
-	NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: "NL80211_FREQUENCY_ATTR_NO_HT40_MINUS",
-	NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: "NL80211_FREQUENCY_ATTR_NO_HT40_PLUS",
-	NL80211_FREQUENCY_ATTR_NO_80MHZ: "NL80211_FREQUENCY_ATTR_NO_80MHZ",
-	NL80211_FREQUENCY_ATTR_NO_160MHZ: "NL80211_FREQUENCY_ATTR_NO_160MHZ",
-	__NL80211_FREQUENCY_ATTR_AFTER_LAST: "__NL80211_FREQUENCY_ATTR_AFTER_LAST",
+    __NL80211_FREQUENCY_ATTR_INVALID: "__NL80211_FREQUENCY_ATTR_INVALID",
+    NL80211_FREQUENCY_ATTR_FREQ: "NL80211_FREQUENCY_ATTR_FREQ",
+    NL80211_FREQUENCY_ATTR_DISABLED: "NL80211_FREQUENCY_ATTR_DISABLED",
+    NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: "NL80211_FREQUENCY_ATTR_PASSIVE_SCAN",
+    NL80211_FREQUENCY_ATTR_NO_IBSS: "NL80211_FREQUENCY_ATTR_NO_IBSS",
+    NL80211_FREQUENCY_ATTR_RADAR: "NL80211_FREQUENCY_ATTR_RADAR",
+    NL80211_FREQUENCY_ATTR_MAX_TX_POWER: "NL80211_FREQUENCY_ATTR_MAX_TX_POWER",
+    NL80211_FREQUENCY_ATTR_DFS_STATE: "NL80211_FREQUENCY_ATTR_DFS_STATE",
+    NL80211_FREQUENCY_ATTR_DFS_TIME: "NL80211_FREQUENCY_ATTR_DFS_TIME",
+    NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: "NL80211_FREQUENCY_ATTR_NO_HT40_MINUS",
+    NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: "NL80211_FREQUENCY_ATTR_NO_HT40_PLUS",
+    NL80211_FREQUENCY_ATTR_NO_80MHZ: "NL80211_FREQUENCY_ATTR_NO_80MHZ",
+    NL80211_FREQUENCY_ATTR_NO_160MHZ: "NL80211_FREQUENCY_ATTR_NO_160MHZ",
+    __NL80211_FREQUENCY_ATTR_AFTER_LAST: "__NL80211_FREQUENCY_ATTR_AFTER_LAST",
 }
 nl80211_bitrate_attr2str = {
-	__NL80211_BITRATE_ATTR_INVALID: "__NL80211_BITRATE_ATTR_INVALID",
-	NL80211_BITRATE_ATTR_RATE: "NL80211_BITRATE_ATTR_RATE",
-	NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: "NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE",
-	__NL80211_BITRATE_ATTR_AFTER_LAST: "__NL80211_BITRATE_ATTR_AFTER_LAST",
+    __NL80211_BITRATE_ATTR_INVALID: "__NL80211_BITRATE_ATTR_INVALID",
+    NL80211_BITRATE_ATTR_RATE: "NL80211_BITRATE_ATTR_RATE",
+    NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: "NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE",
+    __NL80211_BITRATE_ATTR_AFTER_LAST: "__NL80211_BITRATE_ATTR_AFTER_LAST",
 }
 nl80211_reg_initiator2str = {
-	NL80211_REGDOM_SET_BY_CORE: "NL80211_REGDOM_SET_BY_CORE",
-	NL80211_REGDOM_SET_BY_USER: "NL80211_REGDOM_SET_BY_USER",
-	NL80211_REGDOM_SET_BY_DRIVER: "NL80211_REGDOM_SET_BY_DRIVER",
-	NL80211_REGDOM_SET_BY_COUNTRY_IE: "NL80211_REGDOM_SET_BY_COUNTRY_IE",
+    NL80211_REGDOM_SET_BY_CORE: "NL80211_REGDOM_SET_BY_CORE",
+    NL80211_REGDOM_SET_BY_USER: "NL80211_REGDOM_SET_BY_USER",
+    NL80211_REGDOM_SET_BY_DRIVER: "NL80211_REGDOM_SET_BY_DRIVER",
+    NL80211_REGDOM_SET_BY_COUNTRY_IE: "NL80211_REGDOM_SET_BY_COUNTRY_IE",
 }
 nl80211_reg_type2str = {
-	NL80211_REGDOM_TYPE_COUNTRY: "NL80211_REGDOM_TYPE_COUNTRY",
-	NL80211_REGDOM_TYPE_WORLD: "NL80211_REGDOM_TYPE_WORLD",
-	NL80211_REGDOM_TYPE_CUSTOM_WORLD: "NL80211_REGDOM_TYPE_CUSTOM_WORLD",
-	NL80211_REGDOM_TYPE_INTERSECTION: "NL80211_REGDOM_TYPE_INTERSECTION",
+    NL80211_REGDOM_TYPE_COUNTRY: "NL80211_REGDOM_TYPE_COUNTRY",
+    NL80211_REGDOM_TYPE_WORLD: "NL80211_REGDOM_TYPE_WORLD",
+    NL80211_REGDOM_TYPE_CUSTOM_WORLD: "NL80211_REGDOM_TYPE_CUSTOM_WORLD",
+    NL80211_REGDOM_TYPE_INTERSECTION: "NL80211_REGDOM_TYPE_INTERSECTION",
 }
 nl80211_reg_rule_attr2str = {
-	__NL80211_REG_RULE_ATTR_INVALID: "__NL80211_REG_RULE_ATTR_INVALID",
-	NL80211_ATTR_REG_RULE_FLAGS: "NL80211_ATTR_REG_RULE_FLAGS",
-	NL80211_ATTR_FREQ_RANGE_START: "NL80211_ATTR_FREQ_RANGE_START",
-	NL80211_ATTR_FREQ_RANGE_END: "NL80211_ATTR_FREQ_RANGE_END",
-	NL80211_ATTR_FREQ_RANGE_MAX_BW: "NL80211_ATTR_FREQ_RANGE_MAX_BW",
-	NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: "NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN",
-	NL80211_ATTR_POWER_RULE_MAX_EIRP: "NL80211_ATTR_POWER_RULE_MAX_EIRP",
-	__NL80211_REG_RULE_ATTR_AFTER_LAST: "__NL80211_REG_RULE_ATTR_AFTER_LAST",
+    __NL80211_REG_RULE_ATTR_INVALID: "__NL80211_REG_RULE_ATTR_INVALID",
+    NL80211_ATTR_REG_RULE_FLAGS: "NL80211_ATTR_REG_RULE_FLAGS",
+    NL80211_ATTR_FREQ_RANGE_START: "NL80211_ATTR_FREQ_RANGE_START",
+    NL80211_ATTR_FREQ_RANGE_END: "NL80211_ATTR_FREQ_RANGE_END",
+    NL80211_ATTR_FREQ_RANGE_MAX_BW: "NL80211_ATTR_FREQ_RANGE_MAX_BW",
+    NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: "NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN",
+    NL80211_ATTR_POWER_RULE_MAX_EIRP: "NL80211_ATTR_POWER_RULE_MAX_EIRP",
+    __NL80211_REG_RULE_ATTR_AFTER_LAST: "__NL80211_REG_RULE_ATTR_AFTER_LAST",
 }
 nl80211_sched_scan_match_attr2str = {
-	__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: "__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID",
-	NL80211_SCHED_SCAN_MATCH_ATTR_SSID: "NL80211_SCHED_SCAN_MATCH_ATTR_SSID",
-	NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: "NL80211_SCHED_SCAN_MATCH_ATTR_RSSI",
-	__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: "__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST",
+    __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: "__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID",
+    NL80211_SCHED_SCAN_MATCH_ATTR_SSID: "NL80211_SCHED_SCAN_MATCH_ATTR_SSID",
+    NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: "NL80211_SCHED_SCAN_MATCH_ATTR_RSSI",
+    __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: "__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST",
 }
 nl80211_reg_rule_flags2str = {
-	NL80211_RRF_NO_OFDM: "NL80211_RRF_NO_OFDM",
-	NL80211_RRF_NO_CCK: "NL80211_RRF_NO_CCK",
-	NL80211_RRF_NO_INDOOR: "NL80211_RRF_NO_INDOOR",
-	NL80211_RRF_NO_OUTDOOR: "NL80211_RRF_NO_OUTDOOR",
-	NL80211_RRF_DFS: "NL80211_RRF_DFS",
-	NL80211_RRF_PTP_ONLY: "NL80211_RRF_PTP_ONLY",
-	NL80211_RRF_PTMP_ONLY: "NL80211_RRF_PTMP_ONLY",
-	NL80211_RRF_PASSIVE_SCAN: "NL80211_RRF_PASSIVE_SCAN",
-	NL80211_RRF_NO_IBSS: "NL80211_RRF_NO_IBSS",
+    NL80211_RRF_NO_OFDM: "NL80211_RRF_NO_OFDM",
+    NL80211_RRF_NO_CCK: "NL80211_RRF_NO_CCK",
+    NL80211_RRF_NO_INDOOR: "NL80211_RRF_NO_INDOOR",
+    NL80211_RRF_NO_OUTDOOR: "NL80211_RRF_NO_OUTDOOR",
+    NL80211_RRF_DFS: "NL80211_RRF_DFS",
+    NL80211_RRF_PTP_ONLY: "NL80211_RRF_PTP_ONLY",
+    NL80211_RRF_PTMP_ONLY: "NL80211_RRF_PTMP_ONLY",
+    NL80211_RRF_PASSIVE_SCAN: "NL80211_RRF_PASSIVE_SCAN",
+    NL80211_RRF_NO_IBSS: "NL80211_RRF_NO_IBSS",
 }
-nl80211_dfs_regions2str = {
-}
-nl80211_user_reg_hint_type2str = {
-}
+nl80211_dfs_regions2str = {}
+nl80211_user_reg_hint_type2str = {}
 nl80211_survey_info2str = {
-	__NL80211_SURVEY_INFO_INVALID: "__NL80211_SURVEY_INFO_INVALID",
-	NL80211_SURVEY_INFO_FREQUENCY: "NL80211_SURVEY_INFO_FREQUENCY",
-	NL80211_SURVEY_INFO_NOISE: "NL80211_SURVEY_INFO_NOISE",
-	NL80211_SURVEY_INFO_IN_USE: "NL80211_SURVEY_INFO_IN_USE",
-	NL80211_SURVEY_INFO_CHANNEL_TIME: "NL80211_SURVEY_INFO_CHANNEL_TIME",
-	NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY",
-	NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY",
-	NL80211_SURVEY_INFO_CHANNEL_TIME_RX: "NL80211_SURVEY_INFO_CHANNEL_TIME_RX",
-	NL80211_SURVEY_INFO_CHANNEL_TIME_TX: "NL80211_SURVEY_INFO_CHANNEL_TIME_TX",
-	__NL80211_SURVEY_INFO_AFTER_LAST: "__NL80211_SURVEY_INFO_AFTER_LAST",
+    __NL80211_SURVEY_INFO_INVALID: "__NL80211_SURVEY_INFO_INVALID",
+    NL80211_SURVEY_INFO_FREQUENCY: "NL80211_SURVEY_INFO_FREQUENCY",
+    NL80211_SURVEY_INFO_NOISE: "NL80211_SURVEY_INFO_NOISE",
+    NL80211_SURVEY_INFO_IN_USE: "NL80211_SURVEY_INFO_IN_USE",
+    NL80211_SURVEY_INFO_CHANNEL_TIME: "NL80211_SURVEY_INFO_CHANNEL_TIME",
+    NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY",
+    NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: "NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY",
+    NL80211_SURVEY_INFO_CHANNEL_TIME_RX: "NL80211_SURVEY_INFO_CHANNEL_TIME_RX",
+    NL80211_SURVEY_INFO_CHANNEL_TIME_TX: "NL80211_SURVEY_INFO_CHANNEL_TIME_TX",
+    __NL80211_SURVEY_INFO_AFTER_LAST: "__NL80211_SURVEY_INFO_AFTER_LAST",
 }
 nl80211_mntr_flags2str = {
-	__NL80211_MNTR_FLAG_INVALID: "__NL80211_MNTR_FLAG_INVALID",
-	NL80211_MNTR_FLAG_FCSFAIL: "NL80211_MNTR_FLAG_FCSFAIL",
-	NL80211_MNTR_FLAG_PLCPFAIL: "NL80211_MNTR_FLAG_PLCPFAIL",
-	NL80211_MNTR_FLAG_CONTROL: "NL80211_MNTR_FLAG_CONTROL",
-	NL80211_MNTR_FLAG_OTHER_BSS: "NL80211_MNTR_FLAG_OTHER_BSS",
-	NL80211_MNTR_FLAG_COOK_FRAMES: "NL80211_MNTR_FLAG_COOK_FRAMES",
-	NL80211_MNTR_FLAG_ACTIVE: "NL80211_MNTR_FLAG_ACTIVE",
-	__NL80211_MNTR_FLAG_AFTER_LAST: "__NL80211_MNTR_FLAG_AFTER_LAST",
+    __NL80211_MNTR_FLAG_INVALID: "__NL80211_MNTR_FLAG_INVALID",
+    NL80211_MNTR_FLAG_FCSFAIL: "NL80211_MNTR_FLAG_FCSFAIL",
+    NL80211_MNTR_FLAG_PLCPFAIL: "NL80211_MNTR_FLAG_PLCPFAIL",
+    NL80211_MNTR_FLAG_CONTROL: "NL80211_MNTR_FLAG_CONTROL",
+    NL80211_MNTR_FLAG_OTHER_BSS: "NL80211_MNTR_FLAG_OTHER_BSS",
+    NL80211_MNTR_FLAG_COOK_FRAMES: "NL80211_MNTR_FLAG_COOK_FRAMES",
+    NL80211_MNTR_FLAG_ACTIVE: "NL80211_MNTR_FLAG_ACTIVE",
+    __NL80211_MNTR_FLAG_AFTER_LAST: "__NL80211_MNTR_FLAG_AFTER_LAST",
 }
 nl80211_mesh_power_mode2str = {
-	NL80211_MESH_POWER_UNKNOWN: "NL80211_MESH_POWER_UNKNOWN",
-	NL80211_MESH_POWER_ACTIVE: "NL80211_MESH_POWER_ACTIVE",
-	NL80211_MESH_POWER_LIGHT_SLEEP: "NL80211_MESH_POWER_LIGHT_SLEEP",
-	NL80211_MESH_POWER_DEEP_SLEEP: "NL80211_MESH_POWER_DEEP_SLEEP",
-	__NL80211_MESH_POWER_AFTER_LAST: "__NL80211_MESH_POWER_AFTER_LAST",
+    NL80211_MESH_POWER_UNKNOWN: "NL80211_MESH_POWER_UNKNOWN",
+    NL80211_MESH_POWER_ACTIVE: "NL80211_MESH_POWER_ACTIVE",
+    NL80211_MESH_POWER_LIGHT_SLEEP: "NL80211_MESH_POWER_LIGHT_SLEEP",
+    NL80211_MESH_POWER_DEEP_SLEEP: "NL80211_MESH_POWER_DEEP_SLEEP",
+    __NL80211_MESH_POWER_AFTER_LAST: "__NL80211_MESH_POWER_AFTER_LAST",
 }
 nl80211_meshconf_params2str = {
-	__NL80211_MESHCONF_INVALID: "__NL80211_MESHCONF_INVALID",
-	NL80211_MESHCONF_RETRY_TIMEOUT: "NL80211_MESHCONF_RETRY_TIMEOUT",
-	NL80211_MESHCONF_CONFIRM_TIMEOUT: "NL80211_MESHCONF_CONFIRM_TIMEOUT",
-	NL80211_MESHCONF_HOLDING_TIMEOUT: "NL80211_MESHCONF_HOLDING_TIMEOUT",
-	NL80211_MESHCONF_MAX_PEER_LINKS: "NL80211_MESHCONF_MAX_PEER_LINKS",
-	NL80211_MESHCONF_MAX_RETRIES: "NL80211_MESHCONF_MAX_RETRIES",
-	NL80211_MESHCONF_TTL: "NL80211_MESHCONF_TTL",
-	NL80211_MESHCONF_AUTO_OPEN_PLINKS: "NL80211_MESHCONF_AUTO_OPEN_PLINKS",
-	NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: "NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES",
-	NL80211_MESHCONF_PATH_REFRESH_TIME: "NL80211_MESHCONF_PATH_REFRESH_TIME",
-	NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: "NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT",
-	NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: "NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT",
-	NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL",
-	NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: "NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME",
-	NL80211_MESHCONF_HWMP_ROOTMODE: "NL80211_MESHCONF_HWMP_ROOTMODE",
-	NL80211_MESHCONF_ELEMENT_TTL: "NL80211_MESHCONF_ELEMENT_TTL",
-	NL80211_MESHCONF_HWMP_RANN_INTERVAL: "NL80211_MESHCONF_HWMP_RANN_INTERVAL",
-	NL80211_MESHCONF_GATE_ANNOUNCEMENTS: "NL80211_MESHCONF_GATE_ANNOUNCEMENTS",
-	NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL",
-	NL80211_MESHCONF_FORWARDING: "NL80211_MESHCONF_FORWARDING",
-	NL80211_MESHCONF_RSSI_THRESHOLD: "NL80211_MESHCONF_RSSI_THRESHOLD",
-	NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: "NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR",
-	NL80211_MESHCONF_HT_OPMODE: "NL80211_MESHCONF_HT_OPMODE",
-	NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: "NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT",
-	NL80211_MESHCONF_HWMP_ROOT_INTERVAL: "NL80211_MESHCONF_HWMP_ROOT_INTERVAL",
-	NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: "NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL",
-	NL80211_MESHCONF_POWER_MODE: "NL80211_MESHCONF_POWER_MODE",
-	NL80211_MESHCONF_AWAKE_WINDOW: "NL80211_MESHCONF_AWAKE_WINDOW",
-	NL80211_MESHCONF_PLINK_TIMEOUT: "NL80211_MESHCONF_PLINK_TIMEOUT",
-	__NL80211_MESHCONF_ATTR_AFTER_LAST: "__NL80211_MESHCONF_ATTR_AFTER_LAST",
+    __NL80211_MESHCONF_INVALID: "__NL80211_MESHCONF_INVALID",
+    NL80211_MESHCONF_RETRY_TIMEOUT: "NL80211_MESHCONF_RETRY_TIMEOUT",
+    NL80211_MESHCONF_CONFIRM_TIMEOUT: "NL80211_MESHCONF_CONFIRM_TIMEOUT",
+    NL80211_MESHCONF_HOLDING_TIMEOUT: "NL80211_MESHCONF_HOLDING_TIMEOUT",
+    NL80211_MESHCONF_MAX_PEER_LINKS: "NL80211_MESHCONF_MAX_PEER_LINKS",
+    NL80211_MESHCONF_MAX_RETRIES: "NL80211_MESHCONF_MAX_RETRIES",
+    NL80211_MESHCONF_TTL: "NL80211_MESHCONF_TTL",
+    NL80211_MESHCONF_AUTO_OPEN_PLINKS: "NL80211_MESHCONF_AUTO_OPEN_PLINKS",
+    NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: "NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES",
+    NL80211_MESHCONF_PATH_REFRESH_TIME: "NL80211_MESHCONF_PATH_REFRESH_TIME",
+    NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: "NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT",
+    NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: "NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT",
+    NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL",
+    NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: "NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME",
+    NL80211_MESHCONF_HWMP_ROOTMODE: "NL80211_MESHCONF_HWMP_ROOTMODE",
+    NL80211_MESHCONF_ELEMENT_TTL: "NL80211_MESHCONF_ELEMENT_TTL",
+    NL80211_MESHCONF_HWMP_RANN_INTERVAL: "NL80211_MESHCONF_HWMP_RANN_INTERVAL",
+    NL80211_MESHCONF_GATE_ANNOUNCEMENTS: "NL80211_MESHCONF_GATE_ANNOUNCEMENTS",
+    NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: "NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL",
+    NL80211_MESHCONF_FORWARDING: "NL80211_MESHCONF_FORWARDING",
+    NL80211_MESHCONF_RSSI_THRESHOLD: "NL80211_MESHCONF_RSSI_THRESHOLD",
+    NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: "NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR",
+    NL80211_MESHCONF_HT_OPMODE: "NL80211_MESHCONF_HT_OPMODE",
+    NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: "NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT",
+    NL80211_MESHCONF_HWMP_ROOT_INTERVAL: "NL80211_MESHCONF_HWMP_ROOT_INTERVAL",
+    NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: "NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL",
+    NL80211_MESHCONF_POWER_MODE: "NL80211_MESHCONF_POWER_MODE",
+    NL80211_MESHCONF_AWAKE_WINDOW: "NL80211_MESHCONF_AWAKE_WINDOW",
+    NL80211_MESHCONF_PLINK_TIMEOUT: "NL80211_MESHCONF_PLINK_TIMEOUT",
+    __NL80211_MESHCONF_ATTR_AFTER_LAST: "__NL80211_MESHCONF_ATTR_AFTER_LAST",
 }
 nl80211_mesh_setup_params2str = {
-	__NL80211_MESH_SETUP_INVALID: "__NL80211_MESH_SETUP_INVALID",
-	NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: "NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL",
-	NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: "NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC",
-	NL80211_MESH_SETUP_IE: "NL80211_MESH_SETUP_IE",
-	NL80211_MESH_SETUP_USERSPACE_AUTH: "NL80211_MESH_SETUP_USERSPACE_AUTH",
-	NL80211_MESH_SETUP_USERSPACE_AMPE: "NL80211_MESH_SETUP_USERSPACE_AMPE",
-	NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: "NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC",
-	NL80211_MESH_SETUP_USERSPACE_MPM: "NL80211_MESH_SETUP_USERSPACE_MPM",
-	NL80211_MESH_SETUP_AUTH_PROTOCOL: "NL80211_MESH_SETUP_AUTH_PROTOCOL",
-	__NL80211_MESH_SETUP_ATTR_AFTER_LAST: "__NL80211_MESH_SETUP_ATTR_AFTER_LAST",
+    __NL80211_MESH_SETUP_INVALID: "__NL80211_MESH_SETUP_INVALID",
+    NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: "NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL",
+    NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: "NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC",
+    NL80211_MESH_SETUP_IE: "NL80211_MESH_SETUP_IE",
+    NL80211_MESH_SETUP_USERSPACE_AUTH: "NL80211_MESH_SETUP_USERSPACE_AUTH",
+    NL80211_MESH_SETUP_USERSPACE_AMPE: "NL80211_MESH_SETUP_USERSPACE_AMPE",
+    NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: "NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC",
+    NL80211_MESH_SETUP_USERSPACE_MPM: "NL80211_MESH_SETUP_USERSPACE_MPM",
+    NL80211_MESH_SETUP_AUTH_PROTOCOL: "NL80211_MESH_SETUP_AUTH_PROTOCOL",
+    __NL80211_MESH_SETUP_ATTR_AFTER_LAST: "__NL80211_MESH_SETUP_ATTR_AFTER_LAST",
 }
 nl80211_txq_attr2str = {
-	__NL80211_TXQ_ATTR_INVALID: "__NL80211_TXQ_ATTR_INVALID",
-	NL80211_TXQ_ATTR_AC: "NL80211_TXQ_ATTR_AC",
-	NL80211_TXQ_ATTR_TXOP: "NL80211_TXQ_ATTR_TXOP",
-	NL80211_TXQ_ATTR_CWMIN: "NL80211_TXQ_ATTR_CWMIN",
-	NL80211_TXQ_ATTR_CWMAX: "NL80211_TXQ_ATTR_CWMAX",
-	NL80211_TXQ_ATTR_AIFS: "NL80211_TXQ_ATTR_AIFS",
-	__NL80211_TXQ_ATTR_AFTER_LAST: "__NL80211_TXQ_ATTR_AFTER_LAST",
+    __NL80211_TXQ_ATTR_INVALID: "__NL80211_TXQ_ATTR_INVALID",
+    NL80211_TXQ_ATTR_AC: "NL80211_TXQ_ATTR_AC",
+    NL80211_TXQ_ATTR_TXOP: "NL80211_TXQ_ATTR_TXOP",
+    NL80211_TXQ_ATTR_CWMIN: "NL80211_TXQ_ATTR_CWMIN",
+    NL80211_TXQ_ATTR_CWMAX: "NL80211_TXQ_ATTR_CWMAX",
+    NL80211_TXQ_ATTR_AIFS: "NL80211_TXQ_ATTR_AIFS",
+    __NL80211_TXQ_ATTR_AFTER_LAST: "__NL80211_TXQ_ATTR_AFTER_LAST",
 }
 nl80211_ac2str = {
-	NL80211_AC_VO: "NL80211_AC_VO",
-	NL80211_AC_VI: "NL80211_AC_VI",
-	NL80211_AC_BE: "NL80211_AC_BE",
-	NL80211_AC_BK: "NL80211_AC_BK",
-	NL80211_NUM_ACS: "NL80211_NUM_ACS",
+    NL80211_AC_VO: "NL80211_AC_VO",
+    NL80211_AC_VI: "NL80211_AC_VI",
+    NL80211_AC_BE: "NL80211_AC_BE",
+    NL80211_AC_BK: "NL80211_AC_BK",
+    NL80211_NUM_ACS: "NL80211_NUM_ACS",
 }
 nl80211_channel_type2str = {
-	NL80211_CHAN_NO_HT: "NL80211_CHAN_NO_HT",
-	NL80211_CHAN_HT20: "NL80211_CHAN_HT20",
-	NL80211_CHAN_HT40MINUS: "NL80211_CHAN_HT40MINUS",
-	NL80211_CHAN_HT40PLUS: "NL80211_CHAN_HT40PLUS",
+    NL80211_CHAN_NO_HT: "NL80211_CHAN_NO_HT",
+    NL80211_CHAN_HT20: "NL80211_CHAN_HT20",
+    NL80211_CHAN_HT40MINUS: "NL80211_CHAN_HT40MINUS",
+    NL80211_CHAN_HT40PLUS: "NL80211_CHAN_HT40PLUS",
 }
 nl80211_chan_width2str = {
-	NL80211_CHAN_WIDTH_20_NOHT: "NL80211_CHAN_WIDTH_20_NOHT",
-	NL80211_CHAN_WIDTH_20: "NL80211_CHAN_WIDTH_20",
-	NL80211_CHAN_WIDTH_40: "NL80211_CHAN_WIDTH_40",
-	NL80211_CHAN_WIDTH_80: "NL80211_CHAN_WIDTH_80",
-	NL80211_CHAN_WIDTH_80P80: "NL80211_CHAN_WIDTH_80P80",
-	NL80211_CHAN_WIDTH_160: "NL80211_CHAN_WIDTH_160",
+    NL80211_CHAN_WIDTH_20_NOHT: "NL80211_CHAN_WIDTH_20_NOHT",
+    NL80211_CHAN_WIDTH_20: "NL80211_CHAN_WIDTH_20",
+    NL80211_CHAN_WIDTH_40: "NL80211_CHAN_WIDTH_40",
+    NL80211_CHAN_WIDTH_80: "NL80211_CHAN_WIDTH_80",
+    NL80211_CHAN_WIDTH_80P80: "NL80211_CHAN_WIDTH_80P80",
+    NL80211_CHAN_WIDTH_160: "NL80211_CHAN_WIDTH_160",
 }
 nl80211_bss2str = {
-	__NL80211_BSS_INVALID: "__NL80211_BSS_INVALID",
-	NL80211_BSS_BSSID: "NL80211_BSS_BSSID",
-	NL80211_BSS_FREQUENCY: "NL80211_BSS_FREQUENCY",
-	NL80211_BSS_TSF: "NL80211_BSS_TSF",
-	NL80211_BSS_BEACON_INTERVAL: "NL80211_BSS_BEACON_INTERVAL",
-	NL80211_BSS_CAPABILITY: "NL80211_BSS_CAPABILITY",
-	NL80211_BSS_INFORMATION_ELEMENTS: "NL80211_BSS_INFORMATION_ELEMENTS",
-	NL80211_BSS_SIGNAL_MBM: "NL80211_BSS_SIGNAL_MBM",
-	NL80211_BSS_SIGNAL_UNSPEC: "NL80211_BSS_SIGNAL_UNSPEC",
-	NL80211_BSS_STATUS: "NL80211_BSS_STATUS",
-	NL80211_BSS_SEEN_MS_AGO: "NL80211_BSS_SEEN_MS_AGO",
-	NL80211_BSS_BEACON_IES: "NL80211_BSS_BEACON_IES",
-	__NL80211_BSS_AFTER_LAST: "__NL80211_BSS_AFTER_LAST",
+    __NL80211_BSS_INVALID: "__NL80211_BSS_INVALID",
+    NL80211_BSS_BSSID: "NL80211_BSS_BSSID",
+    NL80211_BSS_FREQUENCY: "NL80211_BSS_FREQUENCY",
+    NL80211_BSS_TSF: "NL80211_BSS_TSF",
+    NL80211_BSS_BEACON_INTERVAL: "NL80211_BSS_BEACON_INTERVAL",
+    NL80211_BSS_CAPABILITY: "NL80211_BSS_CAPABILITY",
+    NL80211_BSS_INFORMATION_ELEMENTS: "NL80211_BSS_INFORMATION_ELEMENTS",
+    NL80211_BSS_SIGNAL_MBM: "NL80211_BSS_SIGNAL_MBM",
+    NL80211_BSS_SIGNAL_UNSPEC: "NL80211_BSS_SIGNAL_UNSPEC",
+    NL80211_BSS_STATUS: "NL80211_BSS_STATUS",
+    NL80211_BSS_SEEN_MS_AGO: "NL80211_BSS_SEEN_MS_AGO",
+    NL80211_BSS_BEACON_IES: "NL80211_BSS_BEACON_IES",
+    __NL80211_BSS_AFTER_LAST: "__NL80211_BSS_AFTER_LAST",
 }
 nl80211_bss_status2str = {
-	NL80211_BSS_STATUS_AUTHENTICATED: "NL80211_BSS_STATUS_AUTHENTICATED",
-	NL80211_BSS_STATUS_ASSOCIATED: "NL80211_BSS_STATUS_ASSOCIATED",
-	NL80211_BSS_STATUS_IBSS_JOINED: "NL80211_BSS_STATUS_IBSS_JOINED",
+    NL80211_BSS_STATUS_AUTHENTICATED: "NL80211_BSS_STATUS_AUTHENTICATED",
+    NL80211_BSS_STATUS_ASSOCIATED: "NL80211_BSS_STATUS_ASSOCIATED",
+    NL80211_BSS_STATUS_IBSS_JOINED: "NL80211_BSS_STATUS_IBSS_JOINED",
 }
 nl80211_auth_type2str = {
-	NL80211_AUTHTYPE_OPEN_SYSTEM: "NL80211_AUTHTYPE_OPEN_SYSTEM",
-	NL80211_AUTHTYPE_SHARED_KEY: "NL80211_AUTHTYPE_SHARED_KEY",
-	NL80211_AUTHTYPE_FT: "NL80211_AUTHTYPE_FT",
-	NL80211_AUTHTYPE_NETWORK_EAP: "NL80211_AUTHTYPE_NETWORK_EAP",
-	NL80211_AUTHTYPE_SAE: "NL80211_AUTHTYPE_SAE",
-	__NL80211_AUTHTYPE_NUM: "__NL80211_AUTHTYPE_NUM",
-	NL80211_AUTHTYPE_AUTOMATIC: "NL80211_AUTHTYPE_AUTOMATIC",
+    NL80211_AUTHTYPE_OPEN_SYSTEM: "NL80211_AUTHTYPE_OPEN_SYSTEM",
+    NL80211_AUTHTYPE_SHARED_KEY: "NL80211_AUTHTYPE_SHARED_KEY",
+    NL80211_AUTHTYPE_FT: "NL80211_AUTHTYPE_FT",
+    NL80211_AUTHTYPE_NETWORK_EAP: "NL80211_AUTHTYPE_NETWORK_EAP",
+    NL80211_AUTHTYPE_SAE: "NL80211_AUTHTYPE_SAE",
+    __NL80211_AUTHTYPE_NUM: "__NL80211_AUTHTYPE_NUM",
+    NL80211_AUTHTYPE_AUTOMATIC: "NL80211_AUTHTYPE_AUTOMATIC",
 }
 nl80211_key_type2str = {
-	NL80211_KEYTYPE_GROUP: "NL80211_KEYTYPE_GROUP",
-	NL80211_KEYTYPE_PAIRWISE: "NL80211_KEYTYPE_PAIRWISE",
-	NL80211_KEYTYPE_PEERKEY: "NL80211_KEYTYPE_PEERKEY",
-	NUM_NL80211_KEYTYPES: "NUM_NL80211_KEYTYPES",
+    NL80211_KEYTYPE_GROUP: "NL80211_KEYTYPE_GROUP",
+    NL80211_KEYTYPE_PAIRWISE: "NL80211_KEYTYPE_PAIRWISE",
+    NL80211_KEYTYPE_PEERKEY: "NL80211_KEYTYPE_PEERKEY",
+    NUM_NL80211_KEYTYPES: "NUM_NL80211_KEYTYPES",
 }
 nl80211_mfp2str = {
-	NL80211_MFP_NO: "NL80211_MFP_NO",
-	NL80211_MFP_REQUIRED: "NL80211_MFP_REQUIRED",
+    NL80211_MFP_NO: "NL80211_MFP_NO",
+    NL80211_MFP_REQUIRED: "NL80211_MFP_REQUIRED",
 }
 nl80211_wpa_versions2str = {
-	NL80211_WPA_VERSION_1: "NL80211_WPA_VERSION_1",
-	NL80211_WPA_VERSION_2: "NL80211_WPA_VERSION_2",
+    NL80211_WPA_VERSION_1: "NL80211_WPA_VERSION_1",
+    NL80211_WPA_VERSION_2: "NL80211_WPA_VERSION_2",
 }
 nl80211_key_default_types2str = {
-	__NL80211_KEY_DEFAULT_TYPE_INVALID: "__NL80211_KEY_DEFAULT_TYPE_INVALID",
-	NL80211_KEY_DEFAULT_TYPE_UNICAST: "NL80211_KEY_DEFAULT_TYPE_UNICAST",
-	NL80211_KEY_DEFAULT_TYPE_MULTICAST: "NL80211_KEY_DEFAULT_TYPE_MULTICAST",
-	NUM_NL80211_KEY_DEFAULT_TYPES: "NUM_NL80211_KEY_DEFAULT_TYPES",
+    __NL80211_KEY_DEFAULT_TYPE_INVALID: "__NL80211_KEY_DEFAULT_TYPE_INVALID",
+    NL80211_KEY_DEFAULT_TYPE_UNICAST: "NL80211_KEY_DEFAULT_TYPE_UNICAST",
+    NL80211_KEY_DEFAULT_TYPE_MULTICAST: "NL80211_KEY_DEFAULT_TYPE_MULTICAST",
+    NUM_NL80211_KEY_DEFAULT_TYPES: "NUM_NL80211_KEY_DEFAULT_TYPES",
 }
 nl80211_key_attributes2str = {
-	__NL80211_KEY_INVALID: "__NL80211_KEY_INVALID",
-	NL80211_KEY_DATA: "NL80211_KEY_DATA",
-	NL80211_KEY_IDX: "NL80211_KEY_IDX",
-	NL80211_KEY_CIPHER: "NL80211_KEY_CIPHER",
-	NL80211_KEY_SEQ: "NL80211_KEY_SEQ",
-	NL80211_KEY_DEFAULT: "NL80211_KEY_DEFAULT",
-	NL80211_KEY_DEFAULT_MGMT: "NL80211_KEY_DEFAULT_MGMT",
-	NL80211_KEY_TYPE: "NL80211_KEY_TYPE",
-	NL80211_KEY_DEFAULT_TYPES: "NL80211_KEY_DEFAULT_TYPES",
-	__NL80211_KEY_AFTER_LAST: "__NL80211_KEY_AFTER_LAST",
+    __NL80211_KEY_INVALID: "__NL80211_KEY_INVALID",
+    NL80211_KEY_DATA: "NL80211_KEY_DATA",
+    NL80211_KEY_IDX: "NL80211_KEY_IDX",
+    NL80211_KEY_CIPHER: "NL80211_KEY_CIPHER",
+    NL80211_KEY_SEQ: "NL80211_KEY_SEQ",
+    NL80211_KEY_DEFAULT: "NL80211_KEY_DEFAULT",
+    NL80211_KEY_DEFAULT_MGMT: "NL80211_KEY_DEFAULT_MGMT",
+    NL80211_KEY_TYPE: "NL80211_KEY_TYPE",
+    NL80211_KEY_DEFAULT_TYPES: "NL80211_KEY_DEFAULT_TYPES",
+    __NL80211_KEY_AFTER_LAST: "__NL80211_KEY_AFTER_LAST",
 }
 nl80211_tx_rate_attributes2str = {
-	__NL80211_TXRATE_INVALID: "__NL80211_TXRATE_INVALID",
-	NL80211_TXRATE_LEGACY: "NL80211_TXRATE_LEGACY",
-	NL80211_TXRATE_MCS: "NL80211_TXRATE_MCS",
-	__NL80211_TXRATE_AFTER_LAST: "__NL80211_TXRATE_AFTER_LAST",
+    __NL80211_TXRATE_INVALID: "__NL80211_TXRATE_INVALID",
+    NL80211_TXRATE_LEGACY: "NL80211_TXRATE_LEGACY",
+    NL80211_TXRATE_MCS: "NL80211_TXRATE_MCS",
+    __NL80211_TXRATE_AFTER_LAST: "__NL80211_TXRATE_AFTER_LAST",
 }
 nl80211_band2str = {
-	NL80211_BAND_2GHZ: "NL80211_BAND_2GHZ",
-	NL80211_BAND_5GHZ: "NL80211_BAND_5GHZ",
-	NL80211_BAND_60GHZ: "NL80211_BAND_60GHZ",
+    NL80211_BAND_2GHZ: "NL80211_BAND_2GHZ",
+    NL80211_BAND_5GHZ: "NL80211_BAND_5GHZ",
+    NL80211_BAND_60GHZ: "NL80211_BAND_60GHZ",
 }
 nl80211_ps_state2str = {
-	NL80211_PS_DISABLED: "NL80211_PS_DISABLED",
-	NL80211_PS_ENABLED: "NL80211_PS_ENABLED",
+    NL80211_PS_DISABLED: "NL80211_PS_DISABLED",
+    NL80211_PS_ENABLED: "NL80211_PS_ENABLED",
 }
 nl80211_attr_cqm2str = {
-	__NL80211_ATTR_CQM_INVALID: "__NL80211_ATTR_CQM_INVALID",
-	NL80211_ATTR_CQM_RSSI_THOLD: "NL80211_ATTR_CQM_RSSI_THOLD",
-	NL80211_ATTR_CQM_RSSI_HYST: "NL80211_ATTR_CQM_RSSI_HYST",
-	NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: "NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT",
-	NL80211_ATTR_CQM_PKT_LOSS_EVENT: "NL80211_ATTR_CQM_PKT_LOSS_EVENT",
-	NL80211_ATTR_CQM_TXE_RATE: "NL80211_ATTR_CQM_TXE_RATE",
-	NL80211_ATTR_CQM_TXE_PKTS: "NL80211_ATTR_CQM_TXE_PKTS",
-	NL80211_ATTR_CQM_TXE_INTVL: "NL80211_ATTR_CQM_TXE_INTVL",
-	__NL80211_ATTR_CQM_AFTER_LAST: "__NL80211_ATTR_CQM_AFTER_LAST",
+    __NL80211_ATTR_CQM_INVALID: "__NL80211_ATTR_CQM_INVALID",
+    NL80211_ATTR_CQM_RSSI_THOLD: "NL80211_ATTR_CQM_RSSI_THOLD",
+    NL80211_ATTR_CQM_RSSI_HYST: "NL80211_ATTR_CQM_RSSI_HYST",
+    NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: "NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT",
+    NL80211_ATTR_CQM_PKT_LOSS_EVENT: "NL80211_ATTR_CQM_PKT_LOSS_EVENT",
+    NL80211_ATTR_CQM_TXE_RATE: "NL80211_ATTR_CQM_TXE_RATE",
+    NL80211_ATTR_CQM_TXE_PKTS: "NL80211_ATTR_CQM_TXE_PKTS",
+    NL80211_ATTR_CQM_TXE_INTVL: "NL80211_ATTR_CQM_TXE_INTVL",
+    __NL80211_ATTR_CQM_AFTER_LAST: "__NL80211_ATTR_CQM_AFTER_LAST",
 }
 nl80211_cqm_rssi_threshold_event2str = {
-	NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: "NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW",
-	NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: "NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH",
-	NL80211_CQM_RSSI_BEACON_LOSS_EVENT: "NL80211_CQM_RSSI_BEACON_LOSS_EVENT",
+    NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: "NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW",
+    NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: "NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH",
+    NL80211_CQM_RSSI_BEACON_LOSS_EVENT: "NL80211_CQM_RSSI_BEACON_LOSS_EVENT",
 }
 nl80211_tx_power_setting2str = {
-	NL80211_TX_POWER_AUTOMATIC: "NL80211_TX_POWER_AUTOMATIC",
-	NL80211_TX_POWER_LIMITED: "NL80211_TX_POWER_LIMITED",
-	NL80211_TX_POWER_FIXED: "NL80211_TX_POWER_FIXED",
+    NL80211_TX_POWER_AUTOMATIC: "NL80211_TX_POWER_AUTOMATIC",
+    NL80211_TX_POWER_LIMITED: "NL80211_TX_POWER_LIMITED",
+    NL80211_TX_POWER_FIXED: "NL80211_TX_POWER_FIXED",
 }
 nl80211_wowlan_packet_pattern_attr2str = {
-	__NL80211_WOWLAN_PKTPAT_INVALID: "__NL80211_WOWLAN_PKTPAT_INVALID",
-	NL80211_WOWLAN_PKTPAT_MASK: "NL80211_WOWLAN_PKTPAT_MASK",
-	NL80211_WOWLAN_PKTPAT_PATTERN: "NL80211_WOWLAN_PKTPAT_PATTERN",
-	NL80211_WOWLAN_PKTPAT_OFFSET: "NL80211_WOWLAN_PKTPAT_OFFSET",
-	NUM_NL80211_WOWLAN_PKTPAT: "NUM_NL80211_WOWLAN_PKTPAT",
+    __NL80211_WOWLAN_PKTPAT_INVALID: "__NL80211_WOWLAN_PKTPAT_INVALID",
+    NL80211_WOWLAN_PKTPAT_MASK: "NL80211_WOWLAN_PKTPAT_MASK",
+    NL80211_WOWLAN_PKTPAT_PATTERN: "NL80211_WOWLAN_PKTPAT_PATTERN",
+    NL80211_WOWLAN_PKTPAT_OFFSET: "NL80211_WOWLAN_PKTPAT_OFFSET",
+    NUM_NL80211_WOWLAN_PKTPAT: "NUM_NL80211_WOWLAN_PKTPAT",
 }
 nl80211_wowlan_triggers2str = {
-	__NL80211_WOWLAN_TRIG_INVALID: "__NL80211_WOWLAN_TRIG_INVALID",
-	NL80211_WOWLAN_TRIG_ANY: "NL80211_WOWLAN_TRIG_ANY",
-	NL80211_WOWLAN_TRIG_DISCONNECT: "NL80211_WOWLAN_TRIG_DISCONNECT",
-	NL80211_WOWLAN_TRIG_MAGIC_PKT: "NL80211_WOWLAN_TRIG_MAGIC_PKT",
-	NL80211_WOWLAN_TRIG_PKT_PATTERN: "NL80211_WOWLAN_TRIG_PKT_PATTERN",
-	NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: "NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED",
-	NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: "NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE",
-	NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: "NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST",
-	NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: "NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE",
-	NL80211_WOWLAN_TRIG_RFKILL_RELEASE: "NL80211_WOWLAN_TRIG_RFKILL_RELEASE",
-	NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211",
-	NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN",
-	NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023",
-	NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN",
-	NL80211_WOWLAN_TRIG_TCP_CONNECTION: "NL80211_WOWLAN_TRIG_TCP_CONNECTION",
-	NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH",
-	NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST",
-	NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS",
-	NUM_NL80211_WOWLAN_TRIG: "NUM_NL80211_WOWLAN_TRIG",
+    __NL80211_WOWLAN_TRIG_INVALID: "__NL80211_WOWLAN_TRIG_INVALID",
+    NL80211_WOWLAN_TRIG_ANY: "NL80211_WOWLAN_TRIG_ANY",
+    NL80211_WOWLAN_TRIG_DISCONNECT: "NL80211_WOWLAN_TRIG_DISCONNECT",
+    NL80211_WOWLAN_TRIG_MAGIC_PKT: "NL80211_WOWLAN_TRIG_MAGIC_PKT",
+    NL80211_WOWLAN_TRIG_PKT_PATTERN: "NL80211_WOWLAN_TRIG_PKT_PATTERN",
+    NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: "NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED",
+    NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: "NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE",
+    NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: "NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST",
+    NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: "NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE",
+    NL80211_WOWLAN_TRIG_RFKILL_RELEASE: "NL80211_WOWLAN_TRIG_RFKILL_RELEASE",
+    NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211",
+    NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN",
+    NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023",
+    NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: "NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN",
+    NL80211_WOWLAN_TRIG_TCP_CONNECTION: "NL80211_WOWLAN_TRIG_TCP_CONNECTION",
+    NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH",
+    NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST",
+    NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: "NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS",
+    NUM_NL80211_WOWLAN_TRIG: "NUM_NL80211_WOWLAN_TRIG",
 }
 nl80211_wowlan_tcp_attrs2str = {
-	__NL80211_WOWLAN_TCP_INVALID: "__NL80211_WOWLAN_TCP_INVALID",
-	NL80211_WOWLAN_TCP_SRC_IPV4: "NL80211_WOWLAN_TCP_SRC_IPV4",
-	NL80211_WOWLAN_TCP_DST_IPV4: "NL80211_WOWLAN_TCP_DST_IPV4",
-	NL80211_WOWLAN_TCP_DST_MAC: "NL80211_WOWLAN_TCP_DST_MAC",
-	NL80211_WOWLAN_TCP_SRC_PORT: "NL80211_WOWLAN_TCP_SRC_PORT",
-	NL80211_WOWLAN_TCP_DST_PORT: "NL80211_WOWLAN_TCP_DST_PORT",
-	NL80211_WOWLAN_TCP_DATA_PAYLOAD: "NL80211_WOWLAN_TCP_DATA_PAYLOAD",
-	NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ",
-	NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN",
-	NL80211_WOWLAN_TCP_DATA_INTERVAL: "NL80211_WOWLAN_TCP_DATA_INTERVAL",
-	NL80211_WOWLAN_TCP_WAKE_PAYLOAD: "NL80211_WOWLAN_TCP_WAKE_PAYLOAD",
-	NL80211_WOWLAN_TCP_WAKE_MASK: "NL80211_WOWLAN_TCP_WAKE_MASK",
-	NUM_NL80211_WOWLAN_TCP: "NUM_NL80211_WOWLAN_TCP",
+    __NL80211_WOWLAN_TCP_INVALID: "__NL80211_WOWLAN_TCP_INVALID",
+    NL80211_WOWLAN_TCP_SRC_IPV4: "NL80211_WOWLAN_TCP_SRC_IPV4",
+    NL80211_WOWLAN_TCP_DST_IPV4: "NL80211_WOWLAN_TCP_DST_IPV4",
+    NL80211_WOWLAN_TCP_DST_MAC: "NL80211_WOWLAN_TCP_DST_MAC",
+    NL80211_WOWLAN_TCP_SRC_PORT: "NL80211_WOWLAN_TCP_SRC_PORT",
+    NL80211_WOWLAN_TCP_DST_PORT: "NL80211_WOWLAN_TCP_DST_PORT",
+    NL80211_WOWLAN_TCP_DATA_PAYLOAD: "NL80211_WOWLAN_TCP_DATA_PAYLOAD",
+    NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ",
+    NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: "NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN",
+    NL80211_WOWLAN_TCP_DATA_INTERVAL: "NL80211_WOWLAN_TCP_DATA_INTERVAL",
+    NL80211_WOWLAN_TCP_WAKE_PAYLOAD: "NL80211_WOWLAN_TCP_WAKE_PAYLOAD",
+    NL80211_WOWLAN_TCP_WAKE_MASK: "NL80211_WOWLAN_TCP_WAKE_MASK",
+    NUM_NL80211_WOWLAN_TCP: "NUM_NL80211_WOWLAN_TCP",
 }
 nl80211_iface_limit_attrs2str = {
-	NL80211_IFACE_LIMIT_UNSPEC: "NL80211_IFACE_LIMIT_UNSPEC",
-	NL80211_IFACE_LIMIT_MAX: "NL80211_IFACE_LIMIT_MAX",
-	NL80211_IFACE_LIMIT_TYPES: "NL80211_IFACE_LIMIT_TYPES",
-	NUM_NL80211_IFACE_LIMIT: "NUM_NL80211_IFACE_LIMIT",
+    NL80211_IFACE_LIMIT_UNSPEC: "NL80211_IFACE_LIMIT_UNSPEC",
+    NL80211_IFACE_LIMIT_MAX: "NL80211_IFACE_LIMIT_MAX",
+    NL80211_IFACE_LIMIT_TYPES: "NL80211_IFACE_LIMIT_TYPES",
+    NUM_NL80211_IFACE_LIMIT: "NUM_NL80211_IFACE_LIMIT",
 }
 nl80211_if_combination_attrs2str = {
-	NL80211_IFACE_COMB_UNSPEC: "NL80211_IFACE_COMB_UNSPEC",
-	NL80211_IFACE_COMB_LIMITS: "NL80211_IFACE_COMB_LIMITS",
-	NL80211_IFACE_COMB_MAXNUM: "NL80211_IFACE_COMB_MAXNUM",
-	NL80211_IFACE_COMB_STA_AP_BI_MATCH: "NL80211_IFACE_COMB_STA_AP_BI_MATCH",
-	NL80211_IFACE_COMB_NUM_CHANNELS: "NL80211_IFACE_COMB_NUM_CHANNELS",
-	NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: "NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS",
-	NUM_NL80211_IFACE_COMB: "NUM_NL80211_IFACE_COMB",
+    NL80211_IFACE_COMB_UNSPEC: "NL80211_IFACE_COMB_UNSPEC",
+    NL80211_IFACE_COMB_LIMITS: "NL80211_IFACE_COMB_LIMITS",
+    NL80211_IFACE_COMB_MAXNUM: "NL80211_IFACE_COMB_MAXNUM",
+    NL80211_IFACE_COMB_STA_AP_BI_MATCH: "NL80211_IFACE_COMB_STA_AP_BI_MATCH",
+    NL80211_IFACE_COMB_NUM_CHANNELS: "NL80211_IFACE_COMB_NUM_CHANNELS",
+    NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: "NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS",
+    NUM_NL80211_IFACE_COMB: "NUM_NL80211_IFACE_COMB",
 }
 nl80211_plink_state2str = {
-	NL80211_PLINK_LISTEN: "NL80211_PLINK_LISTEN",
-	NL80211_PLINK_OPN_SNT: "NL80211_PLINK_OPN_SNT",
-	NL80211_PLINK_OPN_RCVD: "NL80211_PLINK_OPN_RCVD",
-	NL80211_PLINK_CNF_RCVD: "NL80211_PLINK_CNF_RCVD",
-	NL80211_PLINK_ESTAB: "NL80211_PLINK_ESTAB",
-	NL80211_PLINK_HOLDING: "NL80211_PLINK_HOLDING",
-	NL80211_PLINK_BLOCKED: "NL80211_PLINK_BLOCKED",
-	NUM_NL80211_PLINK_STATES: "NUM_NL80211_PLINK_STATES",
+    NL80211_PLINK_LISTEN: "NL80211_PLINK_LISTEN",
+    NL80211_PLINK_OPN_SNT: "NL80211_PLINK_OPN_SNT",
+    NL80211_PLINK_OPN_RCVD: "NL80211_PLINK_OPN_RCVD",
+    NL80211_PLINK_CNF_RCVD: "NL80211_PLINK_CNF_RCVD",
+    NL80211_PLINK_ESTAB: "NL80211_PLINK_ESTAB",
+    NL80211_PLINK_HOLDING: "NL80211_PLINK_HOLDING",
+    NL80211_PLINK_BLOCKED: "NL80211_PLINK_BLOCKED",
+    NUM_NL80211_PLINK_STATES: "NUM_NL80211_PLINK_STATES",
 }
 plink_actions2str = {
-	NL80211_PLINK_ACTION_NO_ACTION: "NL80211_PLINK_ACTION_NO_ACTION",
-	NL80211_PLINK_ACTION_OPEN: "NL80211_PLINK_ACTION_OPEN",
-	NL80211_PLINK_ACTION_BLOCK: "NL80211_PLINK_ACTION_BLOCK",
-	NUM_NL80211_PLINK_ACTIONS: "NUM_NL80211_PLINK_ACTIONS",
+    NL80211_PLINK_ACTION_NO_ACTION: "NL80211_PLINK_ACTION_NO_ACTION",
+    NL80211_PLINK_ACTION_OPEN: "NL80211_PLINK_ACTION_OPEN",
+    NL80211_PLINK_ACTION_BLOCK: "NL80211_PLINK_ACTION_BLOCK",
+    NUM_NL80211_PLINK_ACTIONS: "NUM_NL80211_PLINK_ACTIONS",
 }
 nl80211_rekey_data2str = {
-	__NL80211_REKEY_DATA_INVALID: "__NL80211_REKEY_DATA_INVALID",
-	NL80211_REKEY_DATA_KEK: "NL80211_REKEY_DATA_KEK",
-	NL80211_REKEY_DATA_KCK: "NL80211_REKEY_DATA_KCK",
-	NL80211_REKEY_DATA_REPLAY_CTR: "NL80211_REKEY_DATA_REPLAY_CTR",
-	NUM_NL80211_REKEY_DATA: "NUM_NL80211_REKEY_DATA",
+    __NL80211_REKEY_DATA_INVALID: "__NL80211_REKEY_DATA_INVALID",
+    NL80211_REKEY_DATA_KEK: "NL80211_REKEY_DATA_KEK",
+    NL80211_REKEY_DATA_KCK: "NL80211_REKEY_DATA_KCK",
+    NL80211_REKEY_DATA_REPLAY_CTR: "NL80211_REKEY_DATA_REPLAY_CTR",
+    NUM_NL80211_REKEY_DATA: "NUM_NL80211_REKEY_DATA",
 }
 nl80211_hidden_ssid2str = {
-	NL80211_HIDDEN_SSID_NOT_IN_USE: "NL80211_HIDDEN_SSID_NOT_IN_USE",
-	NL80211_HIDDEN_SSID_ZERO_LEN: "NL80211_HIDDEN_SSID_ZERO_LEN",
-	NL80211_HIDDEN_SSID_ZERO_CONTENTS: "NL80211_HIDDEN_SSID_ZERO_CONTENTS",
+    NL80211_HIDDEN_SSID_NOT_IN_USE: "NL80211_HIDDEN_SSID_NOT_IN_USE",
+    NL80211_HIDDEN_SSID_ZERO_LEN: "NL80211_HIDDEN_SSID_ZERO_LEN",
+    NL80211_HIDDEN_SSID_ZERO_CONTENTS: "NL80211_HIDDEN_SSID_ZERO_CONTENTS",
 }
 nl80211_sta_wme_attr2str = {
-	__NL80211_STA_WME_INVALID: "__NL80211_STA_WME_INVALID",
-	NL80211_STA_WME_UAPSD_QUEUES: "NL80211_STA_WME_UAPSD_QUEUES",
-	NL80211_STA_WME_MAX_SP: "NL80211_STA_WME_MAX_SP",
-	__NL80211_STA_WME_AFTER_LAST: "__NL80211_STA_WME_AFTER_LAST",
+    __NL80211_STA_WME_INVALID: "__NL80211_STA_WME_INVALID",
+    NL80211_STA_WME_UAPSD_QUEUES: "NL80211_STA_WME_UAPSD_QUEUES",
+    NL80211_STA_WME_MAX_SP: "NL80211_STA_WME_MAX_SP",
+    __NL80211_STA_WME_AFTER_LAST: "__NL80211_STA_WME_AFTER_LAST",
 }
 nl80211_pmksa_candidate_attr2str = {
-	__NL80211_PMKSA_CANDIDATE_INVALID: "__NL80211_PMKSA_CANDIDATE_INVALID",
-	NL80211_PMKSA_CANDIDATE_INDEX: "NL80211_PMKSA_CANDIDATE_INDEX",
-	NL80211_PMKSA_CANDIDATE_BSSID: "NL80211_PMKSA_CANDIDATE_BSSID",
-	NL80211_PMKSA_CANDIDATE_PREAUTH: "NL80211_PMKSA_CANDIDATE_PREAUTH",
-	NUM_NL80211_PMKSA_CANDIDATE: "NUM_NL80211_PMKSA_CANDIDATE",
+    __NL80211_PMKSA_CANDIDATE_INVALID: "__NL80211_PMKSA_CANDIDATE_INVALID",
+    NL80211_PMKSA_CANDIDATE_INDEX: "NL80211_PMKSA_CANDIDATE_INDEX",
+    NL80211_PMKSA_CANDIDATE_BSSID: "NL80211_PMKSA_CANDIDATE_BSSID",
+    NL80211_PMKSA_CANDIDATE_PREAUTH: "NL80211_PMKSA_CANDIDATE_PREAUTH",
+    NUM_NL80211_PMKSA_CANDIDATE: "NUM_NL80211_PMKSA_CANDIDATE",
 }
 nl80211_tdls_operation2str = {
-	NL80211_TDLS_DISCOVERY_REQ: "NL80211_TDLS_DISCOVERY_REQ",
-	NL80211_TDLS_SETUP: "NL80211_TDLS_SETUP",
-	NL80211_TDLS_TEARDOWN: "NL80211_TDLS_TEARDOWN",
-	NL80211_TDLS_ENABLE_LINK: "NL80211_TDLS_ENABLE_LINK",
-	NL80211_TDLS_DISABLE_LINK: "NL80211_TDLS_DISABLE_LINK",
+    NL80211_TDLS_DISCOVERY_REQ: "NL80211_TDLS_DISCOVERY_REQ",
+    NL80211_TDLS_SETUP: "NL80211_TDLS_SETUP",
+    NL80211_TDLS_TEARDOWN: "NL80211_TDLS_TEARDOWN",
+    NL80211_TDLS_ENABLE_LINK: "NL80211_TDLS_ENABLE_LINK",
+    NL80211_TDLS_DISABLE_LINK: "NL80211_TDLS_DISABLE_LINK",
 }
 nl80211_feature_flags2str = {
-	NL80211_FEATURE_SK_TX_STATUS: "NL80211_FEATURE_SK_TX_STATUS",
-	NL80211_FEATURE_HT_IBSS: "NL80211_FEATURE_HT_IBSS",
-	NL80211_FEATURE_INACTIVITY_TIMER: "NL80211_FEATURE_INACTIVITY_TIMER",
-	NL80211_FEATURE_CELL_BASE_REG_HINTS: "NL80211_FEATURE_CELL_BASE_REG_HINTS",
-	NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: "NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL",
-	NL80211_FEATURE_SAE: "NL80211_FEATURE_SAE",
-	NL80211_FEATURE_LOW_PRIORITY_SCAN: "NL80211_FEATURE_LOW_PRIORITY_SCAN",
-	NL80211_FEATURE_SCAN_FLUSH: "NL80211_FEATURE_SCAN_FLUSH",
-	NL80211_FEATURE_AP_SCAN: "NL80211_FEATURE_AP_SCAN",
-	NL80211_FEATURE_VIF_TXPOWER: "NL80211_FEATURE_VIF_TXPOWER",
-	NL80211_FEATURE_NEED_OBSS_SCAN: "NL80211_FEATURE_NEED_OBSS_SCAN",
-	NL80211_FEATURE_P2P_GO_CTWIN: "NL80211_FEATURE_P2P_GO_CTWIN",
-	NL80211_FEATURE_P2P_GO_OPPPS: "NL80211_FEATURE_P2P_GO_OPPPS",
-	NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: "NL80211_FEATURE_ADVERTISE_CHAN_LIMITS",
-	NL80211_FEATURE_FULL_AP_CLIENT_STATE: "NL80211_FEATURE_FULL_AP_CLIENT_STATE",
-	NL80211_FEATURE_USERSPACE_MPM: "NL80211_FEATURE_USERSPACE_MPM",
-	NL80211_FEATURE_ACTIVE_MONITOR: "NL80211_FEATURE_ACTIVE_MONITOR",
+    NL80211_FEATURE_SK_TX_STATUS: "NL80211_FEATURE_SK_TX_STATUS",
+    NL80211_FEATURE_HT_IBSS: "NL80211_FEATURE_HT_IBSS",
+    NL80211_FEATURE_INACTIVITY_TIMER: "NL80211_FEATURE_INACTIVITY_TIMER",
+    NL80211_FEATURE_CELL_BASE_REG_HINTS: "NL80211_FEATURE_CELL_BASE_REG_HINTS",
+    NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: "NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL",
+    NL80211_FEATURE_SAE: "NL80211_FEATURE_SAE",
+    NL80211_FEATURE_LOW_PRIORITY_SCAN: "NL80211_FEATURE_LOW_PRIORITY_SCAN",
+    NL80211_FEATURE_SCAN_FLUSH: "NL80211_FEATURE_SCAN_FLUSH",
+    NL80211_FEATURE_AP_SCAN: "NL80211_FEATURE_AP_SCAN",
+    NL80211_FEATURE_VIF_TXPOWER: "NL80211_FEATURE_VIF_TXPOWER",
+    NL80211_FEATURE_NEED_OBSS_SCAN: "NL80211_FEATURE_NEED_OBSS_SCAN",
+    NL80211_FEATURE_P2P_GO_CTWIN: "NL80211_FEATURE_P2P_GO_CTWIN",
+    NL80211_FEATURE_P2P_GO_OPPPS: "NL80211_FEATURE_P2P_GO_OPPPS",
+    NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: "NL80211_FEATURE_ADVERTISE_CHAN_LIMITS",
+    NL80211_FEATURE_FULL_AP_CLIENT_STATE: "NL80211_FEATURE_FULL_AP_CLIENT_STATE",
+    NL80211_FEATURE_USERSPACE_MPM: "NL80211_FEATURE_USERSPACE_MPM",
+    NL80211_FEATURE_ACTIVE_MONITOR: "NL80211_FEATURE_ACTIVE_MONITOR",
 }
 nl80211_probe_resp_offload_support_attr2str = {
-	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS",
-	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2",
-	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P",
-	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U",
+    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS",
+    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2",
+    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P",
+    NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: "NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U",
 }
 nl80211_connect_failed_reason2str = {
-	NL80211_CONN_FAIL_MAX_CLIENTS: "NL80211_CONN_FAIL_MAX_CLIENTS",
-	NL80211_CONN_FAIL_BLOCKED_CLIENT: "NL80211_CONN_FAIL_BLOCKED_CLIENT",
+    NL80211_CONN_FAIL_MAX_CLIENTS: "NL80211_CONN_FAIL_MAX_CLIENTS",
+    NL80211_CONN_FAIL_BLOCKED_CLIENT: "NL80211_CONN_FAIL_BLOCKED_CLIENT",
 }
 nl80211_scan_flags2str = {
-	NL80211_SCAN_FLAG_LOW_PRIORITY: "NL80211_SCAN_FLAG_LOW_PRIORITY",
-	NL80211_SCAN_FLAG_FLUSH: "NL80211_SCAN_FLAG_FLUSH",
-	NL80211_SCAN_FLAG_AP: "NL80211_SCAN_FLAG_AP",
+    NL80211_SCAN_FLAG_LOW_PRIORITY: "NL80211_SCAN_FLAG_LOW_PRIORITY",
+    NL80211_SCAN_FLAG_FLUSH: "NL80211_SCAN_FLAG_FLUSH",
+    NL80211_SCAN_FLAG_AP: "NL80211_SCAN_FLAG_AP",
 }
 nl80211_acl_policy2str = {
-	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: "NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED",
-	NL80211_ACL_POLICY_DENY_UNLESS_LISTED: "NL80211_ACL_POLICY_DENY_UNLESS_LISTED",
+    NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: "NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED",
+    NL80211_ACL_POLICY_DENY_UNLESS_LISTED: "NL80211_ACL_POLICY_DENY_UNLESS_LISTED",
 }
 nl80211_radar_event2str = {
-	NL80211_RADAR_DETECTED: "NL80211_RADAR_DETECTED",
-	NL80211_RADAR_CAC_FINISHED: "NL80211_RADAR_CAC_FINISHED",
-	NL80211_RADAR_CAC_ABORTED: "NL80211_RADAR_CAC_ABORTED",
-	NL80211_RADAR_NOP_FINISHED: "NL80211_RADAR_NOP_FINISHED",
+    NL80211_RADAR_DETECTED: "NL80211_RADAR_DETECTED",
+    NL80211_RADAR_CAC_FINISHED: "NL80211_RADAR_CAC_FINISHED",
+    NL80211_RADAR_CAC_ABORTED: "NL80211_RADAR_CAC_ABORTED",
+    NL80211_RADAR_NOP_FINISHED: "NL80211_RADAR_NOP_FINISHED",
 }
 nl80211_dfs_state2str = {
-	NL80211_DFS_USABLE: "NL80211_DFS_USABLE",
-	NL80211_DFS_UNAVAILABLE: "NL80211_DFS_UNAVAILABLE",
-	NL80211_DFS_AVAILABLE: "NL80211_DFS_AVAILABLE",
+    NL80211_DFS_USABLE: "NL80211_DFS_USABLE",
+    NL80211_DFS_UNAVAILABLE: "NL80211_DFS_UNAVAILABLE",
+    NL80211_DFS_AVAILABLE: "NL80211_DFS_AVAILABLE",
 }
 nl80211_protocol_features2str = {
-	NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: "NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP",
+    NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: "NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP",
 }
 nl80211_crit_proto_id2str = {
-	NL80211_CRIT_PROTO_UNSPEC: "NL80211_CRIT_PROTO_UNSPEC",
-	NL80211_CRIT_PROTO_DHCP: "NL80211_CRIT_PROTO_DHCP",
-	NL80211_CRIT_PROTO_EAPOL: "NL80211_CRIT_PROTO_EAPOL",
-	NL80211_CRIT_PROTO_APIPA: "NL80211_CRIT_PROTO_APIPA",
-	NUM_NL80211_CRIT_PROTO: "NUM_NL80211_CRIT_PROTO",
+    NL80211_CRIT_PROTO_UNSPEC: "NL80211_CRIT_PROTO_UNSPEC",
+    NL80211_CRIT_PROTO_DHCP: "NL80211_CRIT_PROTO_DHCP",
+    NL80211_CRIT_PROTO_EAPOL: "NL80211_CRIT_PROTO_EAPOL",
+    NL80211_CRIT_PROTO_APIPA: "NL80211_CRIT_PROTO_APIPA",
+    NUM_NL80211_CRIT_PROTO: "NUM_NL80211_CRIT_PROTO",
 }
diff --git a/python/examples/wiphy.py b/python/examples/wiphy.py
index 6601883..572e95a 100644
--- a/python/examples/wiphy.py
+++ b/python/examples/wiphy.py
@@ -5,138 +5,157 @@
 import sys
 import traceback
 
+
 class test_class:
-	def __init__(self):
-		self.done = 1
+    def __init__(self):
+        self.done = 1
+
 
 def freq_to_ch(freq):
-	if freq == 2484:
-		return 14
+    if freq == 2484:
+        return 14
 
-	if freq < 2484:
-		return (freq - 2407) / 5
+    if freq < 2484:
+        return (freq - 2407) / 5
 
-	# FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2)
-	if freq < 45000:
-		return freq/5 - 1000
+    # FIXME: dot11ChannelStartingFactor (802.11-2007 17.3.8.3.2)
+    if freq < 45000:
+        return freq / 5 - 1000
 
-	if freq >= 58320 and freq <= 64800:
-		return (freq - 56160) / 2160
+    if freq >= 58320 and freq <= 64800:
+        return (freq - 56160) / 2160
 
-	return 0
+    return 0
+
 
 def handle_freq(attr, pol):
-	e, fattr = nl.py_nla_parse_nested(nl80211.NL80211_FREQUENCY_ATTR_MAX, attr, pol)
-	if nl80211.NL80211_FREQUENCY_ATTR_FREQ in fattr:
-		freq = nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_FREQ])
-		sys.stdout.write("\t\tfreq %d MHz [%d]" % (freq, freq_to_ch(freq)))
-	if nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER in fattr and not (nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr):
-		sys.stdout.write(" (%.1f dBm)" % (0.01 * nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER])))
-	if nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr:
-		sys.stdout.write(" (disabled)")
-	sys.stdout.write("\n")
+    e, fattr = nl.py_nla_parse_nested(nl80211.NL80211_FREQUENCY_ATTR_MAX, attr, pol)
+    if nl80211.NL80211_FREQUENCY_ATTR_FREQ in fattr:
+        freq = nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_FREQ])
+        sys.stdout.write("\t\tfreq %d MHz [%d]" % (freq, freq_to_ch(freq)))
+    if nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER in fattr and not (
+        nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr
+    ):
+        sys.stdout.write(
+            " (%.1f dBm)"
+            % (
+                0.01
+                * nl.nla_get_u32(fattr[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER])
+            )
+        )
+    if nl80211.NL80211_FREQUENCY_ATTR_DISABLED in fattr:
+        sys.stdout.write(" (disabled)")
+    sys.stdout.write("\n")
+
 
 def handle_band(attr, fpol):
-	e, battr = nl.py_nla_parse_nested(nl80211.NL80211_BAND_ATTR_MAX, attr, None)
-	print("\tband %d:" % nl.nla_type(attr))
-	if nl80211.NL80211_BAND_ATTR_FREQS in battr:
-		for fattr in nl.nla_get_nested(battr[nl80211.NL80211_BAND_ATTR_FREQS]):
-			handle_freq(fattr, fpol)
+    e, battr = nl.py_nla_parse_nested(nl80211.NL80211_BAND_ATTR_MAX, attr, None)
+    print("\tband %d:" % nl.nla_type(attr))
+    if nl80211.NL80211_BAND_ATTR_FREQS in battr:
+        for fattr in nl.nla_get_nested(battr[nl80211.NL80211_BAND_ATTR_FREQS]):
+            handle_freq(fattr, fpol)
+
 
 def cipher_name(suite):
-	suite_val = '%02x%02x%02x%02x' % tuple(reversed(suite))
-	if suite_val == '000fac01':
-		return "WEP40 (00-0f-ac:1)"
-	elif suite_val == '000fac05':
-		return "WEP104 (00-0f-ac:5)"
-	elif suite_val == '000fac02':
-		return "TKIP (00-0f-ac:2)"
-	elif suite_val == '000fac04':
-		return "CCMP (00-0f-ac:4)"
-	elif suite_val == '000fac06':
-		return "CMAC (00-0f-ac:6)"
-	elif suite_val == '000fac08':
-		return "GCMP (00-0f-ac:8)"
-	elif suite_val == '00147201':
-		return "WPI-SMS4 (00-14-72:1)"
-	else:
-		return suite_val
+    suite_val = "%02x%02x%02x%02x" % tuple(reversed(suite))
+    if suite_val == "000fac01":
+        return "WEP40 (00-0f-ac:1)"
+    elif suite_val == "000fac05":
+        return "WEP104 (00-0f-ac:5)"
+    elif suite_val == "000fac02":
+        return "TKIP (00-0f-ac:2)"
+    elif suite_val == "000fac04":
+        return "CCMP (00-0f-ac:4)"
+    elif suite_val == "000fac06":
+        return "CMAC (00-0f-ac:6)"
+    elif suite_val == "000fac08":
+        return "GCMP (00-0f-ac:8)"
+    elif suite_val == "00147201":
+        return "WPI-SMS4 (00-14-72:1)"
+    else:
+        return suite_val
+
 
 def msg_handler(m, a):
-	try:
-		e, attr = genl.py_genlmsg_parse(nl.nlmsg_hdr(m), 0,
-						nl80211.NL80211_ATTR_MAX, None)
-		if nl80211.NL80211_ATTR_WIPHY_NAME in attr:
-			print('wiphy %s' % nl.nla_get_string(attr[nl80211.NL80211_ATTR_WIPHY_NAME]))
-		if nl80211.NL80211_ATTR_WIPHY_BANDS in attr:
-			fpol = nl.nla_policy_array(nl80211.NL80211_FREQUENCY_ATTR_MAX + 1)
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_FREQ].type = nl.NLA_U32
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_DISABLED].type = nl.NLA_FLAG
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_PASSIVE_SCAN].type = nl.NLA_FLAG
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_NO_IBSS].type = nl.NLA_FLAG
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_RADAR].type = nl.NLA_FLAG
-			fpol[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = nl.NLA_U32
+    try:
+        e, attr = genl.py_genlmsg_parse(
+            nl.nlmsg_hdr(m), 0, nl80211.NL80211_ATTR_MAX, None
+        )
+        if nl80211.NL80211_ATTR_WIPHY_NAME in attr:
+            print("wiphy %s" % nl.nla_get_string(attr[nl80211.NL80211_ATTR_WIPHY_NAME]))
+        if nl80211.NL80211_ATTR_WIPHY_BANDS in attr:
+            fpol = nl.nla_policy_array(nl80211.NL80211_FREQUENCY_ATTR_MAX + 1)
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_FREQ].type = nl.NLA_U32
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_DISABLED].type = nl.NLA_FLAG
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_PASSIVE_SCAN].type = nl.NLA_FLAG
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_NO_IBSS].type = nl.NLA_FLAG
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_RADAR].type = nl.NLA_FLAG
+            fpol[nl80211.NL80211_FREQUENCY_ATTR_MAX_TX_POWER].type = nl.NLA_U32
 
-			nattrs = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_WIPHY_BANDS])
-			for nattr in nattrs:
-				handle_band(nattr, fpol)
-		if nl80211.NL80211_ATTR_CIPHER_SUITES in attr:
-			ciphers = nl.nla_data(attr[nl80211.NL80211_ATTR_CIPHER_SUITES])
-			num = len(ciphers) / 4
-			if num > 0:
-				print("\tSupported Ciphers:")
-				for i in range(0, num, 4):
-					print("\t\t* %s" % cipher_name(ciphers[i:i+4]))
-		if nl80211.NL80211_ATTR_SUPPORTED_IFTYPES in attr:
-			print("\tSupported interface modes:")
-			ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SUPPORTED_IFTYPES])
-			for nl_mode in ifattr:
-				print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
-		if nl80211.NL80211_ATTR_SOFTWARE_IFTYPES in attr:
-			print("\tsoftware interface modes (can always be added):")
-			ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SOFTWARE_IFTYPES])
-			for nl_mode in ifattr:
-				print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
-		return nl.NL_SKIP
-	except Exception as e:
-		(t,v,tb) = sys.exc_info()
-		print(v.message)
-		traceback.print_tb(tb)
+            nattrs = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_WIPHY_BANDS])
+            for nattr in nattrs:
+                handle_band(nattr, fpol)
+        if nl80211.NL80211_ATTR_CIPHER_SUITES in attr:
+            ciphers = nl.nla_data(attr[nl80211.NL80211_ATTR_CIPHER_SUITES])
+            num = len(ciphers) / 4
+            if num > 0:
+                print("\tSupported Ciphers:")
+                for i in range(0, num, 4):
+                    print("\t\t* %s" % cipher_name(ciphers[i : i + 4]))
+        if nl80211.NL80211_ATTR_SUPPORTED_IFTYPES in attr:
+            print("\tSupported interface modes:")
+            ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SUPPORTED_IFTYPES])
+            for nl_mode in ifattr:
+                print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
+        if nl80211.NL80211_ATTR_SOFTWARE_IFTYPES in attr:
+            print("\tsoftware interface modes (can always be added):")
+            ifattr = nl.nla_get_nested(attr[nl80211.NL80211_ATTR_SOFTWARE_IFTYPES])
+            for nl_mode in ifattr:
+                print("\t\t* %s" % nl80211.nl80211_iftype2str[nl.nla_type(nl_mode)])
+        return nl.NL_SKIP
+    except Exception:
+        (t, v, tb) = sys.exc_info()
+        print(v.message)
+        traceback.print_tb(tb)
+
 
 def error_handler(err, a):
-	a.done = err.error
-	return nl.NL_STOP
+    a.done = err.error
+    return nl.NL_STOP
+
 
 def finish_handler(m, a):
-	return nl.NL_SKIP
+    return nl.NL_SKIP
+
 
 def ack_handler(m, a):
-	a.done = 0
-	return nl.NL_STOP
+    a.done = 0
+    return nl.NL_STOP
+
 
 try:
-	cbd = test_class()
-	tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT)
-	rx_cb = nl.nl_cb_clone(tx_cb)
-	s = nl.nl_socket_alloc_cb(tx_cb)
-	nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd)
-	nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd)
+    cbd = test_class()
+    tx_cb = nl.nl_cb_alloc(nl.NL_CB_DEFAULT)
+    rx_cb = nl.nl_cb_clone(tx_cb)
+    s = nl.nl_socket_alloc_cb(tx_cb)
+    nl.py_nl_cb_err(rx_cb, nl.NL_CB_CUSTOM, error_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_FINISH, nl.NL_CB_CUSTOM, finish_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_ACK, nl.NL_CB_CUSTOM, ack_handler, cbd)
+    nl.py_nl_cb_set(rx_cb, nl.NL_CB_VALID, nl.NL_CB_CUSTOM, msg_handler, cbd)
 
-	genl.genl_connect(s)
-	family = genl.genl_ctrl_resolve(s, 'nl80211')
-	m = nl.nlmsg_alloc()
-	genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_WIPHY, 0)
-	nl.nla_put_u32(m, nl80211.NL80211_ATTR_WIPHY, 7)
+    genl.genl_connect(s)
+    family = genl.genl_ctrl_resolve(s, "nl80211")
+    m = nl.nlmsg_alloc()
+    genl.genlmsg_put(m, 0, 0, family, 0, 0, nl80211.NL80211_CMD_GET_WIPHY, 0)
+    nl.nla_put_u32(m, nl80211.NL80211_ATTR_WIPHY, 7)
 
-	err = nl.nl_send_auto_complete(s, m)
-	if err < 0:
-		nl.nlmsg_free(m)
+    err = nl.nl_send_auto_complete(s, m)
+    if err < 0:
+        nl.nlmsg_free(m)
 
-	while cbd.done > 0 and not err < 0:
-		err = nl.nl_recvmsgs(s, rx_cb)
-except Exception as e:
-	(t, v, tb) = sys.exc_info()
-	print(v.message)
-	traceback.print_tb(tb)
+    while cbd.done > 0 and not err < 0:
+        err = nl.nl_recvmsgs(s, rx_cb)
+except Exception:
+    (t, v, tb) = sys.exc_info()
+    print(v.message)
+    traceback.print_tb(tb)
diff --git a/python/netlink/core.py b/python/netlink/core.py
index 1a8ea8f..b994a73 100644
--- a/python/netlink/core.py
+++ b/python/netlink/core.py
@@ -30,23 +30,22 @@
 from __future__ import absolute_import
 
 
-
 from . import capi
 import sys
 import socket
 
 __all__ = [
-    'Socket',
-    'Message',
-    'Callback',
-    'DumpParams',
-    'Object',
-    'Cache',
-    'KernelError',
-    'NetlinkError',
+    "Socket",
+    "Message",
+    "Callback",
+    "DumpParams",
+    "Object",
+    "Cache",
+    "KernelError",
+    "NetlinkError",
 ]
 
-__version__ = '0.1'
+__version__ = "0.1"
 
 # netlink protocols
 NETLINK_ROUTE = 0
@@ -92,6 +91,7 @@
 NLM_F_CREATE = 0x400
 NLM_F_APPEND = 0x800
 
+
 class NetlinkError(Exception):
     def __init__(self, error):
         self._error = error
@@ -100,16 +100,19 @@
     def __str__(self):
         return self._msg
 
+
 class KernelError(NetlinkError):
     def __str__(self):
-        return 'Kernel returned: {0}'.format(self._msg)
+        return "Kernel returned: {0}".format(self._msg)
+
 
 class ImmutableError(NetlinkError):
     def __init__(self, msg):
         self._msg = msg
 
     def __str__(self):
-        return 'Immutable attribute: {0}'.format(self._msg)
+        return "Immutable attribute: {0}".format(self._msg)
+
 
 class Message(object):
     """Netlink message"""
@@ -121,7 +124,7 @@
             self._msg = capi.nlmsg_alloc_size(size)
 
         if self._msg is None:
-            raise Exception('Message allocation returned NULL')
+            raise Exception("Message allocation returned NULL")
 
     def __del__(self):
         capi.nlmsg_free(self._msg)
@@ -156,6 +159,7 @@
     def send(self, sock):
         sock.send(self)
 
+
 class Callback(object):
     """Netlink callback"""
 
@@ -180,25 +184,26 @@
     def clone(self):
         return Callback(self)
 
+
 class Socket(object):
     """Netlink socket"""
 
     def __init__(self, cb=None):
         if isinstance(cb, Callback):
             self._sock = capi.nl_socket_alloc_cb(cb._cb)
-        elif cb == None:
+        elif cb is None:
             self._sock = capi.nl_socket_alloc()
         else:
-            raise Exception('\'cb\' parameter has wrong type')
+            raise Exception("'cb' parameter has wrong type")
 
         if self._sock is None:
-            raise Exception('NULL pointer returned while allocating socket')
+            raise Exception("NULL pointer returned while allocating socket")
 
     def __del__(self):
         capi.nl_socket_free(self._sock)
 
     def __str__(self):
-        return 'nlsock<{0}>'.format(self.local_port)
+        return "nlsock<{0}>".format(self.local_port)
 
     @property
     def local_port(self):
@@ -237,27 +242,29 @@
     def sendto(self, buf):
         ret = capi.nl_sendto(self._sock, buf, len(buf))
         if ret < 0:
-            raise Exception('Failed to send')
+            raise Exception("Failed to send")
         else:
             return ret
 
     def send_auto_complete(self, msg):
         if not isinstance(msg, Message):
-            raise Exception('must provide Message instance')
+            raise Exception("must provide Message instance")
         ret = capi.nl_send_auto_complete(self._sock, msg._msg)
         if ret < 0:
-            raise Exception('send_auto_complete failed: ret=%d' % ret)
+            raise Exception("send_auto_complete failed: ret=%d" % ret)
         return ret
 
     def recvmsgs(self, recv_cb):
         if not isinstance(recv_cb, Callback):
-            raise Exception('must provide Callback instance')
+            raise Exception("must provide Callback instance")
         ret = capi.nl_recvmsgs(self._sock, recv_cb._cb)
         if ret < 0:
-            raise Exception('recvmsg failed: ret=%d' % ret)
+            raise Exception("recvmsg failed: ret=%d" % ret)
+
 
 _sockets = {}
 
+
 def lookup_socket(protocol):
     try:
         sock = _sockets[protocol]
@@ -268,13 +275,14 @@
 
     return sock
 
+
 class DumpParams(object):
     """Dumping parameters"""
 
     def __init__(self, type_=NL_DUMP_LINE):
         self._dp = capi.alloc_dump_params()
         if not self._dp:
-            raise Exception('Unable to allocate struct nl_dump_params')
+            raise Exception("Unable to allocate struct nl_dump_params")
 
         self._dp.dp_type = type_
 
@@ -297,9 +305,11 @@
     def prefix(self, value):
         self._dp.dp_prefix = value
 
+
 # underscore this to make sure it is deleted first upon module deletion
 _defaultDumpParams = DumpParams(NL_DUMP_LINE)
 
+
 class Object(object):
     """Cacheable object (base class)"""
 
@@ -325,7 +335,7 @@
         capi.nl_object_put(self._nl_object)
 
     def __str__(self):
-        if hasattr(self, 'format'):
+        if hasattr(self, "format"):
             return self.format()
         else:
             return capi.nl_object_dump_buf(self._nl_object, 4096).rstrip()
@@ -368,10 +378,10 @@
             self._modules.append(ret)
 
     def _module_brief(self):
-        ret = ''
+        ret = ""
 
         for module in self._modules:
-            if hasattr(module, 'brief'):
+            if hasattr(module, "brief"):
                 ret += module.brief()
 
         return ret
@@ -383,7 +393,6 @@
 
         capi.nl_object_dump(self._nl_object, params._dp)
 
-
     @property
     def mark(self):
         return bool(capi.nl_object_is_marked(self._nl_object))
@@ -412,10 +421,10 @@
     # accessing properties of subclass/subtypes (e.g. link.vlan.id)
     def _resolve(self, attr):
         obj = self
-        l = attr.split('.')
-        while len(l) > 1:
-            obj = getattr(obj, l.pop(0))
-        return (obj, l.pop(0))
+        lst = attr.split(".")
+        while len(lst) > 1:
+            obj = getattr(obj, lst.pop(0))
+        return (obj, lst.pop(0))
 
     def _setattr(self, attr, val):
         obj, attr = self._resolve(attr)
@@ -425,6 +434,7 @@
         obj, attr = self._resolve(attr)
         return hasattr(obj, attr)
 
+
 class ObjIterator(object):
     def __init__(self, cache, obj):
         self._cache = cache
@@ -480,8 +490,10 @@
     def get_next(self):
         return capi.nl_cache_get_prev(self._nl_object)
 
+
 class Cache(object):
     """Collection of netlink objects"""
+
     def __init__(self):
         if self.__class__ is Cache:
             raise NotImplementedError()
@@ -597,8 +609,11 @@
         """
         capi.nl_cache_mngt_unprovide(self._nl_cache)
 
+
 # Cache Manager (Work in Progress)
 NL_AUTO_PROVIDE = 1
+
+
 class CacheManager(object):
     def __init__(self, protocol, flags=None):
 
@@ -620,6 +635,7 @@
     def add(self, name):
         capi.cache_mngr_add(self._mngr, name, None, None)
 
+
 class AddressFamily(object):
     """Address family representation
 
@@ -632,11 +648,12 @@
     print int(af)   # => 10 (numeric representation)
     print repr(af)  # => AddressFamily('inet6')
     """
+
     def __init__(self, family=socket.AF_UNSPEC):
         if isinstance(family, str):
             family = capi.nl_str2af(family)
             if family < 0:
-                raise ValueError('Unknown family name')
+                raise ValueError("Unknown family name")
         elif not isinstance(family, int):
             raise TypeError()
 
@@ -649,7 +666,7 @@
         return self._family
 
     def __repr__(self):
-        return 'AddressFamily({0!r})'.format(str(self))
+        return "AddressFamily({0!r})".format(str(self))
 
 
 class AbstractAddress(object):
@@ -667,15 +684,16 @@
 
 
     """
+
     def __init__(self, addr):
         self._nl_addr = None
 
         if isinstance(addr, str):
             # returns None on success I guess
-            # TO CORRECT 
+            # TO CORRECT
             addr = capi.addr_parse(addr, socket.AF_UNSPEC)
             if addr is None:
-                raise ValueError('Invalid address format')
+                raise ValueError("Invalid address format")
         elif addr:
             capi.nl_addr_get(addr)
 
@@ -722,7 +740,7 @@
         if self._nl_addr:
             return capi.nl_addr2str(self._nl_addr, 64)[0]
         else:
-            return 'none'
+            return "none"
 
     @property
     def shared(self):
@@ -773,6 +791,7 @@
 #   fmt = func (formatting function)
 #   title = string
 
+
 def nlattr(**kwds):
     """netlink object attribute decorator
 
@@ -790,4 +809,5 @@
     def wrap_fn(func):
         func.formatinfo = kwds
         return func
+
     return wrap_fn
diff --git a/python/netlink/fixes.h b/python/netlink/fixes.h
deleted file mode 100644
index 9a6118b..0000000
--- a/python/netlink/fixes.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <stdint.h>
diff --git a/python/netlink/route/address.py b/python/netlink/route/address.py
index cab2a97..541f428 100644
--- a/python/netlink/route/address.py
+++ b/python/netlink/route/address.py
@@ -8,23 +8,22 @@
 from __future__ import absolute_import
 
 
-__version__ = '1.0'
-__all__ = [
-    'AddressCache',
-    'Address']
+__version__ = "1.0"
+__all__ = ["AddressCache", "Address"]
 
 import datetime
 from .. import core as netlink
-from .  import capi as capi
-from .  import link as Link
+from . import capi as capi
+from . import link as Link
 from .. import util as util
 
+
 class AddressCache(netlink.Cache):
     """Cache containing network addresses"""
 
     def __init__(self, cache=None):
         if not cache:
-            cache = self._alloc_cache_name('route/addr')
+            cache = self._alloc_cache_name("route/addr")
 
         self._protocol = netlink.NETLINK_ROUTE
         self._nl_cache = cache
@@ -38,8 +37,7 @@
         if type(local) is str:
             local = netlink.AbstractAddress(local)
 
-        addr = capi.rtnl_addr_get(self._nl_cache, ifindex,
-                      local._nl_addr)
+        addr = capi.rtnl_addr_get(self._nl_cache, ifindex, local._nl_addr)
         if addr is None:
             raise KeyError()
 
@@ -53,11 +51,12 @@
     def _new_cache(cache):
         return AddressCache(cache=cache)
 
+
 class Address(netlink.Object):
     """Network address"""
 
     def __init__(self, obj=None):
-        netlink.Object.__init__(self, 'route/addr', 'address', obj)
+        netlink.Object.__init__(self, "route/addr", "address", obj)
         self._rtnl_addr = self._obj2type(self._nl_object)
 
     @classmethod
@@ -148,13 +147,13 @@
         addr.flags = [ '+xxx', '-yyy' ] # list operation
         """
         flags = capi.rtnl_addr_get_flags(self._rtnl_addr)
-        return capi.rtnl_addr_flags2str(flags, 256)[0].split(',')
+        return capi.rtnl_addr_flags2str(flags, 256)[0].split(",")
 
     def _set_flag(self, flag):
-        if flag.startswith('-'):
+        if flag.startswith("-"):
             i = capi.rtnl_addr_str2flags(flag[1:])
             capi.rtnl_addr_unset_flags(self._rtnl_addr, i)
-        elif flag.startswith('+'):
+        elif flag.startswith("+"):
             i = capi.rtnl_addr_str2flags(flag[1:])
             capi.rtnl_addr_set_flags(self._rtnl_addr, i)
         else:
@@ -249,7 +248,7 @@
         try:
             a = netlink.AbstractAddress(value)
         except ValueError as err:
-            raise AttributeError('multicast', err)
+            raise AttributeError("multicast", err)
 
         capi.rtnl_addr_set_multicast(self._rtnl_addr, a._nl_addr)
 
@@ -298,14 +297,14 @@
     def create_time(self):
         """Creation time"""
         hsec = capi.rtnl_addr_get_create_time(self._rtnl_addr)
-        return datetime.timedelta(milliseconds=10*hsec)
+        return datetime.timedelta(milliseconds=10 * hsec)
 
     @property
     @netlink.nlattr(type=int, immutable=True, fmt=util.num)
     def last_update(self):
         """Last update"""
         hsec = capi.rtnl_addr_get_last_update_time(self._rtnl_addr)
-        return datetime.timedelta(milliseconds=10*hsec)
+        return datetime.timedelta(milliseconds=10 * hsec)
 
     def add(self, socket=None, flags=None):
         if not socket:
@@ -330,38 +329,38 @@
     # Used for formatting output. USE AT OWN RISK
     @property
     def _flags(self):
-        return ','.join(self.flags)
+        return ",".join(self.flags)
 
-    def format(self, details=False, stats=False, nodev=False, indent=''):
+    def format(self, details=False, stats=False, nodev=False, indent=""):
         """Return address as formatted text"""
         fmt = util.MyFormatter(self, indent)
 
-        buf = fmt.format('{a|local!b}')
+        buf = fmt.format("{a|local!b}")
 
         if not nodev:
-            buf += fmt.format(' {a|ifindex}')
+            buf += fmt.format(" {a|ifindex}")
 
-        buf += fmt.format(' {a|scope}')
+        buf += fmt.format(" {a|scope}")
 
         if self.label:
             buf += fmt.format(' "{a|label}"')
 
-        buf += fmt.format(' <{a|_flags}>')
+        buf += fmt.format(" <{a|_flags}>")
 
         if details:
-            buf += fmt.nl('\t{t|broadcast} {t|multicast}') \
-                 + fmt.nl('\t{t|peer} {t|anycast}')
+            buf += fmt.nl("\t{t|broadcast} {t|multicast}") + fmt.nl(
+                "\t{t|peer} {t|anycast}"
+            )
 
             if self.valid_lifetime:
-                buf += fmt.nl('\t{s|valid-lifetime!k} '\
-                       '{a|valid_lifetime}')
+                buf += fmt.nl("\t{s|valid-lifetime!k} " "{a|valid_lifetime}")
 
             if self.preferred_lifetime:
-                buf += fmt.nl('\t{s|preferred-lifetime!k} '\
-                       '{a|preferred_lifetime}')
+                buf += fmt.nl("\t{s|preferred-lifetime!k} " "{a|preferred_lifetime}")
 
         if stats and (self.create_time or self.last_update):
-            buf += self.nl('\t{s|created!k} {a|create_time}'\
-                   ' {s|last-updated!k} {a|last_update}')
+            buf += self.nl(
+                "\t{s|created!k} {a|create_time}" " {s|last-updated!k} {a|last_update}"
+            )
 
         return buf
diff --git a/python/netlink/route/link.py b/python/netlink/route/link.py
index e3a6bd3..e6089e2 100644
--- a/python/netlink/route/link.py
+++ b/python/netlink/route/link.py
@@ -36,17 +36,17 @@
 
 from __future__ import absolute_import
 
-__version__ = '0.1'
+__version__ = "0.1"
 __all__ = [
-    'LinkCache',
-    'Link',
+    "LinkCache",
+    "Link",
 ]
 
 import socket
 from .. import core as netlink
 from .. import capi as core_capi
-from .  import capi as capi
-from .links  import inet as inet
+from . import capi as capi
+from .links import inet as inet
 from .. import util as util
 
 # Link statistics definitions
@@ -108,12 +108,13 @@
 ICMP6_OUTMSGS = 55
 ICMP6_OUTERRORS = 56
 
+
 class LinkCache(netlink.Cache):
     """Cache of network links"""
 
     def __init__(self, family=socket.AF_UNSPEC, cache=None):
         if not cache:
-            cache = self._alloc_cache_name('route/link')
+            cache = self._alloc_cache_name("route/link")
 
         self._info_module = None
         self._protocol = netlink.NETLINK_ROUTE
@@ -138,18 +139,19 @@
     def _new_cache(self, cache):
         return LinkCache(family=self.arg1, cache=cache)
 
+
 class Link(netlink.Object):
     """Network link"""
 
     def __init__(self, obj=None):
-        netlink.Object.__init__(self, 'route/link', 'link', obj)
+        netlink.Object.__init__(self, "route/link", "link", obj)
         self._rtnl_link = self._obj2type(self._nl_object)
 
         if self.type:
-            self._module_lookup('netlink.route.links.' + self.type)
+            self._module_lookup("netlink.route.links." + self.type)
 
         self.inet = inet.InetLink(self)
-        self.af = {'inet' : self.inet }
+        self.af = {"inet": self.inet}
 
     def __enter__(self):
         return self
@@ -222,13 +224,13 @@
         link.flags = [ '+xxx', '-yyy' ] # list operation
         """
         flags = capi.rtnl_link_get_flags(self._rtnl_link)
-        return capi.rtnl_link_flags2str(flags, 256)[0].split(',')
+        return capi.rtnl_link_flags2str(flags, 256)[0].split(",")
 
     def _set_flag(self, flag):
-        if flag.startswith('-'):
+        if flag.startswith("-"):
             i = capi.rtnl_link_str2flags(flag[1:])
             capi.rtnl_link_unset_flags(self._rtnl_link, i)
-        elif flag.startswith('+'):
+        elif flag.startswith("+"):
             i = capi.rtnl_link_str2flags(flag[1:])
             capi.rtnl_link_set_flags(self._rtnl_link, i)
         else:
@@ -318,7 +320,7 @@
         capi.rtnl_link_set_arptype(self._rtnl_link, i)
 
     @property
-    @netlink.nlattr(type=str, immutable=True, fmt=util.string, title='state')
+    @netlink.nlattr(type=str, immutable=True, fmt=util.string, title="state")
     def operstate(self):
         """Operational status"""
         operstate = capi.rtnl_link_get_operstate(self._rtnl_link)
@@ -360,16 +362,16 @@
     @type.setter
     def type(self, value):
         if capi.rtnl_link_set_type(self._rtnl_link, value) < 0:
-            raise NameError('unknown info type')
+            raise NameError("unknown info type")
 
-        self._module_lookup('netlink.route.links.' + value)
+        self._module_lookup("netlink.route.links." + value)
 
     def get_stat(self, stat):
         """Retrieve statistical information"""
         if type(stat) is str:
             stat = capi.rtnl_link_str2stat(stat)
             if stat < 0:
-                raise NameError('unknown name of statistic')
+                raise NameError("unknown name of statistic")
 
         return capi.rtnl_link_get_stat(self._rtnl_link, stat)
 
@@ -402,7 +404,7 @@
             sock = netlink.lookup_socket(netlink.NETLINK_ROUTE)
 
         if not self._orig:
-            raise netlink.NetlinkError('Original link not available')
+            raise netlink.NetlinkError("Original link not available")
         ret = capi.rtnl_link_change(sock._sock, self._orig, self._rtnl_link, flags)
         if ret < 0:
             raise netlink.KernelError(ret)
@@ -422,113 +424,121 @@
     # Used for formatting output. USE AT OWN RISK
     @property
     def _state(self):
-        if 'up' in self.flags:
-            buf = util.good('up')
-            if 'lowerup' not in self.flags:
-                buf += ' ' + util.bad('no-carrier')
+        if "up" in self.flags:
+            buf = util.good("up")
+            if "lowerup" not in self.flags:
+                buf += " " + util.bad("no-carrier")
         else:
-            buf = util.bad('down')
+            buf = util.bad("down")
         return buf
 
     @property
     def _brief(self):
-        return self._module_brief() + self._foreach_af('brief')
+        return self._module_brief() + self._foreach_af("brief")
 
     @property
     def _flags(self):
         ignore = [
-            'up',
-            'running',
-            'lowerup',
+            "up",
+            "running",
+            "lowerup",
         ]
-        return ','.join([flag for flag in self.flags if flag not in ignore])
+        return ",".join([flag for flag in self.flags if flag not in ignore])
 
     def _foreach_af(self, name, args=None):
-        buf = ''
+        buf = ""
         for af in self.af:
             try:
                 func = getattr(self.af[af], name)
                 s = str(func(args))
                 if len(s) > 0:
-                    buf += ' ' + s
+                    buf += " " + s
             except AttributeError:
                 pass
         return buf
 
-    def format(self, details=False, stats=False, indent=''):
+    def format(self, details=False, stats=False, indent=""):
         """Return link as formatted text"""
         fmt = util.MyFormatter(self, indent)
 
-        buf = fmt.format('{a|ifindex} {a|name} {a|arptype} {a|address} '\
-                 '{a|_state} <{a|_flags}> {a|_brief}')
+        buf = fmt.format(
+            "{a|ifindex} {a|name} {a|arptype} {a|address} "
+            "{a|_state} <{a|_flags}> {a|_brief}"
+        )
 
         if details:
-            buf += fmt.nl('\t{t|mtu} {t|txqlen} {t|weight} '\
-                      '{t|qdisc} {t|operstate}')
-            buf += fmt.nl('\t{t|broadcast} {t|alias}')
+            buf += fmt.nl("\t{t|mtu} {t|txqlen} {t|weight} " "{t|qdisc} {t|operstate}")
+            buf += fmt.nl("\t{t|broadcast} {t|alias}")
 
-            buf += self._foreach_af('details', fmt)
+            buf += self._foreach_af("details", fmt)
 
         if stats:
-            l = [['Packets', RX_PACKETS, TX_PACKETS],
-                 ['Bytes', RX_BYTES, TX_BYTES],
-                 ['Errors', RX_ERRORS, TX_ERRORS],
-                 ['Dropped', RX_DROPPED, TX_DROPPED],
-                 ['Compressed', RX_COMPRESSED, TX_COMPRESSED],
-                 ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR],
-                 ['Length Errors', RX_LEN_ERR, None],
-                 ['Over Errors', RX_OVER_ERR, None],
-                 ['CRC Errors', RX_CRC_ERR, None],
-                 ['Frame Errors', RX_FRAME_ERR, None],
-                 ['Missed Errors', RX_MISSED_ERR, None],
-                 ['Abort Errors', None, TX_ABORT_ERR],
-                 ['Carrier Errors', None, TX_CARRIER_ERR],
-                 ['Heartbeat Errors', None, TX_HBEAT_ERR],
-                 ['Window Errors', None, TX_WIN_ERR],
-                 ['Collisions', None, COLLISIONS],
-                 ['Multicast', None, MULTICAST],
-                 ['', None, None],
-                 ['Ipv6:', None, None],
-                 ['Packets', IP6_INPKTS, IP6_OUTPKTS],
-                 ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS],
-                 ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS],
-                 ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS],
-                 ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS],
-                 ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS],
-                 ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS],
-                 ['Delivers', IP6_INDELIVERS, None],
-                 ['Forwarded', None, IP6_OUTFORWDATAGRAMS],
-                 ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES],
-                 ['Header Errors', IP6_INHDRERRORS, None],
-                 ['Too Big Errors', IP6_INTOOBIGERRORS, None],
-                 ['Address Errors', IP6_INADDRERRORS, None],
-                 ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None],
-                 ['Truncated Packets', IP6_INTRUNCATEDPKTS, None],
-                 ['Reasm Timeouts', IP6_REASMTIMEOUT, None],
-                 ['Reasm Requests', IP6_REASMREQDS, None],
-                 ['Reasm Failures', IP6_REASMFAILS, None],
-                 ['Reasm OK', IP6_REASMOKS, None],
-                 ['Frag Created', None, IP6_FRAGCREATES],
-                 ['Frag Failures', None, IP6_FRAGFAILS],
-                 ['Frag OK', None, IP6_FRAGOKS],
-                 ['', None, None],
-                 ['ICMPv6:', None, None],
-                 ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS],
-                 ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]]
+            lst = [
+                ["Packets", RX_PACKETS, TX_PACKETS],
+                ["Bytes", RX_BYTES, TX_BYTES],
+                ["Errors", RX_ERRORS, TX_ERRORS],
+                ["Dropped", RX_DROPPED, TX_DROPPED],
+                ["Compressed", RX_COMPRESSED, TX_COMPRESSED],
+                ["FIFO Errors", RX_FIFO_ERR, TX_FIFO_ERR],
+                ["Length Errors", RX_LEN_ERR, None],
+                ["Over Errors", RX_OVER_ERR, None],
+                ["CRC Errors", RX_CRC_ERR, None],
+                ["Frame Errors", RX_FRAME_ERR, None],
+                ["Missed Errors", RX_MISSED_ERR, None],
+                ["Abort Errors", None, TX_ABORT_ERR],
+                ["Carrier Errors", None, TX_CARRIER_ERR],
+                ["Heartbeat Errors", None, TX_HBEAT_ERR],
+                ["Window Errors", None, TX_WIN_ERR],
+                ["Collisions", None, COLLISIONS],
+                ["Multicast", None, MULTICAST],
+                ["", None, None],
+                ["Ipv6:", None, None],
+                ["Packets", IP6_INPKTS, IP6_OUTPKTS],
+                ["Bytes", IP6_INOCTETS, IP6_OUTOCTETS],
+                ["Discards", IP6_INDISCARDS, IP6_OUTDISCARDS],
+                ["Multicast Packets", IP6_INMCASTPKTS, IP6_OUTMCASTPKTS],
+                ["Multicast Bytes", IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS],
+                ["Broadcast Packets", IP6_INBCASTPKTS, IP6_OUTBCASTPKTS],
+                ["Broadcast Bytes", IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS],
+                ["Delivers", IP6_INDELIVERS, None],
+                ["Forwarded", None, IP6_OUTFORWDATAGRAMS],
+                ["No Routes", IP6_INNOROUTES, IP6_OUTNOROUTES],
+                ["Header Errors", IP6_INHDRERRORS, None],
+                ["Too Big Errors", IP6_INTOOBIGERRORS, None],
+                ["Address Errors", IP6_INADDRERRORS, None],
+                ["Unknown Protocol", IP6_INUNKNOWNPROTOS, None],
+                ["Truncated Packets", IP6_INTRUNCATEDPKTS, None],
+                ["Reasm Timeouts", IP6_REASMTIMEOUT, None],
+                ["Reasm Requests", IP6_REASMREQDS, None],
+                ["Reasm Failures", IP6_REASMFAILS, None],
+                ["Reasm OK", IP6_REASMOKS, None],
+                ["Frag Created", None, IP6_FRAGCREATES],
+                ["Frag Failures", None, IP6_FRAGFAILS],
+                ["Frag OK", None, IP6_FRAGOKS],
+                ["", None, None],
+                ["ICMPv6:", None, None],
+                ["Messages", ICMP6_INMSGS, ICMP6_OUTMSGS],
+                ["Errors", ICMP6_INERRORS, ICMP6_OUTERRORS],
+            ]
 
-            buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'),
-                           15 * ' ', util.title('TX'))
+            buf += "\n\t%s%s%s%s\n" % (
+                33 * " ",
+                util.title("RX"),
+                15 * " ",
+                util.title("TX"),
+            )
 
-            for row in l:
+            for row in lst:
                 row[0] = util.kw(row[0])
-                row[1] = self.get_stat(row[1]) if row[1] else ''
-                row[2] = self.get_stat(row[2]) if row[2] else ''
-                buf += '\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n'.format(row)
+                row[1] = self.get_stat(row[1]) if row[1] else ""
+                row[2] = self.get_stat(row[2]) if row[2] else ""
+                buf += "\t{0[0]:27} {0[1]:>16} {0[2]:>16}\n".format(row)
 
-            buf += self._foreach_af('stats')
+            buf += self._foreach_af("stats")
 
         return buf
 
+
 def get(name, sock=None):
     """Lookup Link object directly from kernel"""
     if not name:
@@ -543,8 +553,10 @@
 
     return Link.from_capi(link)
 
+
 _link_cache = LinkCache()
 
+
 def resolve(name):
     _link_cache.refill()
     return _link_cache[name]
diff --git a/python/netlink/route/links/bridge.py b/python/netlink/route/links/bridge.py
index cf4e764..d3e72e5 100644
--- a/python/netlink/route/links/bridge.py
+++ b/python/netlink/route/links/bridge.py
@@ -10,20 +10,29 @@
 from __future__ import print_function
 
 from ... import core as netlink
-from ..  import capi as capi
+from .. import capi as capi
+
 
 class BRIDGELink(object):
     def __init__(self, link):
         self._link = link
         self._has_ext_info = capi.rtnl_link_bridge_has_ext_info(self._link)
-        self._port_state_values = ['disabled','listening','learning','forwarding','blocking']
+        self._port_state_values = [
+            "disabled",
+            "listening",
+            "learning",
+            "forwarding",
+            "blocking",
+        ]
 
     def bridge_assert_ext_info(self):
-        if self._has_ext_info == False:
-            print("""
+        if not self._has_ext_info:
+            print(
+                """
             Please update your kernel to be able to call this method.
             Your current kernel bridge version is too old to support this extention.
-            """)
+            """
+            )
             raise RuntimeWarning()
 
     def port_state2str(self, state):
@@ -40,7 +49,9 @@
     def port_state(self):
         """bridge state :
         %s
-        """ % (self.port_state)
+        """ % (
+            self.port_state
+        )
         return capi.rtnl_link_bridge_get_state(self._link)
 
     @port_state.setter
@@ -50,8 +61,7 @@
     @property
     @netlink.nlattr(type=int)
     def priority(self):
-        """bridge prio
-        """
+        """bridge prio"""
         self.bridge_assert_ext_info()
         return capi.rtnl_link_bridge_get_prio(self._link)
 
@@ -65,8 +75,7 @@
     @property
     @netlink.nlattr(type=int)
     def cost(self):
-        """bridge prio
-        """
+        """bridge prio"""
         self.bridge_assert_ext_info()
         return capi.rtnl_link_bridge_get_cost(self._link)
 
@@ -80,7 +89,7 @@
     @property
     @netlink.nlattr(type=str)
     def flags(self):
-        """ BRIDGE flags
+        """BRIDGE flags
         Setting this property will *Not* reset flags to value you supply in
         Examples:
         link.flags = '+xxx' # add xxx flag
@@ -90,13 +99,13 @@
         """
         self.bridge_assert_ext_info()
         flags = capi.rtnl_link_bridge_get_flags(self._link)
-        return capi.rtnl_link_bridge_flags2str(flags, 256)[0].split(',')
+        return capi.rtnl_link_bridge_flags2str(flags, 256)[0].split(",")
 
     def _set_flag(self, flag):
-        if flag.startswith('-'):
+        if flag.startswith("-"):
             i = capi.rtnl_link_bridge_str2flags(flag[1:])
             capi.rtnl_link_bridge_unset_flags(self._link, i)
-        elif flag.startswith('+'):
+        elif flag.startswith("+"):
             i = capi.rtnl_link_bridge_str2flags(flag[1:])
             capi.rtnl_link_bridge_set_flags(self._link, i)
         else:
@@ -113,7 +122,8 @@
             self._set_flag(value)
 
     def brief(self):
-        return 'bridge-has-ext-info {0}'.format(self._has_ext_info)
+        return "bridge-has-ext-info {0}".format(self._has_ext_info)
+
 
 def init(link):
     link.bridge = BRIDGELink(link._rtnl_link)
diff --git a/python/netlink/route/links/dummy.py b/python/netlink/route/links/dummy.py
index e9491cc..1dc3c68 100644
--- a/python/netlink/route/links/dummy.py
+++ b/python/netlink/route/links/dummy.py
@@ -7,9 +7,9 @@
 """
 from __future__ import absolute_import
 
-__version__ = '1.0'
+__version__ = "1.0"
 __all__ = [
-    'init',
+    "init",
 ]
 
 
@@ -19,7 +19,8 @@
 
     @staticmethod
     def brief():
-        return 'dummy'
+        return "dummy"
+
 
 def init(link):
     link.dummy = DummyLink(link._rtnl_link)
diff --git a/python/netlink/route/links/inet.py b/python/netlink/route/links/inet.py
index d4de07b..7aeedcd 100644
--- a/python/netlink/route/links/inet.py
+++ b/python/netlink/route/links/inet.py
@@ -11,8 +11,9 @@
 __all__ = []
 
 from ... import core as netlink
-from ..  import capi as capi
+from .. import capi as capi
 from ... import util as util
+
 DEVCONF_FORWARDING = 1
 DEVCONF_MC_FORWARDING = 2
 DEVCONF_PROXY_ARP = 3
@@ -40,27 +41,27 @@
 DEVCONF_PROXY_ARP_PVLAN = 25
 DEVCONF_MAX = DEVCONF_PROXY_ARP_PVLAN
 
+
 def _resolve(id):
     if type(id) is str:
         id = capi.rtnl_link_inet_str2devconf(id)[0]
         if id < 0:
-            raise NameError('unknown configuration id')
+            raise NameError("unknown configuration id")
     return id
 
+
 class InetLink(object):
     def __init__(self, link):
         self._link = link
 
     def details(self, fmt):
-        buf = fmt.nl('\n\t{0}\n\t'.format(util.title('Configuration:')))
+        buf = fmt.nl("\n\t{0}\n\t".format(util.title("Configuration:")))
 
-        for i in range(DEVCONF_FORWARDING, DEVCONF_MAX+1):
+        for i in range(DEVCONF_FORWARDING, DEVCONF_MAX + 1):
             if i & 1 and i > 1:
-                buf += fmt.nl('\t')
+                buf += fmt.nl("\t")
             txt = util.kw(capi.rtnl_link_inet_devconf2str(i, 32)[0])
-            buf += fmt.format('{0:28s} {1:12}  ', txt,
-                      self.get_conf(i))
-
+            buf += fmt.format("{0:28s} {1:12}  ", txt, self.get_conf(i))
 
         return buf
 
@@ -68,8 +69,9 @@
         return capi.inet_get_conf(self._link._rtnl_link, _resolve(id))
 
     def set_conf(self, id, value):
-        return capi.rtnl_link_inet_set_conf(self._link._rtnl_link,
-                        _resolve(id), int(value))
+        return capi.rtnl_link_inet_set_conf(
+            self._link._rtnl_link, _resolve(id), int(value)
+        )
 
     @property
     @netlink.nlattr(type=bool, fmt=util.boolean)
@@ -80,7 +82,6 @@
     def forwarding(self, value):
         self.set_conf(DEVCONF_FORWARDING, int(value))
 
-
     @property
     @netlink.nlattr(type=bool, fmt=util.boolean)
     def mc_forwarding(self):
@@ -90,7 +91,6 @@
     def mc_forwarding(self, value):
         self.set_conf(DEVCONF_MC_FORWARDING, int(value))
 
-
     @property
     @netlink.nlattr(type=bool, fmt=util.boolean)
     def proxy_arp(self):
@@ -136,21 +136,22 @@
     def shared_media(self, value):
         self.set_conf(DEVCONF_SHARED_MEDIA, int(value))
 
-#	IPV4_DEVCONF_RP_FILTER,
-#	IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
-#	IPV4_DEVCONF_BOOTP_RELAY,
-#	IPV4_DEVCONF_LOG_MARTIANS,
-#	IPV4_DEVCONF_TAG,
-#	IPV4_DEVCONF_ARPFILTER,
-#	IPV4_DEVCONF_MEDIUM_ID,
-#	IPV4_DEVCONF_NOXFRM,
-#	IPV4_DEVCONF_NOPOLICY,
-#	IPV4_DEVCONF_FORCE_IGMP_VERSION,
-#	IPV4_DEVCONF_ARP_ANNOUNCE,
-#	IPV4_DEVCONF_ARP_IGNORE,
-#	IPV4_DEVCONF_PROMOTE_SECONDARIES,
-#	IPV4_DEVCONF_ARP_ACCEPT,
-#	IPV4_DEVCONF_ARP_NOTIFY,
-#	IPV4_DEVCONF_ACCEPT_LOCAL,
-#	IPV4_DEVCONF_SRC_VMARK,
-#	IPV4_DEVCONF_PROXY_ARP_PVLAN,
+
+# 	IPV4_DEVCONF_RP_FILTER,
+# 	IPV4_DEVCONF_ACCEPT_SOURCE_ROUTE,
+# 	IPV4_DEVCONF_BOOTP_RELAY,
+# 	IPV4_DEVCONF_LOG_MARTIANS,
+# 	IPV4_DEVCONF_TAG,
+# 	IPV4_DEVCONF_ARPFILTER,
+# 	IPV4_DEVCONF_MEDIUM_ID,
+# 	IPV4_DEVCONF_NOXFRM,
+# 	IPV4_DEVCONF_NOPOLICY,
+# 	IPV4_DEVCONF_FORCE_IGMP_VERSION,
+# 	IPV4_DEVCONF_ARP_ANNOUNCE,
+# 	IPV4_DEVCONF_ARP_IGNORE,
+# 	IPV4_DEVCONF_PROMOTE_SECONDARIES,
+# 	IPV4_DEVCONF_ARP_ACCEPT,
+# 	IPV4_DEVCONF_ARP_NOTIFY,
+# 	IPV4_DEVCONF_ACCEPT_LOCAL,
+# 	IPV4_DEVCONF_SRC_VMARK,
+# 	IPV4_DEVCONF_PROXY_ARP_PVLAN,
diff --git a/python/netlink/route/links/vlan.py b/python/netlink/route/links/vlan.py
index 0ba3781..8bee3c9 100644
--- a/python/netlink/route/links/vlan.py
+++ b/python/netlink/route/links/vlan.py
@@ -10,7 +10,9 @@
 
 
 from ... import core as netlink
-from ..  import capi as capi
+from .. import capi as capi
+
+
 class VLANLink(object):
     def __init__(self, link):
         self._link = link
@@ -28,7 +30,7 @@
     @property
     @netlink.nlattr(type=str)
     def flags(self):
-        """ VLAN flags
+        """VLAN flags
         Setting this property will *Not* reset flags to value you supply in
         Examples:
         link.flags = '+xxx' # add xxx flag
@@ -37,13 +39,13 @@
         link.flags = [ '+xxx', '-yyy' ] # list operation
         """
         flags = capi.rtnl_link_vlan_get_flags(self._link)
-        return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(',')
+        return capi.rtnl_link_vlan_flags2str(flags, 256)[0].split(",")
 
     def _set_flag(self, flag):
-        if flag.startswith('-'):
+        if flag.startswith("-"):
             i = capi.rtnl_link_vlan_str2flags(flag[1:])
             capi.rtnl_link_vlan_unset_flags(self._link, i)
-        elif flag.startswith('+'):
+        elif flag.startswith("+"):
             i = capi.rtnl_link_vlan_str2flags(flag[1:])
             capi.rtnl_link_vlan_set_flags(self._link, i)
         else:
@@ -64,7 +66,8 @@
     #   - egress map
 
     def brief(self):
-        return 'vlan-id {0}'.format(self.id)
+        return "vlan-id {0}".format(self.id)
+
 
 def init(link):
     link.vlan = VLANLink(link._rtnl_link)
diff --git a/python/netlink/route/qdisc/htb.py b/python/netlink/route/qdisc/htb.py
index d051c8d..0dc70f4 100644
--- a/python/netlink/route/qdisc/htb.py
+++ b/python/netlink/route/qdisc/htb.py
@@ -10,8 +10,9 @@
 
 from ... import core as netlink
 from ... import util as util
-from ..  import capi as capi
-from ..  import tc as tc
+from .. import capi as capi
+from .. import tc as tc
+
 
 class HTBQdisc(object):
     def __init__(self, qdisc):
@@ -27,25 +28,25 @@
         capi.rtnl_htb_set_defcls(self._qdisc._rtnl_qdisc, int(value))
 
     @property
-    @netlink.nlattr('r2q', type=int)
+    @netlink.nlattr(type=int)
     def r2q(self):
         return capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc)
 
     @r2q.setter
     def r2q(self, value):
-        capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc,
-                           int(value))
+        capi.rtnl_htb_get_rate2quantum(self._qdisc._rtnl_qdisc, int(value))
 
     def brief(self):
         fmt = util.MyFormatter(self)
 
-        ret = ' {s|default-class!k} {a|default_class}'
+        ret = " {s|default-class!k} {a|default_class}"
 
         if self.r2q:
-            ret += ' {s|r2q!k} {a|r2q}'
+            ret += " {s|r2q!k} {a|r2q}"
 
         return fmt.format(ret)
 
+
 class HTBClass(object):
     def __init__(self, cl):
         self._class = cl
@@ -120,26 +121,29 @@
     def brief(self):
         fmt = util.MyFormatter(self)
 
-        ret = ' {t|prio} {t|rate}'
+        ret = " {t|prio} {t|rate}"
 
         if self.rate != self.ceil:
-            ret += ' {s|borrow-up-to!k} {a|ceil}'
+            ret += " {s|borrow-up-to!k} {a|ceil}"
 
-        ret += ' {t|burst}'
+        ret += " {t|burst}"
 
         return fmt.format(ret)
 
     def details(self):
         fmt = util.MyFormatter(self)
 
-        return fmt.nl('\t{t|level} {t|quantum}')
+        return fmt.nl("\t{t|level} {t|quantum}")
+
 
 def init_qdisc(qdisc):
     qdisc.htb = HTBQdisc(qdisc)
     return qdisc.htb
 
+
 def init_class(cl):
     cl.htb = HTBClass(cl)
     return cl.htb
 
-#extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum);
+
+# extern void rtnl_htb_set_quantum(struct rtnl_class *, uint32_t quantum);
diff --git a/python/netlink/route/tc.py b/python/netlink/route/tc.py
index 0689b71..daad697 100644
--- a/python/netlink/route/tc.py
+++ b/python/netlink/route/tc.py
@@ -4,18 +4,18 @@
 from __future__ import absolute_import
 
 __all__ = [
-    'TcCache',
-    'Tc',
-    'QdiscCache',
-    'Qdisc',
-    'TcClassCache',
-    'TcClass',
+    "TcCache",
+    "Tc",
+    "QdiscCache",
+    "Qdisc",
+    "TcClassCache",
+    "TcClass",
 ]
 
 from .. import core as netlink
-from .  import capi as capi
+from . import capi as capi
 from .. import util as util
-from .  import link as Link
+from . import link as Link
 
 TC_PACKETS = 0
 TC_BYTES = 1
@@ -43,7 +43,7 @@
 
 
 class Handle(object):
-    """ Traffic control handle
+    """Traffic control handle
 
     Representation of a traffic control handle which uniquely identifies
     each traffic control object in its link namespace.
@@ -53,6 +53,7 @@
     print int(handle)
     print str(handle)
     """
+
     def __init__(self, val=None):
         if type(val) is str:
             val = capi.tc_str2handle(val)
@@ -81,12 +82,14 @@
     def isroot(self):
         return self._val == TC_H_ROOT or self._val == TC_H_INGRESS
 
+
 class TcCache(netlink.Cache):
     """Cache of traffic control object"""
 
     def __getitem__(self, key):
         raise NotImplementedError()
 
+
 class Tc(netlink.Object):
     def __cmp__(self, other):
         diff = self.ifindex - other.ifindex
@@ -95,8 +98,7 @@
         return diff
 
     def _tc_module_lookup(self):
-        self._module_lookup(self._module_path + self.kind,
-                    'init_' + self._name)
+        self._module_lookup(self._module_path + self.kind, "init_" + self._name)
 
     @property
     def root(self):
@@ -189,7 +191,7 @@
 
     @property
     def _dev(self):
-        buf = util.kw('dev') + ' '
+        buf = util.kw("dev") + " "
 
         if self.link:
             return buf + util.string(self.link.name)
@@ -197,19 +199,19 @@
             return buf + util.num(self.ifindex)
 
     def brief(self, title, nodev=False, noparent=False):
-        ret = title + ' {a|kind} {a|handle}'
+        ret = title + " {a|kind} {a|handle}"
 
         if not nodev:
-            ret += ' {a|_dev}'
+            ret += " {a|_dev}"
 
         if not noparent:
-            ret += ' {t|parent}'
+            ret += " {t|parent}"
 
         return ret + self._module_brief()
 
     @staticmethod
     def details():
-        return '{t|mtu} {t|mpu} {t|overhead} {t|linktype}'
+        return "{t|mtu} {t|mpu} {t|overhead} {t|linktype}"
 
     @property
     def packets(self):
@@ -225,28 +227,29 @@
 
     @staticmethod
     def stats(fmt):
-        return fmt.nl('{t|packets} {t|bytes} {t|qlen}')
+        return fmt.nl("{t|packets} {t|bytes} {t|qlen}")
+
 
 class QdiscCache(netlink.Cache):
     """Cache of qdiscs"""
 
     def __init__(self, cache=None):
         if not cache:
-            cache = self._alloc_cache_name('route/qdisc')
+            cache = self._alloc_cache_name("route/qdisc")
 
         self._protocol = netlink.NETLINK_ROUTE
         self._nl_cache = cache
 
-#	def __getitem__(self, key):
-#        	if type(key) is int:
-#                        link = capi.rtnl_link_get(self._this, key)
-#                elif type(key) is str:
-#                        link = capi.rtnl_link_get_by_name(self._this, key)
-#
-#		if qdisc is None:
-#                        raise KeyError()
-#		else:
-#                        return Qdisc._from_capi(capi.qdisc2obj(qdisc))
+    # 	def __getitem__(self, key):
+    #        	if type(key) is int:
+    #                        link = capi.rtnl_link_get(self._this, key)
+    #                elif type(key) is str:
+    #                        link = capi.rtnl_link_get_by_name(self._this, key)
+    #
+    # 		if qdisc is None:
+    #                        raise KeyError()
+    # 		else:
+    #                        return Qdisc._from_capi(capi.qdisc2obj(qdisc))
 
     @staticmethod
     def _new_object(obj):
@@ -256,12 +259,13 @@
     def _new_cache(cache):
         return QdiscCache(cache=cache)
 
+
 class Qdisc(Tc):
     """Queueing discipline"""
 
     def __init__(self, obj=None):
-        netlink.Object.__init__(self, 'route/qdisc', 'qdisc', obj)
-        self._module_path = 'netlink.route.qdisc.'
+        netlink.Object.__init__(self, "route/qdisc", "qdisc", obj)
+        self._module_path = "netlink.route.qdisc."
         self._rtnl_qdisc = self._obj2type(self._nl_object)
         self._rtnl_tc = capi.obj2tc(self._nl_object)
 
@@ -297,105 +301,107 @@
 
         return ret
 
-#	def add(self, socket, flags=None):
-#        	if not flags:
-#                        flags = netlink.NLM_F_CREATE
-#
-#		ret = capi.rtnl_link_add(socket._sock, self._link, flags)
-#		if ret < 0:
-#			raise netlink.KernelError(ret)
-#
-#	def change(self, socket, flags=0):
-#		"""Commit changes made to the link object"""
-#		if not self._orig:
-#			raise NetlinkError('Original link not available')
-#        	ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags)
-#                if ret < 0:
-#                        raise netlink.KernelError(ret)
-#
-#	def delete(self, socket):
-#		"""Attempt to delete this link in the kernel"""
-#        	ret = capi.rtnl_link_delete(socket._sock, self._link)
-#                if ret < 0:
-#                        raise netlink.KernelError(ret)
+    # 	def add(self, socket, flags=None):
+    #        	if not flags:
+    #                        flags = netlink.NLM_F_CREATE
+    #
+    # 		ret = capi.rtnl_link_add(socket._sock, self._link, flags)
+    # 		if ret < 0:
+    # 			raise netlink.KernelError(ret)
+    #
+    # 	def change(self, socket, flags=0):
+    # 		"""Commit changes made to the link object"""
+    # 		if not self._orig:
+    # 			raise NetlinkError('Original link not available')
+    #        	ret = capi.rtnl_link_change(socket._sock, self._orig, self._link, flags)
+    #                if ret < 0:
+    #                        raise netlink.KernelError(ret)
+    #
+    # 	def delete(self, socket):
+    # 		"""Attempt to delete this link in the kernel"""
+    #        	ret = capi.rtnl_link_delete(socket._sock, self._link)
+    #                if ret < 0:
+    #                        raise netlink.KernelError(ret)
 
-    def format(self, details=False, stats=False, nodev=False,
-           noparent=False, indent=''):
+    def format(
+        self, details=False, stats=False, nodev=False, noparent=False, indent=""
+    ):
         """Return qdisc as formatted text"""
         fmt = util.MyFormatter(self, indent)
 
-        buf = fmt.format(self.brief('qdisc', nodev, noparent))
+        buf = fmt.format(self.brief("qdisc", nodev, noparent))
 
         if details:
-            buf += fmt.nl('\t' + self.details())
+            buf += fmt.nl("\t" + self.details())
 
         if stats:
             buf += self.stats(fmt)
 
-#		if stats:
-#			l = [['Packets', RX_PACKETS, TX_PACKETS],
-#			     ['Bytes', RX_BYTES, TX_BYTES],
-#			     ['Errors', RX_ERRORS, TX_ERRORS],
-#			     ['Dropped', RX_DROPPED, TX_DROPPED],
-#			     ['Compressed', RX_COMPRESSED, TX_COMPRESSED],
-#			     ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR],
-#			     ['Length Errors', RX_LEN_ERR, None],
-#			     ['Over Errors', RX_OVER_ERR, None],
-#			     ['CRC Errors', RX_CRC_ERR, None],
-#			     ['Frame Errors', RX_FRAME_ERR, None],
-#			     ['Missed Errors', RX_MISSED_ERR, None],
-#			     ['Abort Errors', None, TX_ABORT_ERR],
-#			     ['Carrier Errors', None, TX_CARRIER_ERR],
-#			     ['Heartbeat Errors', None, TX_HBEAT_ERR],
-#			     ['Window Errors', None, TX_WIN_ERR],
-#			     ['Collisions', None, COLLISIONS],
-#			     ['Multicast', None, MULTICAST],
-#			     ['', None, None],
-#			     ['Ipv6:', None, None],
-#			     ['Packets', IP6_INPKTS, IP6_OUTPKTS],
-#			     ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS],
-#			     ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS],
-#			     ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS],
-#			     ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS],
-#			     ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS],
-#			     ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS],
-#			     ['Delivers', IP6_INDELIVERS, None],
-#			     ['Forwarded', None, IP6_OUTFORWDATAGRAMS],
-#			     ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES],
-#			     ['Header Errors', IP6_INHDRERRORS, None],
-#			     ['Too Big Errors', IP6_INTOOBIGERRORS, None],
-#			     ['Address Errors', IP6_INADDRERRORS, None],
-#			     ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None],
-#			     ['Truncated Packets', IP6_INTRUNCATEDPKTS, None],
-#			     ['Reasm Timeouts', IP6_REASMTIMEOUT, None],
-#			     ['Reasm Requests', IP6_REASMREQDS, None],
-#			     ['Reasm Failures', IP6_REASMFAILS, None],
-#			     ['Reasm OK', IP6_REASMOKS, None],
-#			     ['Frag Created', None, IP6_FRAGCREATES],
-#			     ['Frag Failures', None, IP6_FRAGFAILS],
-#			     ['Frag OK', None, IP6_FRAGOKS],
-#			     ['', None, None],
-#			     ['ICMPv6:', None, None],
-#			     ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS],
-#			     ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]]
-#
-#			buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'),
-#                        			   15 * ' ', util.title('TX'))
-#
-#			for row in l:
-#				row[0] = util.kw(row[0])
-#                                row[1] = self.get_stat(row[1]) if row[1] else ''
-#                                row[2] = self.get_stat(row[2]) if row[2] else ''
-#				buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row)
+        # 		if stats:
+        # 			l = [['Packets', RX_PACKETS, TX_PACKETS],
+        # 			     ['Bytes', RX_BYTES, TX_BYTES],
+        # 			     ['Errors', RX_ERRORS, TX_ERRORS],
+        # 			     ['Dropped', RX_DROPPED, TX_DROPPED],
+        # 			     ['Compressed', RX_COMPRESSED, TX_COMPRESSED],
+        # 			     ['FIFO Errors', RX_FIFO_ERR, TX_FIFO_ERR],
+        # 			     ['Length Errors', RX_LEN_ERR, None],
+        # 			     ['Over Errors', RX_OVER_ERR, None],
+        # 			     ['CRC Errors', RX_CRC_ERR, None],
+        # 			     ['Frame Errors', RX_FRAME_ERR, None],
+        # 			     ['Missed Errors', RX_MISSED_ERR, None],
+        # 			     ['Abort Errors', None, TX_ABORT_ERR],
+        # 			     ['Carrier Errors', None, TX_CARRIER_ERR],
+        # 			     ['Heartbeat Errors', None, TX_HBEAT_ERR],
+        # 			     ['Window Errors', None, TX_WIN_ERR],
+        # 			     ['Collisions', None, COLLISIONS],
+        # 			     ['Multicast', None, MULTICAST],
+        # 			     ['', None, None],
+        # 			     ['Ipv6:', None, None],
+        # 			     ['Packets', IP6_INPKTS, IP6_OUTPKTS],
+        # 			     ['Bytes', IP6_INOCTETS, IP6_OUTOCTETS],
+        # 			     ['Discards', IP6_INDISCARDS, IP6_OUTDISCARDS],
+        # 			     ['Multicast Packets', IP6_INMCASTPKTS, IP6_OUTMCASTPKTS],
+        # 			     ['Multicast Bytes', IP6_INMCASTOCTETS, IP6_OUTMCASTOCTETS],
+        # 			     ['Broadcast Packets', IP6_INBCASTPKTS, IP6_OUTBCASTPKTS],
+        # 			     ['Broadcast Bytes', IP6_INBCASTOCTETS, IP6_OUTBCASTOCTETS],
+        # 			     ['Delivers', IP6_INDELIVERS, None],
+        # 			     ['Forwarded', None, IP6_OUTFORWDATAGRAMS],
+        # 			     ['No Routes', IP6_INNOROUTES, IP6_OUTNOROUTES],
+        # 			     ['Header Errors', IP6_INHDRERRORS, None],
+        # 			     ['Too Big Errors', IP6_INTOOBIGERRORS, None],
+        # 			     ['Address Errors', IP6_INADDRERRORS, None],
+        # 			     ['Unknown Protocol', IP6_INUNKNOWNPROTOS, None],
+        # 			     ['Truncated Packets', IP6_INTRUNCATEDPKTS, None],
+        # 			     ['Reasm Timeouts', IP6_REASMTIMEOUT, None],
+        # 			     ['Reasm Requests', IP6_REASMREQDS, None],
+        # 			     ['Reasm Failures', IP6_REASMFAILS, None],
+        # 			     ['Reasm OK', IP6_REASMOKS, None],
+        # 			     ['Frag Created', None, IP6_FRAGCREATES],
+        # 			     ['Frag Failures', None, IP6_FRAGFAILS],
+        # 			     ['Frag OK', None, IP6_FRAGOKS],
+        # 			     ['', None, None],
+        # 			     ['ICMPv6:', None, None],
+        # 			     ['Messages', ICMP6_INMSGS, ICMP6_OUTMSGS],
+        # 			     ['Errors', ICMP6_INERRORS, ICMP6_OUTERRORS]]
+        #
+        # 			buf += '\n\t%s%s%s%s\n' % (33 * ' ', util.title('RX'),
+        #                        			   15 * ' ', util.title('TX'))
+        #
+        # 			for row in l:
+        # 				row[0] = util.kw(row[0])
+        #                                row[1] = self.get_stat(row[1]) if row[1] else ''
+        #                                row[2] = self.get_stat(row[2]) if row[2] else ''
+        # 				buf += '\t{0:27} {1:>16} {2:>16}\n'.format(*row)
 
         return buf
 
+
 class TcClassCache(netlink.Cache):
     """Cache of traffic classes"""
 
     def __init__(self, ifindex, cache=None):
         if not cache:
-            cache = self._alloc_cache_name('route/class')
+            cache = self._alloc_cache_name("route/class")
 
         self._protocol = netlink.NETLINK_ROUTE
         self._nl_cache = cache
@@ -408,12 +414,13 @@
     def _new_cache(self, cache):
         return TcClassCache(self.arg1, cache=cache)
 
+
 class TcClass(Tc):
     """Traffic Class"""
 
     def __init__(self, obj=None):
-        netlink.Object.__init__(self, 'route/class', 'class', obj)
-        self._module_path = 'netlink.route.qdisc.'
+        netlink.Object.__init__(self, "route/class", "class", obj)
+        self._module_path = "netlink.route.qdisc."
         self._rtnl_class = self._obj2type(self._nl_object)
         self._rtnl_tc = capi.obj2tc(self._nl_object)
 
@@ -447,24 +454,26 @@
 
         return ret
 
-    def format(self, details=False, _stats=False, nodev=False,
-           noparent=False, indent=''):
+    def format(
+        self, details=False, _stats=False, nodev=False, noparent=False, indent=""
+    ):
         """Return class as formatted text"""
         fmt = util.MyFormatter(self, indent)
 
-        buf = fmt.format(self.brief('class', nodev, noparent))
+        buf = fmt.format(self.brief("class", nodev, noparent))
 
         if details:
-            buf += fmt.nl('\t' + self.details())
+            buf += fmt.nl("\t" + self.details())
 
         return buf
 
+
 class ClassifierCache(netlink.Cache):
     """Cache of traffic classifiers objects"""
 
     def __init__(self, ifindex, parent, cache=None):
         if not cache:
-            cache = self._alloc_cache_name('route/cls')
+            cache = self._alloc_cache_name("route/cls")
 
         self._protocol = netlink.NETLINK_ROUTE
         self._nl_cache = cache
@@ -478,12 +487,13 @@
     def _new_cache(self, cache):
         return ClassifierCache(self.arg1, self.arg2, cache=cache)
 
+
 class Classifier(Tc):
     """Classifier"""
 
     def __init__(self, obj=None):
-        netlink.Object.__init__(self, 'route/cls', 'cls', obj)
-        self._module_path = 'netlink.route.cls.'
+        netlink.Object.__init__(self, "route/cls", "cls", obj)
+        self._module_path = "netlink.route.cls."
         self._rtnl_cls = self._obj2type(self._nl_object)
         self._rtnl_tc = capi.obj2tc(self._nl_object)
 
@@ -522,23 +532,26 @@
     def childs(self):
         return []
 
-    def format(self, details=False, _stats=False, nodev=False,
-           noparent=False, indent=''):
+    def format(
+        self, details=False, _stats=False, nodev=False, noparent=False, indent=""
+    ):
         """Return class as formatted text"""
         fmt = util.MyFormatter(self, indent)
 
-        buf = fmt.format(self.brief('classifier', nodev, noparent))
-        buf += fmt.format(' {t|priority} {t|protocol}')
+        buf = fmt.format(self.brief("classifier", nodev, noparent))
+        buf += fmt.format(" {t|priority} {t|protocol}")
 
         if details:
-            buf += fmt.nl('\t' + self.details())
+            buf += fmt.nl("\t" + self.details())
 
         return buf
 
+
 _qdisc_cache = QdiscCache()
 
+
 def get_qdisc(ifindex, handle=None, parent=None):
-    l = []
+    lst = []
 
     _qdisc_cache.refill()
 
@@ -549,14 +562,16 @@
             continue
         if (parent is not None) and (qdisc.parent != parent):
             continue
-        l.append(qdisc)
+        lst.append(qdisc)
 
-    return l
+    return lst
+
 
 _class_cache = {}
 
+
 def get_class(ifindex, parent, handle=None):
-    l = []
+    lst = []
 
     try:
         cache = _class_cache[ifindex]
@@ -571,12 +586,14 @@
             continue
         if (handle is not None) and (cl.handle != handle):
             continue
-        l.append(cl)
+        lst.append(cl)
 
-    return l
+    return lst
+
 
 _cls_cache = {}
 
+
 def get_cls(ifindex, parent, handle=None):
 
     chain = _cls_cache.get(ifindex, dict())
@@ -590,6 +607,6 @@
     cache.refill()
 
     if handle is None:
-        return [ cls for cls in cache ]
+        return [cls for cls in cache]
 
-    return [ cls for cls in cache if cls.handle == handle ]
+    return [cls for cls in cache if cls.handle == handle]
diff --git a/python/netlink/util.py b/python/netlink/util.py
index 22ed5cf..afe7ef0 100644
--- a/python/netlink/util.py
+++ b/python/netlink/util.py
@@ -10,90 +10,108 @@
 
 from __future__ import absolute_import
 
-from . import core as netlink
 from . import capi as capi
 from string import Formatter
-import types
 
-__version__ = '1.0'
+__version__ = "1.0"
 
-#rename into colored_output
+
+# rename into colored_output
 def _color(t, c):
-    return '{esc}[{color}m{text}{esc}[0m'.format(esc=b'\x1b'.decode(), color=c, text=t)
+    return "{esc}[{color}m{text}{esc}[0m".format(esc=b"\x1b".decode(), color=c, text=t)
+
 
 def black(t):
     return _color(t, 30)
 
+
 def red(t):
     return _color(t, 31)
 
+
 def green(t):
     return _color(t, 32)
 
+
 def yellow(t):
     return _color(t, 33)
 
+
 def blue(t):
     return _color(t, 34)
 
+
 def magenta(t):
     return _color(t, 35)
 
+
 def cyan(t):
     return _color(t, 36)
 
+
 def white(t):
     return _color(t, 37)
 
+
 def bold(t):
     return _color(t, 1)
 
+
 def kw(t):
     return yellow(t)
 
+
 def num(t):
     return str(t)
 
+
 def string(t):
     return t
 
+
 def addr(t):
     return str(t)
 
+
 def bad(t):
     return red(t)
 
+
 def good(t):
     return green(t)
 
+
 def title(t):
     return t
 
+
 def boolean(t):
     return str(t)
 
+
 def handle(t):
     return str(t)
 
+
 class MyFormatter(Formatter):
-    def __init__(self, obj, indent=''):
+    def __init__(self, obj, indent=""):
         self._obj = obj
         self._indent = indent
 
     def _nlattr(self, key):
         value = getattr(self._obj.__class__, key)
         if not isinstance(value, property):
-            raise ValueError('Invalid formatting string {0}'.format(key))
+            raise ValueError("Invalid formatting string {0}".format(key))
 
-        d = getattr(value.fget, 'formatinfo', dict())
+        d = getattr(value.fget, "formatinfo", dict())
 
         # value = value.fget() is exactly the same
         value = getattr(self._obj, key)
 
-        if 'fmt' in d:
-            value = d['fmt'](value)
+        if "fmt" in d:
+            value = d["fmt"](value)
 
-        title_ = d.get('title', None)
+        title_ = d.get("title", None)
 
         return title_, str(value)
 
@@ -104,13 +122,13 @@
 
         # HACK, we allow defining strings via fields to allow
         # conversions
-        if key[:2] == 's|':
+        if key[:2] == "s|":
             return key[2:]
 
-        if key[:2] == 't|':
+        if key[:2] == "t|":
             # title mode ("TITLE ATTR")
             include_title = True
-        elif key[:2] == 'a|':
+        elif key[:2] == "a|":
             # plain attribute mode ("ATTR")
             include_title = False
         else:
@@ -122,31 +140,33 @@
 
         if include_title:
             if not title_:
-                title_ = key    # fall back to key as title
-            value = '{0} {1}'.format(kw(title_), value)
+                title_ = key  # fall back to key as title
+            value = "{0} {1}".format(kw(title_), value)
 
         return value
 
     def convert_field(self, value, conversion):
-        if conversion == 'r':
+        if conversion == "r":
             return repr(value)
-        elif conversion == 's':
+        elif conversion == "s":
             return str(value)
-        elif conversion == 'k':
+        elif conversion == "k":
             return kw(value)
-        elif conversion == 'b':
+        elif conversion == "b":
             return bold(value)
         elif conversion is None:
             return value
 
-        raise ValueError('Unknown converion specifier {0!s}'.format(conversion))
+        raise ValueError("Unknown converion specifier {0!s}".format(conversion))
 
-    def nl(self, format_string=''):
-        return '\n' + self._indent + self.format(format_string)
+    def nl(self, format_string=""):
+        return "\n" + self._indent + self.format(format_string)
+
 
 NL_BYTE_RATE = 0
 NL_BIT_RATE = 1
 
+
 class Rate(object):
     def __init__(self, rate, mode=NL_BYTE_RATE):
         self._rate = rate
@@ -161,6 +181,7 @@
     def __cmp__(self, other):
         return int(self) - int(other)
 
+
 class Size(object):
     def __init__(self, size):
         self._size = size
diff --git a/python/setup.py.in b/python/setup.py.in
index 0cd35d0..83ffdb0 100644
--- a/python/setup.py.in
+++ b/python/setup.py.in
@@ -2,45 +2,54 @@
 
 from distutils.core import setup, Extension
 
-opts = ['-O', '-nodefaultctor']
-include = ['@top_builddir@/include', '@top_srcdir@/include']
-library_dirs = ['@top_builddir@/lib/.libs']
+opts = ["-O", "-nodefaultctor"]
+include = ["@top_builddir@/include", "@top_srcdir@/include"]
+library_dirs = ["@top_builddir@/lib/.libs"]
 
-netlink_capi = Extension('netlink/_capi',
-                         sources = ['@srcdir@/netlink/capi.i'],
-			 include_dirs = include,
-			 swig_opts = opts,
-			 library_dirs = library_dirs,
-			 libraries = ['nl-3'],
-			)
+netlink_capi = Extension(
+    "netlink/_capi",
+    sources=["@srcdir@/netlink/capi.i"],
+    include_dirs=include,
+    swig_opts=opts,
+    library_dirs=library_dirs,
+    libraries=["nl-3"],
+)
 
-route_capi = Extension('netlink/route/_capi',
-                         sources = ['@srcdir@/netlink/route/capi.i'],
-			 include_dirs = include,
-			 swig_opts = opts,
-			 library_dirs = library_dirs,
-			 libraries = ['nl-3', 'nl-route-3'],
-			)
+route_capi = Extension(
+    "netlink/route/_capi",
+    sources=["@srcdir@/netlink/route/capi.i"],
+    include_dirs=include,
+    swig_opts=opts,
+    library_dirs=library_dirs,
+    libraries=["nl-3", "nl-route-3"],
+)
 
-genl_capi = Extension('netlink/genl/_capi',
-			 sources = ['@srcdir@/netlink/genl/capi.i'],
-			 include_dirs = include,
-			 swig_opts = opts,
-			 library_dirs = library_dirs,
-			 libraries = ['nl-3', 'nl-genl-3'],
-			)
+genl_capi = Extension(
+    "netlink/genl/_capi",
+    sources=["@srcdir@/netlink/genl/capi.i"],
+    include_dirs=include,
+    swig_opts=opts,
+    library_dirs=library_dirs,
+    libraries=["nl-3", "nl-genl-3"],
+)
 
-setup(name = 'netlink',
-      version = '1.0',
-      description = 'Python wrapper for netlink protocols',
-      author = 'Thomas Graf',
-      author_email = 'tgraf@suug.ch',
-      url = 'http://www.infradead.org/~tgr/libnl/',
-      license = 'LGPL 2',
-      platforms = 'linux2',
-      long_description = 'Experimental python bindings for libnl',
-      ext_modules = [netlink_capi, route_capi, genl_capi],
-      package_dir = {'': '@srcdir@'},
-      packages = ['netlink', 'netlink.genl', 'netlink.route',
-		  'netlink.route.links', 'netlink.route.qdisc'],
-     )
+setup(
+    name="netlink",
+    version="1.0",
+    description="Python wrapper for netlink protocols",
+    author="Thomas Graf",
+    author_email="tgraf@suug.ch",
+    url="http://www.infradead.org/~tgr/libnl/",
+    license="LGPL 2",
+    platforms="linux2",
+    long_description="Experimental python bindings for libnl",
+    ext_modules=[netlink_capi, route_capi, genl_capi],
+    package_dir={"": "@srcdir@"},
+    packages=[
+        "netlink",
+        "netlink.genl",
+        "netlink.route",
+        "netlink.route.links",
+        "netlink.route.qdisc",
+    ],
+)
diff --git a/python/tests/test-create-bridge.py b/python/tests/test-create-bridge.py
index 3b91556..bfb1459 100644
--- a/python/tests/test-create-bridge.py
+++ b/python/tests/test-create-bridge.py
@@ -8,22 +8,22 @@
 cache = link.LinkCache()
 cache.refill(sock)
 
-testtap1 = cache['testtap1']
+testtap1 = cache["testtap1"]
 print(testtap1)
 
 lbr = link.Link()
-lbr.type = 'bridge'
-lbr.name = 'testbridge'
+lbr.type = "bridge"
+lbr.name = "testbridge"
 print(lbr)
 lbr.add()
 
 cache.refill(sock)
-lbr = cache['testbridge']
+lbr = cache["testbridge"]
 print(lbr)
 
 lbr.enslave(testtap1)
 cache.refill(sock)
-testtap1 = cache['testtap1']
+testtap1 = cache["testtap1"]
 
 print(capi.rtnl_link_is_bridge(lbr._rtnl_link))
 print(capi.rtnl_link_get_master(testtap1._rtnl_link))
diff --git a/src/genl-ctrl-list.c b/src/genl-ctrl-list.c
index 62bed3c..035b3e2 100644
--- a/src/genl-ctrl-list.c
+++ b/src/genl-ctrl-list.c
@@ -3,10 +3,12 @@
  * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
+#include "nl-default.h"
 
 #include <linux/genetlink.h>
 
+#include <netlink/cli/utils.h>
+
 static struct nl_cache *alloc_genl_family_cache(struct nl_sock *sk)
 {
 	return nl_cli_alloc_cache(sk, "generic netlink family",
diff --git a/src/idiag-socket-details.c b/src/idiag-socket-details.c
index 6f03627..9f2da41 100644
--- a/src/idiag-socket-details.c
+++ b/src/idiag-socket-details.c
@@ -1,12 +1,15 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: LGPL-2.1-only */
 /*
  * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/idiag/idiagnl.h>
 #include <netlink/idiag/msg.h>
-#include <linux/netlink.h>
 
 static void print_usage(void)
 {
diff --git a/src/lib/addr.c b/src/lib/addr.c
index a79e9b4..7b12f36 100644
--- a/src/lib/addr.c
+++ b/src/lib/addr.c
@@ -10,6 +10,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/addr.h>
 
diff --git a/src/lib/class.c b/src/lib/class.c
index d7312c3..9373b07 100644
--- a/src/lib/class.c
+++ b/src/lib/class.c
@@ -9,6 +9,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/class.h>
 
diff --git a/src/lib/cls.c b/src/lib/cls.c
index d8fd1a8..9c94b0d 100644
--- a/src/lib/cls.c
+++ b/src/lib/cls.c
@@ -9,6 +9,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/cls.h>
 #include <netlink/route/cls/ematch.h>
diff --git a/src/lib/ct.c b/src/lib/ct.c
index c00c0fb..959a850 100644
--- a/src/lib/ct.c
+++ b/src/lib/ct.c
@@ -10,6 +10,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/ct.h>
 
diff --git a/src/lib/exp.c b/src/lib/exp.c
index 48d4ea0..dcda30c 100644
--- a/src/lib/exp.c
+++ b/src/lib/exp.c
@@ -11,6 +11,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/exp.h>
 
diff --git a/src/lib/link.c b/src/lib/link.c
index d1c3e4b..67580b4 100644
--- a/src/lib/link.c
+++ b/src/lib/link.c
@@ -10,9 +10,12 @@
  * @{
  */
 
+#include "nl-default.h"
+
+#include <linux/if.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
-#include <linux/if.h>
 
 struct rtnl_link *nl_cli_link_alloc(void)
 {
diff --git a/src/lib/neigh.c b/src/lib/neigh.c
index 5b44f47..a4b211e 100644
--- a/src/lib/neigh.c
+++ b/src/lib/neigh.c
@@ -10,6 +10,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/neigh.h>
 
diff --git a/src/lib/nh.c b/src/lib/nh.c
new file mode 100644
index 0000000..c1f5137
--- /dev/null
+++ b/src/lib/nh.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+/**
+ * @ingroup cli
+ * @defgroup cli_nh nhs
+ *
+ * @{
+ */
+
+#include "nl-default.h"
+
+#include <linux/if.h>
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/nh.h>
+#include <netlink/route/nh.h>
+
+struct rtnl_nh *nl_cli_nh_alloc(void)
+{
+	struct rtnl_nh *nh;
+
+	nh = rtnl_nh_alloc();
+	if (!nh)
+		nl_cli_fatal(ENOMEM, "Unable to allocate nh object");
+
+	return nh;
+}
+
+struct nl_cache *nl_cli_nh_alloc_cache_family_flags(struct nl_sock *sock,
+						    int family,
+						    unsigned int flags)
+{
+	struct nl_cache *cache;
+	int err;
+
+	if ((err = rtnl_nh_alloc_cache(sock, family, &cache)) < 0)
+		nl_cli_fatal(err, "Unable to allocate nh cache: %s",
+			     nl_geterror(err));
+
+	nl_cache_mngt_provide(cache);
+
+	return cache;
+}
+
+struct nl_cache *nl_cli_nh_alloc_cache_family(struct nl_sock *sock, int family)
+{
+	return nl_cli_nh_alloc_cache_family_flags(sock, family, 0);
+}
+
+struct nl_cache *nl_cli_nh_alloc_cache(struct nl_sock *sock)
+{
+	return nl_cli_nh_alloc_cache_family(sock, AF_UNSPEC);
+}
+
+struct nl_cache *nl_cli_nh_alloc_cache_flags(struct nl_sock *sock,
+					     unsigned int flags)
+{
+	return nl_cli_nh_alloc_cache_family_flags(sock, AF_UNSPEC, flags);
+}
+
+/** @} */
diff --git a/src/lib/qdisc.c b/src/lib/qdisc.c
index beb83cc..659594a 100644
--- a/src/lib/qdisc.c
+++ b/src/lib/qdisc.c
@@ -9,6 +9,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/qdisc.h>
 #include <netlink/route/class.h>
diff --git a/src/lib/route.c b/src/lib/route.c
index 7297a2f..d814950 100644
--- a/src/lib/route.c
+++ b/src/lib/route.c
@@ -10,6 +10,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/route.h>
 
diff --git a/src/lib/rule.c b/src/lib/rule.c
index 6ef9321..8a54e73 100644
--- a/src/lib/rule.c
+++ b/src/lib/rule.c
@@ -10,6 +10,8 @@
  * @{
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/rule.h>
 
diff --git a/src/lib/tc.c b/src/lib/tc.c
index ba3de18..3bed636 100644
--- a/src/lib/tc.c
+++ b/src/lib/tc.c
@@ -3,9 +3,12 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
-#include <netlink-private/route/tc-api.h>
+
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
 
 /**
  * @ingroup cli
diff --git a/src/lib/utils.c b/src/lib/utils.c
index cbcdafe..2839e27 100644
--- a/src/lib/utils.c
+++ b/src/lib/utils.c
@@ -15,15 +15,15 @@
  * accordingly via nl_cli_fatal().
  */
 
-#include <netlink/cli/utils.h>
+#include "nl-default.h"
+
 #include <locale.h>
-
-#include "lib/defs.h"
-
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
 
+#include <netlink/cli/utils.h>
+
 /**
  * Parse a text based 32 bit unsigned integer argument
  * @arg arg		Integer in text form.
diff --git a/src/nf-ct-add.c b/src/nf-ct-add.c
index 632acd9..cefa837 100644
--- a/src/nf-ct-add.c
+++ b/src/nf-ct-add.c
@@ -5,11 +5,13 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/ct.h>
+#include "nl-default.h"
 
 #include <linux/rtnetlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/ct.h>
+
 static int quiet = 0;
 
 static void print_usage(void)
diff --git a/src/nf-ct-events.c b/src/nf-ct-events.c
index 68f9ac0..cd69045 100644
--- a/src/nf-ct-events.c
+++ b/src/nf-ct-events.c
@@ -3,13 +3,15 @@
  * Copyright (c) 2018 Avast software
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/ct.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/ct.h>
+
 struct private_nl_object
 {
 	int			ce_refcnt;
diff --git a/src/nf-ct-list.c b/src/nf-ct-list.c
index 692c24b..3b34572 100644
--- a/src/nf-ct-list.c
+++ b/src/nf-ct-list.c
@@ -5,11 +5,13 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/ct.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/ct.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nf-exp-add.c b/src/nf-exp-add.c
index ae74528..68f0898 100644
--- a/src/nf-exp-add.c
+++ b/src/nf-exp-add.c
@@ -6,11 +6,13 @@
  * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/exp.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/exp.h>
+
 static int quiet = 0;
 
 static void print_usage(void)
diff --git a/src/nf-exp-delete.c b/src/nf-exp-delete.c
index 9d1eea9..a57a69d 100644
--- a/src/nf-exp-delete.c
+++ b/src/nf-exp-delete.c
@@ -6,11 +6,13 @@
  * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/exp.h>
+#include "nl-default.h"
 
 #include <linux/rtnetlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/exp.h>
+
 static int quiet = 0;
 
 static void print_usage(void)
diff --git a/src/nf-exp-list.c b/src/nf-exp-list.c
index 25fd51f..f469fea 100644
--- a/src/nf-exp-list.c
+++ b/src/nf-exp-list.c
@@ -6,11 +6,13 @@
  * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/exp.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/exp.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nf-log.c b/src/nf-log.c
index c9ad560..17f73a8 100644
--- a/src/nf-log.c
+++ b/src/nf-log.c
@@ -5,14 +5,16 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
+#include "nl-default.h"
+
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/log.h>
 
-#include <linux/netfilter/nfnetlink_log.h>
-#include <linux/netlink.h>
-
 static struct nfnl_log *alloc_log(void)
 {
 	struct nfnl_log *log;
diff --git a/src/nf-monitor.c b/src/nf-monitor.c
index 1f67289..21f8edd 100644
--- a/src/nf-monitor.c
+++ b/src/nf-monitor.c
@@ -5,12 +5,14 @@
  * Copyright (c) 2007 Secure Computing Corporation
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/netfilter/nfnl.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/netfilter/nfnl.h>
+
 static void obj_input(struct nl_object *obj, void *arg)
 {
 	struct nl_dump_params dp = {
diff --git a/src/nf-queue.c b/src/nf-queue.c
index ec15f63..38f20ad 100644
--- a/src/nf-queue.c
+++ b/src/nf-queue.c
@@ -4,17 +4,18 @@
  * Copyright (c) 2010  Karl Hiramoto <karl@hiramoto.org>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
-#include <netinet/in.h>
+#include "nl-default.h"
+
 #include <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink_queue.h>
+#include <linux/netlink.h>
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
 #include <netlink/netfilter/nfnl.h>
 #include <netlink/netfilter/queue.h>
 #include <netlink/netfilter/queue_msg.h>
 
-#include <linux/netlink.h>
-
 static struct nl_sock *nf_sock;
 
 static struct nfnl_queue *alloc_queue(void)
diff --git a/src/nl-addr-add.c b/src/nl-addr-add.c
index 3560f4d..3b73cb2 100644
--- a/src/nl-addr-add.c
+++ b/src/nl-addr-add.c
@@ -1,14 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: LGPL-2.1-only */
 /*
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/addr.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0;
 
 static void print_usage(void)
diff --git a/src/nl-addr-delete.c b/src/nl-addr-delete.c
index a8887ac..58dd439 100644
--- a/src/nl-addr-delete.c
+++ b/src/nl-addr-delete.c
@@ -1,14 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: LGPL-2.1-only */
 /*
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/addr.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static struct nl_sock *sock;
 static int interactive = 0, default_yes = 0, quiet = 0;
 static int deleted = 0;
diff --git a/src/nl-addr-list.c b/src/nl-addr-list.c
index d80d862..00df1aa 100644
--- a/src/nl-addr-list.c
+++ b/src/nl-addr-list.c
@@ -1,14 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: LGPL-2.1-only */
 /*
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/addr.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-class-add.c b/src/nl-class-add.c
index d3f9230..ac37daa 100644
--- a/src/nl-class-add.c
+++ b/src/nl-class-add.c
@@ -3,15 +3,17 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/qdisc.h>
 #include <netlink/cli/class.h>
 #include <netlink/cli/link.h>
 
-#include <netlink-private/route/tc-api.h>
-
-#include <linux/netlink.h>
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
 
 static int quiet = 0;
 
diff --git a/src/nl-class-delete.c b/src/nl-class-delete.c
index 1747a65..88dc59e 100644
--- a/src/nl-class-delete.c
+++ b/src/nl-class-delete.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/class.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0;
 static struct nl_sock *sock;
 
diff --git a/src/nl-class-list.c b/src/nl-class-list.c
index ba8e154..8b5cd6c 100644
--- a/src/nl-class-list.c
+++ b/src/nl-class-list.c
@@ -3,13 +3,15 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/class.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static struct nl_sock *sock;
 
 static struct nl_dump_params params = {
diff --git a/src/nl-classid-lookup.c b/src/nl-classid-lookup.c
index 7b82c37..397fcb4 100644
--- a/src/nl-classid-lookup.c
+++ b/src/nl-classid-lookup.c
@@ -3,9 +3,12 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
+#include "nl-default.h"
+
 #include <linux/pkt_sched.h>
 
+#include <netlink/cli/utils.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c
index a29beb7..b583872 100644
--- a/src/nl-cls-add.c
+++ b/src/nl-cls-add.c
@@ -1,16 +1,18 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-License-Identifier: LGPL-2.1-only */
 /*
  * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/cls.h>
 #include <netlink/cli/link.h>
 
-#include <netlink-private/route/tc-api.h>
-
-#include <linux/netlink.h>
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
 
 static int quiet = 0;
 
@@ -109,7 +111,7 @@
 		case 'v': nl_cli_print_version(); break;
 		case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
 		case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
-		case 'i': id = strdup(optarg); break;
+		case 'i': free(id); id = strdup(optarg); break;
 		case ARG_UPDATE: flags = NLM_F_CREATE; break;
 		case ARG_UPDATE_ONLY: flags = 0; break;
 		case ARG_MTU: nl_cli_tc_parse_mtu(tc, optarg); break;
diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c
index 20079a2..ca8e370 100644
--- a/src/nl-cls-delete.c
+++ b/src/nl-cls-delete.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/cls.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0;
 static struct nl_sock *sock;
 
diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c
index 65757d0..5a4e638 100644
--- a/src/nl-cls-list.c
+++ b/src/nl-cls-list.c
@@ -3,13 +3,15 @@
  * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/cls.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static struct nl_sock *sock;
 
 static struct nl_dump_params params = {
diff --git a/src/nl-fib-lookup.c b/src/nl-fib-lookup.c
index 4239063..a1470c7 100644
--- a/src/nl-fib-lookup.c
+++ b/src/nl-fib-lookup.c
@@ -3,10 +3,12 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
+#include "nl-default.h"
 
 #include <linux/rtnetlink.h>
 
+#include <netlink/cli/utils.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-link-enslave.c b/src/nl-link-enslave.c
index ba4817a..5c6dc02 100644
--- a/src/nl-link-enslave.c
+++ b/src/nl-link-enslave.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
 #include <netlink/route/link/bonding.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct nl_sock *sock;
diff --git a/src/nl-link-ifindex2name.c b/src/nl-link-ifindex2name.c
index 05eb788..200c9f2 100644
--- a/src/nl-link-ifindex2name.c
+++ b/src/nl-link-ifindex2name.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static void print_usage(void)
 {
 	printf("Usage: nl-link-ifindex2name <ifindex>\n");
diff --git a/src/nl-link-list.c b/src/nl-link-list.c
index e07bd43..aec96cb 100644
--- a/src/nl-link-list.c
+++ b/src/nl-link-list.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-link-name2ifindex.c b/src/nl-link-name2ifindex.c
index 3ff774e..e35ee27 100644
--- a/src/nl-link-name2ifindex.c
+++ b/src/nl-link-name2ifindex.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static void print_usage(void)
 {
 	printf("Usage: nl-link-name2ifindex <name>\n");
diff --git a/src/nl-link-release.c b/src/nl-link-release.c
index 1c869ad..9d04413 100644
--- a/src/nl-link-release.c
+++ b/src/nl-link-release.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
 #include <netlink/route/link/bonding.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct nl_sock *sock;
diff --git a/src/nl-link-set.c b/src/nl-link-set.c
index 5b54da0..c301542 100644
--- a/src/nl-link-set.c
+++ b/src/nl-link-set.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/if.h>
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static struct nl_sock *sock;
 static int quiet = 0;
 
diff --git a/src/nl-link-stats.c b/src/nl-link-stats.c
index d993f71..07e5e1c 100644
--- a/src/nl-link-stats.c
+++ b/src/nl-link-stats.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-list-caches.c b/src/nl-list-caches.c
index 966f13a..4c2564a 100644
--- a/src/nl-list-caches.c
+++ b/src/nl-list-caches.c
@@ -3,9 +3,13 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
 static void print_usage(void)
 {
 	fprintf(stderr, "Usage: nl-list-caches\n");
diff --git a/src/nl-list-sockets.c b/src/nl-list-sockets.c
index b69b2c2..bb27df0 100644
--- a/src/nl-list-sockets.c
+++ b/src/nl-list-sockets.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 
 #define PROC_NETLINK "/proc/net/netlink"
diff --git a/src/nl-monitor.c b/src/nl-monitor.c
index 86294fb..60a02d2 100644
--- a/src/nl-monitor.c
+++ b/src/nl-monitor.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/rtnetlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
 #include <netlink/cli/mdb.h>
 
-#include <linux/rtnetlink.h>
-
 static const struct {
 	enum rtnetlink_groups gr_id;
 	const char* gr_name;
diff --git a/src/nl-neigh-add.c b/src/nl-neigh-add.c
index cd6063e..d4d926d 100644
--- a/src/nl-neigh-add.c
+++ b/src/nl-neigh-add.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/neigh.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0;
 
 static void print_usage(void)
diff --git a/src/nl-neigh-delete.c b/src/nl-neigh-delete.c
index 6f1ffef..29effcb 100644
--- a/src/nl-neigh-delete.c
+++ b/src/nl-neigh-delete.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/neigh.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0;
 static struct nl_sock *sock;
 
diff --git a/src/nl-neigh-list.c b/src/nl-neigh-list.c
index 2664c8f..80fce0b 100644
--- a/src/nl-neigh-list.c
+++ b/src/nl-neigh-list.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/neigh.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-neightbl-list.c b/src/nl-neightbl-list.c
index 5a5b0a0..596b6ee 100644
--- a/src/nl-neightbl-list.c
+++ b/src/nl-neightbl-list.c
@@ -3,11 +3,13 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/cli/link.h>
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+#include <netlink/cli/link.h>
+
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-nh-list.c b/src/nl-nh-list.c
new file mode 100644
index 0000000..18fc5f4
--- /dev/null
+++ b/src/nl-nh-list.c
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/nh.h>
+#include <netlink/route/nh.h>
+
+static void print_usage(void)
+{
+	printf("Usage: nl-nh-list [OPTIONS]... \n"
+	       "\n"
+	       "OPTIONS\n"
+	       "     --details             Show detailed information of each link\n"
+	       " -h, --help                Show this help text.\n"
+	       " -v, --version             Show versioning information.\n"
+	       "\n"
+	       " -n, --name=NAME	    Name of link\n"
+	       " -i, --index               Interface index (unique identifier)\n"
+	       "     --family=NAME         Link address family\n");
+	exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+	struct nl_sock *sock;
+	struct nl_cache *link_cache;
+	struct nl_dump_params params = {
+		.dp_type = NL_DUMP_LINE,
+		.dp_fd = stdout,
+	};
+
+	sock = nl_cli_alloc_socket();
+	nl_cli_connect(sock, NETLINK_ROUTE);
+
+	for (;;) {
+		int c, optidx = 0;
+		enum {
+			ARG_FAMILY = 257,
+			ARG_DETAILS,
+		};
+		static struct option long_opts[] = { { "details", 0, 0,
+						       ARG_DETAILS },
+						     { "help", 0, 0, 'h' },
+						     { "version", 0, 0, 'v' },
+						     { "name", 1, 0, 'n' },
+						     { 0, 0, 0, 0 } };
+
+		c = getopt_long(argc, argv, "hvn:i:", long_opts, &optidx);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case ARG_DETAILS:
+			params.dp_type = NL_DUMP_DETAILS;
+			break;
+		case 'h':
+			print_usage();
+			break;
+		case 'v':
+			nl_cli_print_version();
+			break;
+		}
+	}
+
+	link_cache = nl_cli_nh_alloc_cache(sock);
+
+	nl_cache_dump(link_cache, &params);
+
+	return 0;
+}
diff --git a/src/nl-pktloc-lookup.c b/src/nl-pktloc-lookup.c
index 606b2db..90502a3 100644
--- a/src/nl-pktloc-lookup.c
+++ b/src/nl-pktloc-lookup.c
@@ -3,11 +3,12 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
-#include <netlink/cli/utils.h>
-#include <netlink/route/pktloc.h>
+#include "nl-default.h"
+
 #include <linux/tc_ematch/tc_em_cmp.h>
 
-#include "netlink-private/utils.h"
+#include <netlink/cli/utils.h>
+#include <netlink/route/pktloc.h>
 
 static void print_usage(void)
 {
diff --git a/src/nl-qdisc-add.c b/src/nl-qdisc-add.c
index 8cd317c..40b9546 100644
--- a/src/nl-qdisc-add.c
+++ b/src/nl-qdisc-add.c
@@ -3,14 +3,16 @@
  * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/qdisc.h>
 #include <netlink/cli/link.h>
 
-#include <netlink-private/route/tc-api.h>
-
-#include <linux/netlink.h>
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
 
 static int quiet = 0;
 
diff --git a/src/nl-qdisc-delete.c b/src/nl-qdisc-delete.c
index 299fd48..8c89372 100644
--- a/src/nl-qdisc-delete.c
+++ b/src/nl-qdisc-delete.c
@@ -3,13 +3,15 @@
  * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/qdisc.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0, default_yes = 0, deleted = 0, interactive = 0;
 static struct nl_sock *sock;
 
diff --git a/src/nl-qdisc-list.c b/src/nl-qdisc-list.c
index d1825da..f41cca2 100644
--- a/src/nl-qdisc-list.c
+++ b/src/nl-qdisc-list.c
@@ -3,6 +3,11 @@
  * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/pkt_sched.h>
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/tc.h>
 #include <netlink/cli/qdisc.h>
@@ -10,9 +15,6 @@
 #include <netlink/cli/cls.h>
 #include <netlink/cli/link.h>
 
-#include <linux/pkt_sched.h>
-#include <linux/netlink.h>
-
 #define NUM_INDENT 4
 
 static struct nl_sock *sock;
diff --git a/src/nl-route-add.c b/src/nl-route-add.c
index 4e96ab0..04fca9f 100644
--- a/src/nl-route-add.c
+++ b/src/nl-route-add.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/route.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int quiet = 0;
 static struct nl_cache *link_cache, *route_cache;
 
diff --git a/src/nl-route-delete.c b/src/nl-route-delete.c
index 9b4366c..17d50b5 100644
--- a/src/nl-route-delete.c
+++ b/src/nl-route-delete.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/route.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static int interactive = 0, default_yes = 0, quiet = 0;
 static int deleted = 0;
 static struct nl_sock *sock;
diff --git a/src/nl-route-get.c b/src/nl-route-get.c
index b49ba4c..ce845b2 100644
--- a/src/nl-route-get.c
+++ b/src/nl-route-get.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/rtnetlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/route.h>
 #include <netlink/cli/link.h>
 
-#include <linux/rtnetlink.h>
-
 static void print_usage(void)
 {
 	printf("Usage: nl-route-get <addr>\n");
diff --git a/src/nl-route-list.c b/src/nl-route-list.c
index 1b293ed..284e240 100644
--- a/src/nl-route-list.c
+++ b/src/nl-route-list.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/route.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-rule-list.c b/src/nl-rule-list.c
index fe87dfe..b31c575 100644
--- a/src/nl-rule-list.c
+++ b/src/nl-rule-list.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/rule.h>
 #include <netlink/cli/link.h>
 
-#include <linux/netlink.h>
-
 static void print_usage(void)
 {
 	printf(
diff --git a/src/nl-tctree-list.c b/src/nl-tctree-list.c
index 16f6f00..63dcc15 100644
--- a/src/nl-tctree-list.c
+++ b/src/nl-tctree-list.c
@@ -3,14 +3,16 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+#include <linux/pkt_sched.h>
+
 #include <netlink/cli/utils.h>
 #include <netlink/cli/link.h>
 #include <netlink/cli/qdisc.h>
 #include <netlink/cli/class.h>
 
-#include <linux/netlink.h>
-#include <linux/pkt_sched.h>
-
 static struct nl_sock *sock;
 static struct nl_cache *qdisc_cache, *class_cache;
 static struct nl_dump_params params = {
diff --git a/src/nl-util-addr.c b/src/nl-util-addr.c
index de92302..fc8ebdd 100644
--- a/src/nl-util-addr.c
+++ b/src/nl-util-addr.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <netlink/cli/utils.h>
 
 int main(int argc, char *argv[])
diff --git a/tests/check-all.c b/tests/check-all.c
index aff16cb..e8a0e80 100644
--- a/tests/check-all.c
+++ b/tests/check-all.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <check.h>
 
 #include "cksuite-all.h"
diff --git a/tests/check-direct.c b/tests/check-direct.c
index f40bcee..db1f48d 100644
--- a/tests/check-direct.c
+++ b/tests/check-direct.c
@@ -1,12 +1,14 @@
 /* SPDX-License-Identifier: LGPL-2.1-only */
 
+#include "nl-default.h"
+
 #include <check.h>
 
-#include "linux/snmp.h"
-#include "netlink-private/utils.h"
-#include "netlink-private/route/utils.h"
+#include <linux/snmp.h>
 
-#include "netlink/route/link.h"
+#include <netlink/route/link.h>
+
+#include "nl-priv-static-route/nl-priv-static-route.h"
 
 START_TEST(static_checks)
 {
@@ -39,6 +41,15 @@
 			ck_assert_int_le(i, RTNL_LINK_STATS_MAX);
 		ck_assert_int_eq(i, rtnl_link_str2stat(s));
 	}
+
+	ck_assert_int_eq(nl_str2ip_proto(""), -NLE_OBJ_NOTFOUND);
+	ck_assert_int_eq(nl_str2ip_proto("5"), 5);
+	ck_assert_int_eq(nl_str2ip_proto("  13 "), -NLE_OBJ_NOTFOUND);
+	ck_assert_int_eq(nl_str2ip_proto("13"), 13);
+	ck_assert_int_eq(nl_str2ip_proto("0x13"), 0x13);
+	ck_assert_int_eq(nl_str2ip_proto("0342"), 0342);
+	ck_assert_int_eq(nl_str2ip_proto("2147483647"), 2147483647);
+	ck_assert_int_eq(nl_str2ip_proto("2147483648"), -NLE_OBJ_NOTFOUND);
 }
 END_TEST
 
diff --git a/tests/cksuite-all-addr.c b/tests/cksuite-all-addr.c
index f395351..f4ee0dd 100644
--- a/tests/cksuite-all-addr.c
+++ b/tests/cksuite-all-addr.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <check.h>
 #include <netlink/addr.h>
 #include <netlink/route/addr.h>
diff --git a/tests/cksuite-all-attr.c b/tests/cksuite-all-attr.c
index 824a596..b4ac61f 100644
--- a/tests/cksuite-all-attr.c
+++ b/tests/cksuite-all-attr.c
@@ -3,15 +3,17 @@
  * Copyright (c) 2013 Thomas Graf <tgraf@suug.ch>
  */
 
+#include "nl-default.h"
+
 #include <linux/netlink.h>
 #include <linux/if_ether.h>
 
+#include <netlink/attr.h>
+#include <netlink/msg.h>
+#include <netlink/route/cls/u32.h>
+
 #include "cksuite-all.h"
-#include "netlink/attr.h"
-#include "netlink/msg.h"
-#include "netlink/route/cls/u32.h"
-#include "netlink-private/route/tc-api.h"
-#include "netlink-private/nl-auto.h"
+#include "nl-aux-route/nl-route.h"
 
 START_TEST(attr_size)
 {
@@ -65,7 +67,7 @@
 
 	nlh = nlmsg_hdr(msg);
 	i = 1;
-	nlmsg_for_each_attr (a, nlh, 0, rem) {
+	nlmsg_for_each_attr(a, nlh, 0, rem) {
 		ck_assert_msg(nla_type(a) == i, "Expected attribute %d", i);
 		i++;
 		ck_assert_msg(nla_get_u32(a) == i,
diff --git a/tests/cksuite-all-ematch-tree-clone.c b/tests/cksuite-all-ematch-tree-clone.c
index f9d17a9..c48a9dd 100644
--- a/tests/cksuite-all-ematch-tree-clone.c
+++ b/tests/cksuite-all-ematch-tree-clone.c
@@ -1,12 +1,18 @@
-#include <linux/netlink.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <stdio.h>
 #include <time.h>
 #include <check.h>
 
-#include "netlink-private/types.h"
-#include "netlink/route/cls/ematch.h"
+#include <linux/netlink.h>
+
+#include <netlink/route/cls/ematch.h>
+
 #include "cksuite-all.h"
-#include "netlink-private/nl-auto.h"
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
 
 #define MAX_DEPTH 6
 #define MAX_CHILDREN 5
@@ -32,12 +38,6 @@
 	return ret;
 }
 
-static long int generate_random(long int max)
-{
-	srandom(time(NULL) + id);
-	return (random() % max);
-}
-
 static int build_children(struct nl_list_head *parent)
 {
 	int i, num = 0;
@@ -51,7 +51,7 @@
 		return 0;
 	}
 
-	num = generate_random(MAX_CHILDREN + 1);
+	num = _nltst_rand_u32() % ((unsigned)(MAX_CHILDREN + 1));
 	for (i = 0; i < num; ++i) {
 		child = rtnl_ematch_alloc();
 		if (!child) {
@@ -76,7 +76,7 @@
 {
 	struct rtnl_ematch *pos = NULL;
 
-	nl_list_for_each_entry (pos, head, e_list) {
+	nl_list_for_each_entry(pos, head, e_list) {
 		if (!nl_list_empty(&pos->e_childs))
 			dump_ematch_list(&pos->e_childs, result, index);
 		result[*index] = pos->e_id;
diff --git a/tests/cksuite-all-netns.c b/tests/cksuite-all-netns.c
index 97f3a70..c6a5ce2 100644
--- a/tests/cksuite-all-netns.c
+++ b/tests/cksuite-all-netns.c
@@ -4,13 +4,12 @@
  * Copyright (c) 2018 Red Hat, Inc.
  */
 
-#include <stdlib.h>
-#include <stdbool.h>
+#include "nl-default.h"
+
 #include <linux/netlink.h>
 
-#include "netlink-private/utils.h"
-#include "netlink/route/link.h"
-#include "netlink/route/link/sit.h"
+#include <netlink/route/link.h>
+#include <netlink/route/link/sit.h>
 #include <netlink/route/link/bonding.h>
 #include <netlink/route/link/bridge.h>
 #include <netlink/route/link/ip6tnl.h>
diff --git a/tests/cksuite-all.h b/tests/cksuite-all.h
index c4b1d8e..26e9b5c 100644
--- a/tests/cksuite-all.h
+++ b/tests/cksuite-all.h
@@ -2,6 +2,7 @@
 #define __LIBNL3_TESTS_CHECK_ALL_H__
 
 #include <check.h>
+
 #include "nl-test-util.h"
 
 Suite *make_nl_attr_suite(void);
diff --git a/tests/nl-test-util.c b/tests/nl-test-util.c
index 1f67ac8..52188a0 100644
--- a/tests/nl-test-util.c
+++ b/tests/nl-test-util.c
@@ -1,22 +1,20 @@
 /* SPDX-License-Identifier: LGPL-2.1-only */
 
+#include "nl-default.h"
+
 #include "nl-test-util.h"
 
 #include <fcntl.h>
-#include <inttypes.h>
-#include <limits.h>
 #include <sched.h>
-#include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <sys/mount.h>
-#include <unistd.h>
 
-#include "netlink-private/utils.h"
-#include "netlink/netlink.h"
-#include "netlink/route/link.h"
-#include "netlink/route/route.h"
-#include "netlink/socket.h"
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+#include <netlink/route/route.h>
+#include <netlink/socket.h>
+
+#include "nl-aux-route/nl-route.h"
 
 /*****************************************************************************/
 
@@ -87,12 +85,12 @@
 
 /*****************************************************************************/
 
-#define _assert_nltst_netns(nsdata)                                            \
-	do {                                                                   \
-		const struct nltst_netns *_nsdata = (nsdata);                  \
-                                                                               \
-		ck_assert_ptr_nonnull(_nsdata);                                \
-		ck_assert_int_eq(_nsdata->canary, _CANARY);                    \
+#define _assert_nltst_netns(nsdata)                           \
+	do {                                                  \
+		const struct nltst_netns *_nsdata = (nsdata); \
+                                                              \
+		ck_assert_ptr_nonnull(_nsdata);               \
+		ck_assert_int_eq(_nsdata->canary, _CANARY);   \
 	} while (0)
 
 static struct {
diff --git a/tests/nl-test-util.h b/tests/nl-test-util.h
index 0ff9752..ee4bd96 100644
--- a/tests/nl-test-util.h
+++ b/tests/nl-test-util.h
@@ -3,18 +3,15 @@
 #ifndef __NL_TEST_UTIL_H__
 #define __NL_TEST_UTIL_H__
 
-#include <errno.h>
 #include <sys/stat.h>
 #include <check.h>
-#include <string.h>
-#include <stdbool.h>
-#include <arpa/inet.h>
 
-#include "netlink/object.h"
-#include "netlink/cache.h"
+#include <netlink/object.h>
+#include <netlink/cache.h>
 
-#include "netlink-private/nl-auto.h"
-#include "netlink-private/utils.h"
+#include "base/nl-base-utils.h"
+#include "nl-aux-core/nl-core.h"
+#include "nl-aux-route/nl-route.h"
 
 /*****************************************************************************/
 
diff --git a/tests/test-cache-mngr.c b/tests/test-cache-mngr.c
index 9761452..cc0e15b 100644
--- a/tests/test-cache-mngr.c
+++ b/tests/test-cache-mngr.c
@@ -1,22 +1,46 @@
-#include <netlink/netlink.h>
-#include <netlink/cache.h>
-#include <netlink/cli/utils.h>
-#include <signal.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
 
-#include <netlink-private/cache-api.h>
+#include "nl-default.h"
+
+#include <signal.h>
+#include <sys/time.h>
+#include <time.h>
 
 #include <linux/netlink.h>
 
-static int quit = 0;
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/cli/utils.h>
 
-static struct nl_dump_params dp = {
+static int quit = 0;
+static int change = 1;
+static int print_ts = 0;
+
+static struct nl_dump_params params = {
 	.dp_type = NL_DUMP_LINE,
 };
 
 
+static void print_timestamp(FILE *fp)
+{
+	struct timeval tv;
+	char tshort[40];
+	struct tm *tm;
+	struct tm tm_buf;
+
+	gettimeofday(&tv, NULL);
+	tm = localtime_r(&tv.tv_sec, &tm_buf);
+
+	strftime(tshort, sizeof(tshort), "%Y-%m-%dT%H:%M:%S", tm);
+	fprintf(fp, "[%s.%06ld] ", tshort, tv.tv_usec);
+}
+
 static void change_cb(struct nl_cache *cache, struct nl_object *obj,
 		      int action, void *data)
 {
+	if (print_ts)
+		print_timestamp(stdout);
+
 	if (action == NL_ACT_NEW)
 		printf("NEW ");
 	else if (action == NL_ACT_DEL)
@@ -24,7 +48,10 @@
 	else if (action == NL_ACT_CHANGE)
 		printf("CHANGE ");
 
-	nl_object_dump(obj, &dp);
+	nl_object_dump(obj, &params);
+	fflush(stdout);
+
+	change = 1;
 }
 
 static void sigint(int arg)
@@ -32,34 +59,128 @@
 	quit = 1;
 }
 
+static void print_usage(FILE* stream, const char *name)
+{
+	fprintf(stream,
+		"Usage: %s [OPTIONS]... <cache name>... \n"
+		"\n"
+		"OPTIONS\n"
+		" -f, --format=TYPE      Output format { brief | details | stats }\n"
+		"                        Default: brief\n"
+		" -d, --dump             Dump cache content after a change.\n"
+		" -i, --interval=TIME    Dump cache content after TIME seconds when there is no\n"
+		"                        change; 0 to disable. Default: 1\n"
+		" -I, --iter             Iterate over all address families when updating caches.\n"
+		" -t, --tshort           Print a short timestamp before change messages.\n"
+		" -h, --help             Show this help text.\n"
+		, name);
+}
+
 int main(int argc, char *argv[])
 {
+	bool dump_on_change = false, dump_on_timeout = true, iter = false;
 	struct nl_cache_mngr *mngr;
-	struct nl_cache *cache;
-	int err, i;
+	int timeout = 1000, err;
 
-	dp.dp_fd = stdout;
+	for (;;) {
+		static struct option long_opts[] = {
+			{ "format", required_argument, 0, 'f' },
+			{ "dump", no_argument, 0, 'd' },
+			{ "interval", required_argument, 0, 'i' },
+			{ "iter", no_argument, 0, 'I' },
+			{ "tshort", no_argument, 0, 't' },
+			{ "help", 0, 0, 'h' },
+			{ 0, 0, 0, 0 }
+		};
+		int c;
 
-	signal(SIGINT, sigint);
+		c = getopt_long(argc, argv, "hf:di:It", long_opts, NULL);
+		if (c == -1)
+			break;
+
+		switch (c) {
+			char *endptr;
+			long interval;
+
+		case 'f':
+			params.dp_type = nl_cli_parse_dumptype(optarg);
+			break;
+
+		case 'd':
+			dump_on_change = true;
+			break;
+
+		case 'i':
+			errno = 0;
+			interval = strtol(optarg, &endptr, 0);
+			if (interval < 0 || errno || *endptr) {
+				nl_cli_fatal(EINVAL, "Invalid interval \"%s\".\n",
+					     optarg);
+				exit(1);
+			}
+			if (!interval) {
+				dump_on_timeout = false;
+			} else {
+				timeout = interval * 1000;
+			}
+
+			break;
+
+		case 'I':
+			iter = true;
+			break;
+
+		case 't':
+			print_ts = true;
+			break;
+
+		case 'h':
+			print_usage(stdout, argv[0]);
+			exit(0);
+
+		case '?':
+			print_usage(stderr, argv[0]);
+			exit(1);
+		}
+	}
 
 	err = nl_cache_mngr_alloc(NULL, NETLINK_ROUTE, NL_AUTO_PROVIDE, &mngr);
 	if (err < 0)
 		nl_cli_fatal(err, "Unable to allocate cache manager: %s",
 			     nl_geterror(err));
 
-	for (i = 1; i < argc; i++) {
-		err = nl_cache_mngr_add(mngr, argv[i], &change_cb, NULL, &cache);
+	while (optind < argc) {
+		struct nl_cache *cache;
+
+		err = nl_cache_alloc_name(argv[optind], &cache);
+		if (err < 0)
+			nl_cli_fatal(err, "Couldn't add cache %s: %s\n",
+				     argv[optind], nl_geterror(err));
+
+		if (iter)
+			nl_cache_set_flags(cache, NL_CACHE_AF_ITER);
+
+		err = nl_cache_mngr_add_cache(mngr, cache, &change_cb, NULL);
 		if (err < 0)
 			nl_cli_fatal(err, "Unable to add cache %s: %s",
-				     argv[i], nl_geterror(err));
+				     argv[optind], nl_geterror(err));
+
+		optind++;
 	}
 
+	params.dp_fd = stdout;
+	signal(SIGINT, sigint);
+
 	while (!quit) {
-		int err = nl_cache_mngr_poll(mngr, 1000);
+		err = nl_cache_mngr_poll(mngr, timeout);
 		if (err < 0 && err != -NLE_INTR)
 			nl_cli_fatal(err, "Polling failed: %s", nl_geterror(err));
 
-		nl_cache_mngr_info(mngr, &dp);
+		if (dump_on_timeout || (dump_on_change && change)) {
+			nl_cache_mngr_info(mngr, &params);
+			fflush(stdout);
+			change = 0;
+		}
 	}
 
 	nl_cache_mngr_free(mngr);
diff --git a/tests/test-complex-HTB-with-hash-filters.c b/tests/test-complex-HTB-with-hash-filters.c
index 016d467..713ed3e 100644
--- a/tests/test-complex-HTB-with-hash-filters.c
+++ b/tests/test-complex-HTB-with-hash-filters.c
@@ -3,6 +3,14 @@
  * Copyright (c) 2011 Adrian Ban <adrian.ban@mantech.ro>
  */
 
+#include "nl-default.h"
+
+#include <stdio.h>
+
+#include <linux/if_ether.h>
+#include <linux/pkt_cls.h>
+#include <linux/netlink.h>
+
 #include <netlink/route/link.h>
 #include <netlink/route/tc.h>
 #include <netlink/route/qdisc.h>
@@ -11,17 +19,7 @@
 #include <netlink/route/cls/u32.h>
 #include <netlink/route/classifier.h>
 #include <netlink/route/class.h>
-#include <linux/if_ether.h>
-#include <linux/pkt_cls.h>
-
 #include <netlink/attr.h>
-//#include "include/rtnl_u32.h"
-
-#include <stdio.h>
-#include <string.h>
-//#include "include/rtnl_u32_addon.h"
-
-#include <linux/netlink.h>
 
 #define 	TC_HANDLE(maj, min)   (TC_H_MAJ((maj) << 16) | TC_H_MIN(min))
 
diff --git a/tests/test-create-bond.c b/tests/test-create-bond.c
index 326e0ef..6edb41f 100644
--- a/tests/test-create-bond.c
+++ b/tests/test-create-bond.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/bonding.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-bridge.c b/tests/test-create-bridge.c
index a9d9f2e..758aaa2 100644
--- a/tests/test-create-bridge.c
+++ b/tests/test-create-bridge.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/bridge.h>
 
-#include <linux/netlink.h>
-
 #define TEST_BRIDGE_NAME "testbridge"
 #define TEST_INTERFACE_NAME "testtap1"
 
diff --git a/tests/test-create-geneve.c b/tests/test-create-geneve.c
index 37b220a..1816e5b 100644
--- a/tests/test-create-geneve.c
+++ b/tests/test-create-geneve.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/geneve.h>
 
-#include <linux/netlink.h>
-
 #define IPv6 1
 
 int main(int argc, char *argv[])
diff --git a/tests/test-create-ifb.c b/tests/test-create-ifb.c
index d154ffd..46524fe 100644
--- a/tests/test-create-ifb.c
+++ b/tests/test-create-ifb.c
@@ -1,8 +1,12 @@
-#include <netlink/netlink.h>
-#include <netlink/route/link.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-ip6tnl.c b/tests/test-create-ip6tnl.c
index b36ab3d..b0c0281 100644
--- a/tests/test-create-ip6tnl.c
+++ b/tests/test-create-ip6tnl.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/ip6tnl.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-ipgre.c b/tests/test-create-ipgre.c
index 66ea6da..31d0eec 100644
--- a/tests/test-create-ipgre.c
+++ b/tests/test-create-ipgre.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/ipgre.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-ipgretap.c b/tests/test-create-ipgretap.c
index 1fe8231..8dceaf1 100644
--- a/tests/test-create-ipgretap.c
+++ b/tests/test-create-ipgretap.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/ipgre.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-ipip.c b/tests/test-create-ipip.c
index 44b9b2c..2ea3bf0 100644
--- a/tests/test-create-ipip.c
+++ b/tests/test-create-ipip.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/ipip.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-ipvlan.c b/tests/test-create-ipvlan.c
index 50bac54..b0b200c 100644
--- a/tests/test-create-ipvlan.c
+++ b/tests/test-create-ipvlan.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/ipvlan.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-ipvti.c b/tests/test-create-ipvti.c
index 6cb92d7..33eb646 100644
--- a/tests/test-create-ipvti.c
+++ b/tests/test-create-ipvti.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/ipvti.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-macsec.c b/tests/test-create-macsec.c
index efadf6b..b702f7d 100644
--- a/tests/test-create-macsec.c
+++ b/tests/test-create-macsec.c
@@ -1,10 +1,13 @@
-#include <netlink/netlink.h>
-#include <netlink/route/link.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 #include <linux/if_link.h>
 
 #include <netlink/route/link/macsec.h>
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-macvlan.c b/tests/test-create-macvlan.c
index f520b67..665c502 100644
--- a/tests/test-create-macvlan.c
+++ b/tests/test-create-macvlan.c
@@ -1,11 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netinet/ether.h>
 
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/macvlan.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-macvtap.c b/tests/test-create-macvtap.c
index 27d1969..c3e19a7 100644
--- a/tests/test-create-macvtap.c
+++ b/tests/test-create-macvtap.c
@@ -1,11 +1,15 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netinet/ether.h>
 
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/macvtap.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-sit.c b/tests/test-create-sit.c
index d33e496..5c7aaeb 100644
--- a/tests/test-create-sit.c
+++ b/tests/test-create-sit.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/sit.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-create-veth.c b/tests/test-create-veth.c
index 9600f8d..fda4d2e 100644
--- a/tests/test-create-veth.c
+++ b/tests/test-create-veth.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/veth.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-vlan.c b/tests/test-create-vlan.c
index 04756d4..e2cd2b1 100644
--- a/tests/test-create-vlan.c
+++ b/tests/test-create-vlan.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/vlan.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-vrf.c b/tests/test-create-vrf.c
index c3d23e7..b5f7176 100644
--- a/tests/test-create-vrf.c
+++ b/tests/test-create-vrf.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/vrf.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct nl_cache *link_cache;
diff --git a/tests/test-create-vxlan.c b/tests/test-create-vxlan.c
index 855fdb5..6d2fd94 100644
--- a/tests/test-create-vxlan.c
+++ b/tests/test-create-vxlan.c
@@ -1,9 +1,13 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/netlink.h>
+
 #include <netlink/netlink.h>
 #include <netlink/route/link.h>
 #include <netlink/route/link/vxlan.h>
 
-#include <linux/netlink.h>
-
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-create-xfrmi.c b/tests/test-create-xfrmi.c
index 3a01a4f..8fd7c3a 100644
--- a/tests/test-create-xfrmi.c
+++ b/tests/test-create-xfrmi.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/route/link/xfrmi.h>
-#include <netlink-private/netlink.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-delete-link.c b/tests/test-delete-link.c
index 8633123..58c70f0 100644
--- a/tests/test-delete-link.c
+++ b/tests/test-delete-link.c
@@ -1,8 +1,12 @@
-#include <netlink/netlink.h>
-#include <netlink/route/link.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+
 int main(int argc, char *argv[])
 {
 	struct rtnl_link *link;
diff --git a/tests/test-genl.c b/tests/test-genl.c
index 42db501..5e32c6d 100644
--- a/tests/test-genl.c
+++ b/tests/test-genl.c
@@ -1,7 +1,12 @@
-#include <netlink/cli/utils.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
+#include <linux/genetlink.h>
 
 #include <linux/taskstats.h>
-#include <linux/genetlink.h>
+
+#include <netlink/cli/utils.h>
 
 static struct nla_policy attr_policy[TASKSTATS_TYPE_MAX+1] = {
 	[TASKSTATS_TYPE_PID]	= { .type = NLA_U32 },
@@ -62,8 +67,6 @@
 	},
 };
 
-#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
-
 static struct genl_ops ops = {
 	.o_name = TASKSTATS_GENL_NAME,
 	.o_cmds = cmds,
diff --git a/tests/test-loopback-up-down.c b/tests/test-loopback-up-down.c
index 5a7bcb1..fdb5a98 100644
--- a/tests/test-loopback-up-down.c
+++ b/tests/test-loopback-up-down.c
@@ -1,4 +1,9 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <net/if.h>
+
 #include <netlink/route/link.h>
 
 int main(void)
diff --git a/tests/test-nf-cache-mngr.c b/tests/test-nf-cache-mngr.c
index 7625e3f..7dcc9fc 100644
--- a/tests/test-nf-cache-mngr.c
+++ b/tests/test-nf-cache-mngr.c
@@ -1,7 +1,11 @@
-#include <netlink/cli/utils.h>
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
 
 #include <linux/netlink.h>
 
+#include <netlink/cli/utils.h>
+
 static void change_cb(struct nl_cache *cache, struct nl_object *obj,
 		      int action, void *data)
 {
diff --git a/tests/test-socket-creation.c b/tests/test-socket-creation.c
index 83f3ad4..00259a1 100644
--- a/tests/test-socket-creation.c
+++ b/tests/test-socket-creation.c
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+
+#include "nl-default.h"
+
 #include <netlink/netlink.h>
-#include <errno.h>
 
 int main(int argc, char *argv[])
 {
diff --git a/tests/test-u32-filter-with-actions.c b/tests/test-u32-filter-with-actions.c
index 17e7bdc..d676013 100644
--- a/tests/test-u32-filter-with-actions.c
+++ b/tests/test-u32-filter-with-actions.c
@@ -5,6 +5,14 @@
  * Stolen from tests/test-complex-HTB-with-hash-filters.c
  */
 
+#include "nl-default.h"
+
+#include <stdio.h>
+
+#include <linux/if_ether.h>
+#include <linux/tc_act/tc_mirred.h>
+#include <linux/netlink.h>
+
 #include <netlink/route/link.h>
 #include <netlink/route/tc.h>
 #include <netlink/route/qdisc.h>
@@ -16,13 +24,6 @@
 #include <netlink/route/class.h>
 #include <netlink/attr.h>
 
-#include <stdio.h>
-#include <string.h>
-
-#include <linux/if_ether.h>
-#include <linux/tc_act/tc_mirred.h>
-#include <linux/netlink.h>
-
 #define 	TC_HANDLE(maj, min)   (TC_H_MAJ((maj) << 16) | TC_H_MIN(min))
 
 /* some functions are copied from iproute-tc tool */
diff --git a/tools/build_release.sh b/tools/build_release.sh
index 2c77d24..e12a195 100755
--- a/tools/build_release.sh
+++ b/tools/build_release.sh
@@ -32,7 +32,6 @@
     ./autogen.sh
     ./configure
     pushd ./doc/
-        ./autogen.sh
         ./configure --enable-doc
     popd
     make -j 5
diff --git a/tools/clang-format-container.sh b/tools/clang-format-container.sh
new file mode 100755
index 0000000..69a68b1
--- /dev/null
+++ b/tools/clang-format-container.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -e
+
+die() {
+    echo "$@" >&2
+    exit 1
+}
+
+DIR="$(realpath "$(dirname "$0")/../")"
+cd "$DIR"
+
+# The correct clang-format version is the one from the Fedora version used in our
+# github action pipeline. Parse it from ".github/workflows/ci.yml".
+FEDORA_VERSION="$(sed -n 's/^      image: fedora:\([0-9]\+\)$/\1/p' .github/workflows/ci.yml)"
+
+test -n "$FEDORA_VERSION" || die "Could not detect the Fedora version in .github/workflows/ci.yml"
+
+IMAGENAME="libnl-code-format-f$FEDORA_VERSION"
+
+ARGS=( "$@" )
+
+if ! podman image exists "$IMAGENAME" ; then
+    echo "Building image \"$IMAGENAME\"..."
+    podman build \
+        --squash-all \
+        --tag "$IMAGENAME" \
+        -f <(cat <<EOF
+FROM fedora:$FEDORA_VERSION
+RUN dnf upgrade -y
+RUN dnf install -y git /usr/bin/clang-format
+EOF
+)
+fi
+
+CMD=( ./tools/clang-format.sh "${ARGS[@]}" )
+
+podman run \
+    --rm \
+    --name "libnm-code-format-f$FEDORA_VERSION" \
+    -v "$DIR:/tmp/NetworkManager:Z" \
+    -w /tmp/NetworkManager \
+    -e "_LIBNL_CODE_FORMAT_CONTAINER=$IMAGENAME" \
+    -ti \
+    "$IMAGENAME" \
+    "${CMD[@]}"
diff --git a/tools/clang-format.sh b/tools/clang-format.sh
new file mode 100755
index 0000000..6a0db2a
--- /dev/null
+++ b/tools/clang-format.sh
@@ -0,0 +1,559 @@
+#!/bin/bash
+
+set -e
+
+die() {
+    printf '%s\n' "$*" >&2
+    exit 1
+}
+
+EXCLUDE_PATHS_TOPLEVEL=(
+    "include/linux-private"
+)
+
+# The following files are currently not formatted with clang.
+# Exclude them too.
+EXCLUDE_PATHS_TOPLEVEL+=(
+    "include/netlink/addr.h"
+    "include/netlink/attr.h"
+    "include/netlink/cache-api.h"
+    "include/netlink/cache.h"
+    "include/netlink/cli/addr.h"
+    "include/netlink/cli/cls.h"
+    "include/netlink/cli/link.h"
+    "include/netlink/cli/mdb.h"
+    "include/netlink/cli/neigh.h"
+    "include/netlink/cli/qdisc.h"
+    "include/netlink/cli/route.h"
+    "include/netlink/cli/tc.h"
+    "include/netlink/cli/utils.h"
+    "include/netlink/data.h"
+    "include/netlink/errno.h"
+    "include/netlink/fib_lookup/lookup.h"
+    "include/netlink/fib_lookup/request.h"
+    "include/netlink/genl/ctrl.h"
+    "include/netlink/genl/family.h"
+    "include/netlink/genl/genl.h"
+    "include/netlink/genl/mngt.h"
+    "include/netlink/handlers.h"
+    "include/netlink/hash.h"
+    "include/netlink/hashtable.h"
+    "include/netlink/idiag/idiagnl.h"
+    "include/netlink/idiag/meminfo.h"
+    "include/netlink/idiag/msg.h"
+    "include/netlink/idiag/req.h"
+    "include/netlink/idiag/vegasinfo.h"
+    "include/netlink/list.h"
+    "include/netlink/msg.h"
+    "include/netlink/netfilter/ct.h"
+    "include/netlink/netfilter/exp.h"
+    "include/netlink/netfilter/log.h"
+    "include/netlink/netfilter/log_msg.h"
+    "include/netlink/netfilter/netfilter.h"
+    "include/netlink/netfilter/nfnl.h"
+    "include/netlink/netfilter/queue.h"
+    "include/netlink/netfilter/queue_msg.h"
+    "include/netlink/netlink-compat.h"
+    "include/netlink/netlink-kernel.h"
+    "include/netlink/netlink.h"
+    "include/netlink/object.h"
+    "include/netlink/route/act/skbedit.h"
+    "include/netlink/route/action.h"
+    "include/netlink/route/addr.h"
+    "include/netlink/route/class.h"
+    "include/netlink/route/classifier.h"
+    "include/netlink/route/cls/basic.h"
+    "include/netlink/route/cls/cgroup.h"
+    "include/netlink/route/cls/ematch.h"
+    "include/netlink/route/cls/ematch/cmp.h"
+    "include/netlink/route/cls/ematch/meta.h"
+    "include/netlink/route/cls/ematch/nbyte.h"
+    "include/netlink/route/cls/ematch/text.h"
+    "include/netlink/route/cls/flower.h"
+    "include/netlink/route/cls/fw.h"
+    "include/netlink/route/cls/matchall.h"
+    "include/netlink/route/cls/police.h"
+    "include/netlink/route/cls/u32.h"
+    "include/netlink/route/link.h"
+    "include/netlink/route/link/api.h"
+    "include/netlink/route/link/bonding.h"
+    "include/netlink/route/link/bridge.h"
+    "include/netlink/route/link/can.h"
+    "include/netlink/route/link/geneve.h"
+    "include/netlink/route/link/inet.h"
+    "include/netlink/route/link/inet6.h"
+    "include/netlink/route/link/info-api.h"
+    "include/netlink/route/link/ip6gre.h"
+    "include/netlink/route/link/ip6tnl.h"
+    "include/netlink/route/link/ip6vti.h"
+    "include/netlink/route/link/ipgre.h"
+    "include/netlink/route/link/ipip.h"
+    "include/netlink/route/link/ipvlan.h"
+    "include/netlink/route/link/ipvti.h"
+    "include/netlink/route/link/macsec.h"
+    "include/netlink/route/link/macvlan.h"
+    "include/netlink/route/link/macvtap.h"
+    "include/netlink/route/link/ppp.h"
+    "include/netlink/route/link/sit.h"
+    "include/netlink/route/link/sriov.h"
+    "include/netlink/route/link/team.h"
+    "include/netlink/route/link/vlan.h"
+    "include/netlink/route/link/vxlan.h"
+    "include/netlink/route/link/xfrmi.h"
+    "include/netlink/route/mdb.h"
+    "include/netlink/route/neighbour.h"
+    "include/netlink/route/neightbl.h"
+    "include/netlink/route/netconf.h"
+    "include/netlink/route/nexthop.h"
+    "include/netlink/route/pktloc.h"
+    "include/netlink/route/qdisc.h"
+    "include/netlink/route/qdisc/cbq.h"
+    "include/netlink/route/qdisc/dsmark.h"
+    "include/netlink/route/qdisc/fifo.h"
+    "include/netlink/route/qdisc/fq_codel.h"
+    "include/netlink/route/qdisc/hfsc.h"
+    "include/netlink/route/qdisc/htb.h"
+    "include/netlink/route/qdisc/mqprio.h"
+    "include/netlink/route/qdisc/netem.h"
+    "include/netlink/route/qdisc/plug.h"
+    "include/netlink/route/qdisc/prio.h"
+    "include/netlink/route/qdisc/red.h"
+    "include/netlink/route/qdisc/sfq.h"
+    "include/netlink/route/route.h"
+    "include/netlink/route/rtnl.h"
+    "include/netlink/route/rule.h"
+    "include/netlink/route/tc-api.h"
+    "include/netlink/route/tc.h"
+    "include/netlink/socket.h"
+    "include/netlink/types.h"
+    "include/netlink/utils.h"
+    "include/netlink/xfrm/ae.h"
+    "include/netlink/xfrm/lifetime.h"
+    "include/netlink/xfrm/sa.h"
+    "include/netlink/xfrm/selector.h"
+    "include/netlink/xfrm/sp.h"
+    "include/netlink/xfrm/template.h"
+    "include/nl-priv-dynamic-core/cache-api.h"
+    "include/nl-priv-dynamic-core/object-api.h"
+    "lib/addr.c"
+    "lib/attr.c"
+    "lib/cache.c"
+    "lib/cache_mngr.c"
+    "lib/cache_mngt.c"
+    "lib/cli/cls/basic.c"
+    "lib/cli/cls/cgroup.c"
+    "lib/cli/qdisc/bfifo.c"
+    "lib/cli/qdisc/blackhole.c"
+    "lib/cli/qdisc/fq_codel.c"
+    "lib/cli/qdisc/hfsc.c"
+    "lib/cli/qdisc/htb.c"
+    "lib/cli/qdisc/ingress.c"
+    "lib/cli/qdisc/pfifo.c"
+    "lib/cli/qdisc/plug.c"
+    "lib/data.c"
+    "lib/error.c"
+    "lib/fib_lookup/lookup.c"
+    "lib/fib_lookup/request.c"
+    "lib/genl/ctrl.c"
+    "lib/genl/family.c"
+    "lib/genl/genl.c"
+    "lib/genl/mngt.c"
+    "lib/genl/nl-genl.h"
+    "lib/handlers.c"
+    "lib/hash.c"
+    "lib/hashtable.c"
+    "lib/idiag/idiag.c"
+    "lib/idiag/idiag_meminfo_obj.c"
+    "lib/idiag/idiag_msg_obj.c"
+    "lib/idiag/idiag_req_obj.c"
+    "lib/idiag/idiag_vegasinfo_obj.c"
+    "lib/mpls.c"
+    "lib/mpls.h"
+    "lib/msg.c"
+    "lib/netfilter/ct.c"
+    "lib/netfilter/ct_obj.c"
+    "lib/netfilter/exp.c"
+    "lib/netfilter/exp_obj.c"
+    "lib/netfilter/log.c"
+    "lib/netfilter/log_msg.c"
+    "lib/netfilter/log_msg_obj.c"
+    "lib/netfilter/log_obj.c"
+    "lib/netfilter/netfilter.c"
+    "lib/netfilter/nfnl.c"
+    "lib/netfilter/queue.c"
+    "lib/netfilter/queue_msg.c"
+    "lib/netfilter/queue_msg_obj.c"
+    "lib/netfilter/queue_obj.c"
+    "lib/nl-core.h"
+    "lib/nl.c"
+    "lib/object.c"
+    "lib/route/act.c"
+    "lib/route/act/gact.c"
+    "lib/route/act/mirred.c"
+    "lib/route/act/skbedit.c"
+    "lib/route/act/vlan.c"
+    "lib/route/addr.c"
+    "lib/route/class.c"
+    "lib/route/classid.c"
+    "lib/route/cls.c"
+    "lib/route/cls/basic.c"
+    "lib/route/cls/cgroup.c"
+    "lib/route/cls/ematch.c"
+    "lib/route/cls/ematch/cmp.c"
+    "lib/route/cls/ematch/container.c"
+    "lib/route/cls/ematch/meta.c"
+    "lib/route/cls/ematch/nbyte.c"
+    "lib/route/cls/ematch/text.c"
+    "lib/route/cls/flower.c"
+    "lib/route/cls/fw.c"
+    "lib/route/cls/mall.c"
+    "lib/route/cls/police.c"
+    "lib/route/cls/u32.c"
+    "lib/route/link-sriov.h"
+    "lib/route/link.c"
+    "lib/route/link/api.c"
+    "lib/route/link/bonding.c"
+    "lib/route/link/bridge.c"
+    "lib/route/link/can.c"
+    "lib/route/link/dummy.c"
+    "lib/route/link/geneve.c"
+    "lib/route/link/ifb.c"
+    "lib/route/link/inet.c"
+    "lib/route/link/inet6.c"
+    "lib/route/link/ip6gre.c"
+    "lib/route/link/ip6tnl.c"
+    "lib/route/link/ip6vti.c"
+    "lib/route/link/ipgre.c"
+    "lib/route/link/ipip.c"
+    "lib/route/link/ipvlan.c"
+    "lib/route/link/ipvti.c"
+    "lib/route/link/link-api.h"
+    "lib/route/link/macsec.c"
+    "lib/route/link/macvlan.c"
+    "lib/route/link/ppp.c"
+    "lib/route/link/sit.c"
+    "lib/route/link/sriov.c"
+    "lib/route/link/team.c"
+    "lib/route/link/veth.c"
+    "lib/route/link/vlan.c"
+    "lib/route/link/vrf.c"
+    "lib/route/link/vxlan.c"
+    "lib/route/link/xfrmi.c"
+    "lib/route/mdb.c"
+    "lib/route/neigh.c"
+    "lib/route/netconf.c"
+    "lib/route/nexthop-encap.h"
+    "lib/route/nexthop.c"
+    "lib/route/nexthop_encap.c"
+    "lib/route/nh_encap_mpls.c"
+    "lib/route/pktloc.c"
+    "lib/route/qdisc.c"
+    "lib/route/qdisc/blackhole.c"
+    "lib/route/qdisc/cbq.c"
+    "lib/route/qdisc/dsmark.c"
+    "lib/route/qdisc/fifo.c"
+    "lib/route/qdisc/fq_codel.c"
+    "lib/route/qdisc/hfsc.c"
+    "lib/route/qdisc/htb.c"
+    "lib/route/qdisc/ingress.c"
+    "lib/route/qdisc/mqprio.c"
+    "lib/route/qdisc/netem.c"
+    "lib/route/qdisc/plug.c"
+    "lib/route/qdisc/prio.c"
+    "lib/route/qdisc/red.c"
+    "lib/route/qdisc/sfq.c"
+    "lib/route/qdisc/tbf.c"
+    "lib/route/route.c"
+    "lib/route/route_obj.c"
+    "lib/route/route_utils.c"
+    "lib/route/rtnl.c"
+    "lib/route/rule.c"
+    "lib/route/tc-api.h"
+    "lib/route/tc.c"
+    "lib/socket.c"
+    "lib/utils.c"
+    "lib/version.c"
+    "lib/xfrm/ae.c"
+    "lib/xfrm/lifetime.c"
+    "lib/xfrm/sa.c"
+    "lib/xfrm/selector.c"
+    "lib/xfrm/sp.c"
+    "lib/xfrm/template.c"
+    "python/netlink/utils.h"
+    "src/genl-ctrl-list.c"
+    "src/idiag-socket-details.c"
+    "src/lib/addr.c"
+    "src/lib/cls.c"
+    "src/lib/ct.c"
+    "src/lib/exp.c"
+    "src/lib/link.c"
+    "src/lib/neigh.c"
+    "src/lib/route.c"
+    "src/lib/tc.c"
+    "src/lib/utils.c"
+    "src/nf-ct-add.c"
+    "src/nf-ct-events.c"
+    "src/nf-ct-list.c"
+    "src/nf-exp-add.c"
+    "src/nf-exp-delete.c"
+    "src/nf-exp-list.c"
+    "src/nf-log.c"
+    "src/nf-monitor.c"
+    "src/nf-queue.c"
+    "src/nl-addr-add.c"
+    "src/nl-addr-delete.c"
+    "src/nl-addr-list.c"
+    "src/nl-class-add.c"
+    "src/nl-class-delete.c"
+    "src/nl-class-list.c"
+    "src/nl-classid-lookup.c"
+    "src/nl-cls-add.c"
+    "src/nl-cls-delete.c"
+    "src/nl-cls-list.c"
+    "src/nl-fib-lookup.c"
+    "src/nl-link-enslave.c"
+    "src/nl-link-list.c"
+    "src/nl-link-release.c"
+    "src/nl-link-set.c"
+    "src/nl-link-stats.c"
+    "src/nl-list-caches.c"
+    "src/nl-list-sockets.c"
+    "src/nl-monitor.c"
+    "src/nl-neigh-add.c"
+    "src/nl-neigh-delete.c"
+    "src/nl-neigh-list.c"
+    "src/nl-neightbl-list.c"
+    "src/nl-pktloc-lookup.c"
+    "src/nl-qdisc-add.c"
+    "src/nl-qdisc-delete.c"
+    "src/nl-qdisc-list.c"
+    "src/nl-route-add.c"
+    "src/nl-route-delete.c"
+    "src/nl-route-get.c"
+    "src/nl-route-list.c"
+    "src/nl-rule-list.c"
+    "src/nl-tctree-list.c"
+    "src/nl-util-addr.c"
+    "tests/nl-test-util.h"
+    "tests/test-cache-mngr.c"
+    "tests/test-complex-HTB-with-hash-filters.c"
+    "tests/test-create-bridge.c"
+    "tests/test-create-geneve.c"
+    "tests/test-create-ip6tnl.c"
+    "tests/test-create-ipgre.c"
+    "tests/test-create-ipgretap.c"
+    "tests/test-create-ipip.c"
+    "tests/test-create-ipvti.c"
+    "tests/test-create-macsec.c"
+    "tests/test-create-macvlan.c"
+    "tests/test-create-macvtap.c"
+    "tests/test-create-sit.c"
+    "tests/test-create-veth.c"
+    "tests/test-create-xfrmi.c"
+    "tests/test-genl.c"
+    "tests/test-nf-cache-mngr.c"
+    "tests/test-socket-creation.c"
+    "tests/test-u32-filter-with-actions.c"
+)
+
+DIR_ROOT="$(git rev-parse --show-toplevel)" || die "not inside a git repository"
+DIR_PREFIX="$(git rev-parse --show-prefix)" || die "not inside a git repository"
+
+if [ ! -f "$DIR_ROOT/.clang-format" ]; then
+    die "Error: the clang-format file in \"$DIR_ROOT\" does not exist"
+fi
+
+if ! command -v clang-format &> /dev/null; then
+    die "Error: clang-format is not installed. On RHEL/Fedora/CentOS run 'dnf install clang-tools-extra'"
+fi
+
+if test -n "$DIR_PREFIX"; then
+    EXCLUDE_PATHS=()
+    for e in "${EXCLUDE_PATHS_TOPLEVEL[@]}"; do
+        REGEX="^$DIR_PREFIX([^/].*)$"
+        if [[ "$e" =~ $REGEX ]]; then
+            EXCLUDE_PATHS+=("${BASH_REMATCH[1]}")
+        fi
+    done
+else
+    EXCLUDE_PATHS=("${EXCLUDE_PATHS_TOPLEVEL[@]}")
+fi
+
+FILES=()
+HAS_EXPLICIT_FILES=0
+SHOW_FILENAMES=0
+TEST_ONLY=0
+CHECK_UPSTREAM=
+
+usage() {
+    printf "Usage: %s [OPTION]... [FILE]...\n" "$(basename "$0")"
+    printf "Reformat source files using clang-format.\n\n"
+    printf "If no file is given the script runs on the whole codebase.\n"
+    printf "OPTIONS:\n"
+    printf "    -h                    Print this help message.\n"
+    printf "    -i                    Reformat files (the default).\n"
+    printf "    -n|--dry-run          Only check the files (contrary to \"-i\").\n"
+    printf "    -a|--all              Check all files (the default).\n"
+    printf "    -u|--upstream COMMIT  Check only files from \`git diff --name-only COMMIT\` (contrary to \"-a\").\n"
+    printf "                          This also affects directories given in the [FILE] list, but not files.\n"
+    printf "                          If this is the last parameter and COMMIT is unspecified/empty, it defaults to \"main\".\n"
+    printf "    -F|--fast             Same as \`-u HEAD^\`.\n"
+    printf "    -l|--show-filenames   Only print the filenames that would be checked/formatted\n"
+    printf "    --                    Separate options from filenames/directories\n"
+    if [ -n "${_LIBNL_CODE_FORMAT_CONTAINER+x}" ] ; then
+        printf "\n"
+        printf "Command runs inside container image \"$_LIBNL_CODE_FORMAT_CONTAINER\".\n"
+        printf "Delete/renew image with \`podman rmi \"$_LIBNL_CODE_FORMAT_CONTAINER\"\`.\n"
+    fi
+}
+
+ls_files_exist() {
+    local OLD_IFS="$IFS"
+    local f
+
+    IFS=$'\n'
+    for f in $(cat) ; do
+        test -f "$f" && printf '%s\n' "$f"
+    done
+    IFS="$OLD_IFS"
+}
+
+ls_files_filter() {
+    local OLD_IFS="$IFS"
+    local f
+
+    IFS=$'\n'
+    for f in $(cat) ; do
+        local found=1
+        local p
+        for p; do
+            [[ "$f" = "$p/"* ]] && found=
+            [[ "$f" = "$p" ]] && found=
+        done
+        test -n "$found" && printf '%s\n' "$f"
+    done
+    IFS="$OLD_IFS"
+}
+
+g_ls_files() {
+    local pattern="$1"
+    shift
+
+    if [ -z "$CHECK_UPSTREAM" ]; then
+        git ls-files -- "$pattern"
+    else
+        git diff --no-renames --name-only "$CHECK_UPSTREAM" -- "$pattern" \
+            | ls_files_exist
+    fi | ls_files_filter "$@"
+}
+
+HAD_DASHDASH=0
+while (( $# )); do
+    if [ "$HAD_DASHDASH" = 0 ]; then
+        case "$1" in
+            -h)
+                usage
+                exit 0
+                ;;
+            -l|--show-filenames)
+                SHOW_FILENAMES=1
+                shift
+                continue
+                ;;
+            -a|--all)
+                CHECK_UPSTREAM=
+                shift
+                continue
+                ;;
+            -u|--upstream)
+                shift
+                CHECK_UPSTREAM="$1"
+                test -n "$CHECK_UPSTREAM" || CHECK_UPSTREAM=main
+                shift || :
+                continue
+                ;;
+            -F|--fast)
+                CHECK_UPSTREAM='HEAD^'
+                shift
+                continue
+                ;;
+            -n|--dry-run)
+                TEST_ONLY=1
+                shift
+                continue
+                ;;
+            -i)
+                TEST_ONLY=0
+                shift
+                continue
+                ;;
+            --)
+                HAD_DASHDASH=1
+                shift
+                continue
+                ;;
+        esac
+    fi
+    if [ -d "$1" ]; then
+        while IFS='' read -r line;
+            do FILES+=("$line")
+        done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files "${1}/*.[hc]" "${EXCLUDE_PATHS[@]}")
+    elif [ -f "$1" ]; then
+        FILES+=("$1")
+    else
+        usage >&2
+        echo >&2
+        die "Unknown argument \"$1\" which also is neither a file nor a directory."
+    fi
+    shift
+    HAS_EXPLICIT_FILES=1
+done
+
+if [ $HAS_EXPLICIT_FILES = 0 ]; then
+    while IFS='' read -r line; do
+        FILES+=("$line")
+    done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files '*.[ch]' "${EXCLUDE_PATHS[@]}")
+fi
+
+if [ $SHOW_FILENAMES = 1 ]; then
+    for f in "${FILES[@]}" ; do
+        printf '%s\n' "$f"
+    done
+    exit 0
+fi
+
+if [ "${#FILES[@]}" = 0 ]; then
+    if [ -z "$CHECK_UPSTREAM" ]; then
+        die "Error: no files to check"
+    fi
+    exit 0
+fi
+
+FLAGS_TEST=( --Werror -n --ferror-limit=1 )
+
+if [ $TEST_ONLY = 1 ]; then
+    # We assume that all formatting is correct. In that mode, passing
+    # all filenames to clang-format is significantly faster.
+    #
+    # Only in case of an error, we iterate over the files one by one
+    # until we find the first invalid file.
+    for f in "${FILES[@]}"; do
+        [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
+    done
+    clang-format "${FLAGS_TEST[@]}" "${FILES[@]}" &>/dev/null && exit 0
+    for f in "${FILES[@]}"; do
+        [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
+        if ! clang-format "${FLAGS_TEST[@]}" "$f" &>/dev/null; then
+            FF="$(mktemp)"
+            trap 'rm -f "$FF"' EXIT
+            clang-format "$f" 2>/dev/null > "$FF"
+            git --no-pager diff "$f" "$FF" || :
+            FEDORA_VERSION="$(sed -n 's/^      image: fedora:\([0-9]\+\)$/\1/p' .github/workflows/ci.yml)"
+            die "Error: file \"$f\" has style issues."$'\n'"Fix it by running \`\"$0\"\` using $(clang-format --version)
+Alternatively, run \`./tools/clang-format-container.sh\` to use a podman container named \"libnl-code-format-f$FEDORA_VERSION\"."
+        fi
+    done
+    die "an unknown error happened."
+fi
+
+clang-format -i "${FILES[@]}"