diff options
Diffstat (limited to 'packages')
16 files changed, 1578 insertions, 119 deletions
diff --git a/packages/frr/patches/0002-zebra-Fixes-for-connected-routes.patch b/packages/frr/patches/0002-zebra-Fixes-for-connected-routes.patch new file mode 100644 index 00000000..6287e071 --- /dev/null +++ b/packages/frr/patches/0002-zebra-Fixes-for-connected-routes.patch @@ -0,0 +1,176 @@ +From 18b1c3c06eb69c8d10666c40f55be4926f888042 Mon Sep 17 00:00:00 2001 +From: zsdc <taras@vyos.io> +Date: Wed, 24 May 2023 20:43:27 +0300 +Subject: [PATCH] zebra: Fixes for connected routes + +This is a cumulative backport of: +92980561382fc04380414a6e2f6ca6746c2fe5e9 +7fb9825cf7e762add68f5108df4eddda1247f198 +e3d901f8638dec32eac4c2690912138963ae5a05 +--- + lib/if.h | 3 ++ + zebra/connected.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 75 insertions(+), 1 deletion(-) + +diff --git a/lib/if.h b/lib/if.h +index a2a40d095..0c73ab63a 100644 +--- a/lib/if.h ++++ b/lib/if.h +@@ -393,6 +393,7 @@ struct connected { + #define ZEBRA_IFC_REAL (1 << 0) + #define ZEBRA_IFC_CONFIGURED (1 << 1) + #define ZEBRA_IFC_QUEUED (1 << 2) ++#define ZEBRA_IFC_DOWN (1 << 3) + /* + The ZEBRA_IFC_REAL flag should be set if and only if this address + exists in the kernel and is actually usable. (A case where it exists +@@ -406,6 +407,8 @@ struct connected { + in the kernel. It may and should be set although the address might + not be + usable yet. (compare with ZEBRA_IFC_REAL) ++ The ZEBRA_IFC_DOWN flag is used to record that an address is ++ present, but down/unavailable. + */ + + /* Flags for connected address. */ +diff --git a/zebra/connected.c b/zebra/connected.c +index 8c4ba163b..fd3fefdd2 100644 +--- a/zebra/connected.c ++++ b/zebra/connected.c +@@ -207,6 +207,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) + }; + struct zebra_vrf *zvrf; + uint32_t metric; ++ uint32_t count = 0; ++ struct listnode *cnode; ++ struct connected *c; + + zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + if (!zvrf) { +@@ -219,6 +222,9 @@ void connected_up(struct interface *ifp, struct connected *ifc) + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; + ++ /* Ensure 'down' flag is cleared */ ++ UNSET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); ++ + PREFIX_COPY(&p, CONNECTED_PREFIX(ifc)); + + /* Apply mask to the network. */ +@@ -251,6 +257,29 @@ void connected_up(struct interface *ifp, struct connected *ifc) + + metric = (ifc->metric < (uint32_t)METRIC_MAX) ? + ifc->metric : ifp->metric; ++ ++ /* ++ * It's possible to add the same network and mask ++ * to an interface over and over. This would ++ * result in an equivalent number of connected ++ * routes. Just add one connected route in ++ * for all the addresses on an interface that ++ * resolve to the same network and mask ++ */ ++ for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { ++ struct prefix cp; ++ ++ PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); ++ apply_mask(&cp); ++ ++ if (prefix_same(&cp, &p) && ++ !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN)) ++ count++; ++ ++ if (count >= 2) ++ return; ++ } ++ + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, + 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); + +@@ -290,6 +319,8 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); ++ if (!if_is_operative(ifp)) ++ SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); + + /* Allocate new connected address. */ + p = prefix_ipv4_new(); +@@ -350,12 +381,15 @@ void connected_down(struct interface *ifp, struct connected *ifc) + .vrf_id = ifp->vrf_id, + }; + struct zebra_vrf *zvrf; ++ uint32_t count = 0; ++ struct listnode *cnode; ++ struct connected *c; + + zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); + if (!zvrf) { + flog_err( + EC_ZEBRA_VRF_NOT_FOUND, +- "%s: Received Up for interface but no associated zvrf: %d", ++ "%s: Received Down for interface but no associated zvrf: %d", + __func__, ifp->vrf_id); + return; + } +@@ -363,6 +397,17 @@ void connected_down(struct interface *ifp, struct connected *ifc) + if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) + return; + ++ /* Skip if we've already done this; this can happen if we have a ++ * config change that takes an interface down, then we receive kernel ++ * notifications about the downed interface and its addresses. ++ */ ++ if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_DOWN)) { ++ if (IS_ZEBRA_DEBUG_RIB) ++ zlog_debug("%s: ifc %p, %pFX already DOWN", ++ __func__, ifc, ifc->address); ++ return; ++ } ++ + PREFIX_COPY(&p, CONNECTED_PREFIX(ifc)); + + /* Apply mask to the network. */ +@@ -388,6 +433,30 @@ void connected_down(struct interface *ifp, struct connected *ifc) + break; + } + ++ /* Mark the address as 'down' */ ++ SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); ++ ++ /* ++ * It's possible to have X number of addresses ++ * on a interface that all resolve to the same ++ * network and mask. Find them and just ++ * allow the deletion when are removing the last ++ * one. ++ */ ++ for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { ++ struct prefix cp; ++ ++ PREFIX_COPY(&cp, CONNECTED_PREFIX(c)); ++ apply_mask(&cp); ++ ++ if (prefix_same(&p, &cp) && ++ !CHECK_FLAG(c->conf, ZEBRA_IFC_DOWN)) ++ count++; ++ ++ if (count >= 1) ++ return; ++ } ++ + /* + * Same logic as for connected_up(): push the changes into the + * head. +@@ -481,6 +550,8 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, + /* If we get a notification from the kernel, + * we can safely assume the address is known to the kernel */ + SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); ++ if (!if_is_operative(ifp)) ++ SET_FLAG(ifc->conf, ZEBRA_IFC_DOWN); + + /* Allocate new connected address. */ + p = prefix_ipv6_new(); +-- +2.34.1 + diff --git a/packages/frr/patches/0003-Fix-as-override-behavior.patch b/packages/frr/patches/0003-Fix-as-override-behavior.patch new file mode 100644 index 00000000..e13ac3a7 --- /dev/null +++ b/packages/frr/patches/0003-Fix-as-override-behavior.patch @@ -0,0 +1,77 @@ +From 6320d4941777d317989209f26ca513379f729c30 Mon Sep 17 00:00:00 2001 +From: zsdc <taras@vyos.io> +Date: Fri, 12 May 2023 13:56:20 +0300 +Subject: [PATCH] Fix as-override behavior + +Backported 9bbdb4572d3bb255211fecf1c756452ab27e91c2 from FRR 8.5 +--- + bgpd/bgp_aspath.c | 22 ---------------------- + bgpd/bgp_aspath.h | 1 - + bgpd/bgp_route.c | 4 +--- + 3 files changed, 1 insertion(+), 26 deletions(-) + +diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c +index 5cf3c60fa..9595bae5f 100644 +--- a/bgpd/bgp_aspath.c ++++ b/bgpd/bgp_aspath.c +@@ -1215,28 +1215,6 @@ bool aspath_private_as_check(struct aspath *aspath) + return true; + } + +-/* Return True if the entire ASPATH consist of the specified ASN */ +-bool aspath_single_asn_check(struct aspath *aspath, as_t asn) +-{ +- struct assegment *seg; +- +- if (!(aspath && aspath->segments)) +- return false; +- +- seg = aspath->segments; +- +- while (seg) { +- int i; +- +- for (i = 0; i < seg->length; i++) { +- if (seg->as[i] != asn) +- return false; +- } +- seg = seg->next; +- } +- return true; +-} +- + /* Replace all instances of the target ASN with our own ASN */ + struct aspath *aspath_replace_specific_asn(struct aspath *aspath, + as_t target_asn, as_t our_asn) +diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h +index 9df352fcd..9bab5bb7b 100644 +--- a/bgpd/bgp_aspath.h ++++ b/bgpd/bgp_aspath.h +@@ -108,7 +108,6 @@ extern unsigned int aspath_get_first_as(struct aspath *); + extern unsigned int aspath_get_last_as(struct aspath *); + extern int aspath_loop_check(struct aspath *, as_t); + extern bool aspath_private_as_check(struct aspath *); +-extern bool aspath_single_asn_check(struct aspath *, as_t asn); + extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath, + as_t target_asn, + as_t our_asn); +diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c +index 48ccb669b..6de3e2a7f 100644 +--- a/bgpd/bgp_route.c ++++ b/bgpd/bgp_route.c +@@ -1571,11 +1571,9 @@ static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, + struct peer *peer, struct attr *attr) + { + if (peer->sort == BGP_PEER_EBGP +- && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { +- if (aspath_single_asn_check(attr->aspath, peer->as)) ++ && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) + attr->aspath = aspath_replace_specific_asn( + attr->aspath, peer->as, bgp->as); +- } + } + + void bgp_attr_add_gshut_community(struct attr *attr) +-- +2.34.1 + diff --git a/packages/keepalived/debian/patches/0001-vrrp-Set-sysctl-arp_ignore-to-1-on-IPv6-VMACs.patch b/packages/keepalived/debian/patches/0001-vrrp-Set-sysctl-arp_ignore-to-1-on-IPv6-VMACs.patch new file mode 100644 index 00000000..b099dc7b --- /dev/null +++ b/packages/keepalived/debian/patches/0001-vrrp-Set-sysctl-arp_ignore-to-1-on-IPv6-VMACs.patch @@ -0,0 +1,129 @@ +From af4aa758c3512bec8233549e138b03741c5404f9 Mon Sep 17 00:00:00 2001 +From: Quentin Armitage <quentin@armitage.org.uk> +Date: Sat, 14 Oct 2023 15:37:19 +0100 +Subject: [PATCH] vrrp: Set sysctl arp_ignore to 1 on IPv6 VMACs + +Setting arp_ignore to 1 ensures that the VMAC interface does not respond +to ARP requests for IPv4 addresses not configured on the VMAC. + +Signed-off-by: Quentin Armitage <quentin@armitage.org.uk> +--- + keepalived/include/vrrp_if_config.h | 2 +- + keepalived/vrrp/vrrp_if_config.c | 28 ++++++++++++++++++++-------- + keepalived/vrrp/vrrp_vmac.c | 5 ++--- + 3 files changed, 23 insertions(+), 12 deletions(-) + +diff --git a/keepalived/include/vrrp_if_config.h b/keepalived/include/vrrp_if_config.h +index 35465cd..c35e56e 100644 +--- a/keepalived/include/vrrp_if_config.h ++++ b/keepalived/include/vrrp_if_config.h +@@ -34,7 +34,7 @@ extern void set_promote_secondaries(interface_t*); + extern void reset_promote_secondaries(interface_t*); + #ifdef _HAVE_VRRP_VMAC_ + extern void restore_rp_filter(void); +-extern void set_interface_parameters(const interface_t*, interface_t*); ++extern void set_interface_parameters(const interface_t*, interface_t*, sa_family_t); + extern void reset_interface_parameters(interface_t*); + extern void link_set_ipv6(const interface_t*, bool); + #endif +diff --git a/keepalived/vrrp/vrrp_if_config.c b/keepalived/vrrp/vrrp_if_config.c +index cfce7e2..fbfd34c 100644 +--- a/keepalived/vrrp/vrrp_if_config.c ++++ b/keepalived/vrrp/vrrp_if_config.c +@@ -81,6 +81,11 @@ static sysctl_opts_t vmac_sysctl[] = { + { 0, 0} + }; + ++static sysctl_opts_t vmac_sysctl_6[] = { ++ { IPV4_DEVCONF_ARP_IGNORE, 1 }, ++ { 0, 0} ++}; ++ + #endif + #endif + +@@ -216,11 +221,14 @@ netlink_set_interface_flags(unsigned ifindex, const sysctl_opts_t *sys_opts) + + #ifdef _HAVE_VRRP_VMAC_ + static inline int +-netlink_set_interface_parameters(const interface_t *ifp, interface_t *base_ifp) ++netlink_set_interface_parameters(const interface_t *ifp, interface_t *base_ifp, sa_family_t family) + { +- if (netlink_set_interface_flags(ifp->ifindex, vmac_sysctl)) ++ if (netlink_set_interface_flags(ifp->ifindex, family == AF_INET6 ? vmac_sysctl_6 : vmac_sysctl)) + return -1; + ++ if (family == AF_INET6) ++ return 0; ++ + /* If the underlying interface is a MACVLAN that has been moved into + * a separate network namespace from the parent, we can't access the + * parent. */ +@@ -271,9 +279,9 @@ netlink_reset_interface_parameters(const interface_t* ifp) + } + + static inline void +-set_interface_parameters_devconf(const interface_t *ifp, interface_t *base_ifp) ++set_interface_parameters_devconf(const interface_t *ifp, interface_t *base_ifp, sa_family_t family) + { +- if (netlink_set_interface_parameters(ifp, base_ifp)) ++ if (netlink_set_interface_parameters(ifp, base_ifp, family)) + log_message(LOG_INFO, "Unable to set parameters for %s", ifp->ifname); + } + +@@ -310,11 +318,15 @@ reset_promote_secondaries_devconf(interface_t *ifp) + + #ifdef _HAVE_VRRP_VMAC_ + static inline void +-set_interface_parameters_sysctl(const interface_t *ifp, interface_t *base_ifp) ++set_interface_parameters_sysctl(const interface_t *ifp, interface_t *base_ifp, sa_family_t family) + { + unsigned val; + + set_sysctl("net/ipv4/conf", ifp->ifname, "arp_ignore", 1); ++ ++ if (family == AF_INET6) ++ return; ++ + set_sysctl("net/ipv4/conf", ifp->ifname, "accept_local", 1); + set_sysctl("net/ipv4/conf", ifp->ifname, "rp_filter", 0); + +@@ -524,15 +536,15 @@ restore_rp_filter(void) + } + + void +-set_interface_parameters(const interface_t *ifp, interface_t *base_ifp) ++set_interface_parameters(const interface_t *ifp, interface_t *base_ifp, sa_family_t family) + { + if (all_rp_filter == UINT_MAX) + clear_rp_filter(); + + #ifdef _HAVE_IPV4_DEVCONF_ +- set_interface_parameters_devconf(ifp, base_ifp); ++ set_interface_parameters_devconf(ifp, base_ifp, family); + #else +- set_interface_parameters_sysctl(ifp, base_ifp); ++ set_interface_parameters_sysctl(ifp, base_ifp, family); + #endif + } + +diff --git a/keepalived/vrrp/vrrp_vmac.c b/keepalived/vrrp/vrrp_vmac.c +index e5ff0e9..021953a 100644 +--- a/keepalived/vrrp/vrrp_vmac.c ++++ b/keepalived/vrrp/vrrp_vmac.c +@@ -407,10 +407,9 @@ netlink_link_add_vmac(vrrp_t *vrrp, const interface_t *old_interface) + if (!ifp->ifindex) + return false; + +- if (vrrp->family == AF_INET && create_interface) { ++ if (create_interface) { + /* Set the necessary kernel parameters to make macvlans work for us */ +-// If this saves current base_ifp's settings, we need to be careful if multiple VMACs on same i/f +- set_interface_parameters(ifp, ifp->base_ifp); ++ set_interface_parameters(ifp, ifp->base_ifp, vrrp->family); + } + + #ifdef _WITH_FIREWALL_ +-- +2.34.1 + diff --git a/packages/keepalived/debian/patches/series b/packages/keepalived/debian/patches/series new file mode 100644 index 00000000..3504d7fa --- /dev/null +++ b/packages/keepalived/debian/patches/series @@ -0,0 +1 @@ +0001-vrrp-Set-sysctl-arp_ignore-to-1-on-IPv6-VMACs.patch diff --git a/packages/keepalived/debian/source/format b/packages/keepalived/debian/source/format new file mode 100644 index 00000000..163aaf8d --- /dev/null +++ b/packages/keepalived/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/packages/linux-kernel/Jenkinsfile b/packages/linux-kernel/Jenkinsfile index 75fb99fb..7825ce9d 100644 --- a/packages/linux-kernel/Jenkinsfile +++ b/packages/linux-kernel/Jenkinsfile @@ -236,6 +236,38 @@ pipeline { } } } + stage('Intel ICE driver') { + when { + beforeOptions true + beforeAgent true + anyOf { + changeset pattern: "**/packages/linux-kernel/*" + changeset pattern: "**/data/defaults.json" + triggeredBy cause: "UserIdCause" + } + } + steps { + dir(env.BASE_DIR) { + sh "./build-intel-ice.py" + } + } + } + stage('Realtek r8152 driver') { + when { + beforeOptions true + beforeAgent true + anyOf { + changeset pattern: "**/packages/linux-kernel/*" + changeset pattern: "**/data/defaults.json" + triggeredBy cause: "UserIdCause" + } + } + steps { + dir(env.BASE_DIR) { + sh "./build-driver-realtek-r8152.py" + } + } + } } } // This stage should not be run in the parallel section as it will call "make" diff --git a/packages/linux-kernel/build-driver-realtek-r8152.py b/packages/linux-kernel/build-driver-realtek-r8152.py new file mode 100755 index 00000000..3200bd9e --- /dev/null +++ b/packages/linux-kernel/build-driver-realtek-r8152.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 + +from json import loads as json_loads +from requests import get +from pathlib import Path +from shutil import copy as copy_file +from subprocess import run + + +# dependency modifier +def add_depends(package_dir: str, package_name: str, depends) -> None: + """Add dependencies to a package + + Args: + package_dir (str): a directory where package sources are located + package_name (str): a name of package + depends (list[str]): a list of dependencies to add + """ + depends_list: str = ', '.join(depends) + depends_line: str = f'misc:Depends={depends_list}\n' + + substvars_file = Path(f'{package_dir}/debian/{package_name}.substvars') + substvars_file.write_text(depends_line) + + +# copy patches +def apply_deb_patches(package_name: str, sources_dir: str): + """Apply patches to sources directory + + Args: + package_name (str): package name + sources_dir (str): sources dir + """ + patches_dir = Path(f'patches/{package_name}') + if patches_dir.exists(): + patches_list = list(patches_dir.iterdir()) + patches_list.sort() + series_file = Path(f'{sources_dir}/debian/patches/series') + series_data = '' + for patch_file in patches_list: + print(f'Applying patch: {patch_file.name}') + copy_file(patch_file, f'{sources_dir}/debian/patches/') + if series_file.exists(): + series_data = series_file.read_text() + series_data = f'{series_data}\n{patch_file.name}' + series_file.write_text(series_data) + + +# find kernel version and source path +defaults_file: str = Path('../../data/defaults.json').read_text() +KERNEL_VER: str = json_loads(defaults_file).get('kernel_version') +KERNEL_FLAVOR: str = json_loads(defaults_file).get('kernel_flavor') +KERNEL_SRC: str = Path.cwd().as_posix() + '/linux' + +# define variables +PACKAGE_NAME: str = 'vyos-drivers-realtek-r8152' +PACKAGE_VERSION: str = '2.17.1' +PACKAGE_DIR: str = f'{PACKAGE_NAME}-{PACKAGE_VERSION}' +SOURCES_ARCHIVE: str = 'r8152-2.17.1.tar.bz2' +SOURCES_URL: str = f'https://dev.packages.vyos.net/source-mirror/{SOURCES_ARCHIVE}' + +# download sources +sources_archive = Path(SOURCES_ARCHIVE) +sources_archive.write_bytes(get(SOURCES_URL).content) + +# prepare sources +debmake_cmd = [ + 'debmake', '-e', 'support@vyos.io', '-f', 'VyOS Support', '-p', + PACKAGE_NAME, '-u', PACKAGE_VERSION, '-a', SOURCES_ARCHIVE +] +run(debmake_cmd) + +# add kernel to dependencies +add_depends(PACKAGE_DIR, PACKAGE_NAME, + [f'linux-image-{KERNEL_VER}-{KERNEL_FLAVOR}']) + +# configure build rules +build_rules_text: str = f'''#!/usr/bin/make -f +# config +export KERNELDIR := {KERNEL_SRC} +PACKAGE_BUILD_DIR := debian/{PACKAGE_NAME} +KVER := {KERNEL_VER}-{KERNEL_FLAVOR} +MODULES_DIR := updates/drivers/net/usb + +# main packaging script based on dh7 syntax +%: + dh $@ + +override_dh_clean: + dh_clean --exclude=debian/{PACKAGE_NAME}.substvars + +override_dh_prep: + dh_prep --exclude=debian/{PACKAGE_NAME}.substvars + +override_dh_auto_clean: + make clean + +override_dh_auto_build: + make modules + +override_dh_auto_install: + install -D -m 644 r8152.ko ${{PACKAGE_BUILD_DIR}}/lib/modules/${{KVER}}/${{MODULES_DIR}}/r8152.ko + install -D -m 644 50-usb-realtek-net.rules ${{PACKAGE_BUILD_DIR}}/etc/udev/rules.d/50-usb-realtek-net.rules +''' +bild_rules = Path(f'{PACKAGE_DIR}/debian/rules') +bild_rules.write_text(build_rules_text) + +# apply patches +apply_deb_patches(PACKAGE_NAME, PACKAGE_DIR) + +# build a package +debuild_cmd = ['debuild'] +run(debuild_cmd, cwd=PACKAGE_DIR) diff --git a/packages/linux-kernel/build-intel-ice.py b/packages/linux-kernel/build-intel-ice.py new file mode 100755 index 00000000..03d83764 --- /dev/null +++ b/packages/linux-kernel/build-intel-ice.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 + +from json import loads as json_loads +from requests import get +from pathlib import Path +from subprocess import run + +# define variables +DRIVER_VERSION: str = '1.11.14' +DRIVER_URL: str = f'https://downloads.sourceforge.net/project/e1000/ice%20stable/{DRIVER_VERSION}/ice-{DRIVER_VERSION}.tar.gz' +DRIVER_ARCHIVE: str = f'ice-{DRIVER_VERSION}.tar.gz' +DRIVER_DIR: str = f'vyos-drivers-intel-ice-{DRIVER_VERSION}' + +# find kernel version ans source path +default_file: str = Path('../../data/defaults.json').read_text() +KERNEL_VER: str = json_loads(default_file).get('kernel_version') +KERNEL_SRC: str = Path.cwd().as_posix() + '/linux' + +# download driver +driver_archive = Path(DRIVER_ARCHIVE) +driver_archive.write_bytes(get(DRIVER_URL).content) + +# prepare sources +debmake_cmd = [ + 'debmake', '-e', 'support@vyos.io', '-f', 'VyOS Support', '-p', + 'vyos-drivers-intel-ice', '-a', DRIVER_ARCHIVE +] +run(debmake_cmd) + +# fix build rules +build_rules_text = f'''#!/usr/bin/make -f +# config +export KSRC := {KERNEL_SRC} +INSTALL_DIR := debian/vyos-drivers-intel-ice +DRIVER := ice +KVER := {KERNEL_VER}-amd64-vyos +KSRC_INSTALL := /lib/modules/${{KVER}}/build/ +INTEL_DIR := updates/drivers/net/ethernet/intel +# DDP variables +DDP_PKG_ORIGIN := $(shell ls ddp/${{DRIVER}}-[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.[[:digit:]]*\.pkg 2>/dev/null) +DDP_PKG_NAME := $(shell basename ${{DDP_PKG_ORIGIN}} 2>/dev/null) +DDP_PKG_DEST_PATH := ${{INSTALL_DIR}}/lib/firmware/updates/intel/${{DRIVER}}/ddp +DDP_PKG_DEST := ${{DDP_PKG_DEST_PATH}}/${{DDP_PKG_NAME}} +DDP_PKG_LINK := ${{DRIVER}}.pkg + +# main packaging script based on dh7 syntax +%: + dh $@ + +override_dh_auto_clean: + cd src && \ + make clean + +override_dh_auto_build: + cd src && sed -e 's/#define NEED_ETH_HW_ADDR_SET/#undef NEED_ETH_HW_ADDR_SET/' -i kcompat_std_defs.h && make all + +override_dh_auto_install: + # DDP + install -D -m 644 ${{DDP_PKG_ORIGIN}} ${{DDP_PKG_DEST}} + (cd ${{DDP_PKG_DEST_PATH}} && ln -sf ${{DDP_PKG_NAME}} ${{DDP_PKG_LINK}}) + install -D -m 644 ddp/LICENSE ${{DDP_PKG_DEST_PATH}}/LICENSE + # module + install -D -m 644 src/${{DRIVER}}.ko ${{INSTALL_DIR}}/lib/modules/${{KVER}}/${{INTEL_DIR}}/ice/${{DRIVER}}.ko + # AUX + install -D -m 644 src/intel_auxiliary.ko ${{INSTALL_DIR}}/lib/modules/${{KVER}}/${{INTEL_DIR}}/auxiliary/intel_auxiliary.ko + install -D -m 644 src/Module.symvers ${{INSTALL_DIR}}/lib/modules/${{KVER}}/extern-symvers/intel_auxiliary.symvers + install -D -m 644 src/linux/auxiliary_bus.h ${{INSTALL_DIR}}/${{KSRC_INSTALL}}/include/linux/auxiliary_bus.h + +''' +bild_rules = Path(f'{DRIVER_DIR}/debian/rules') +bild_rules.write_text(build_rules_text) + +# build a package +debuild_cmd = ['debuild'] +run(debuild_cmd, cwd=DRIVER_DIR) diff --git a/packages/linux-kernel/build-intel-qat.sh b/packages/linux-kernel/build-intel-qat.sh index 795c4526..8e48337b 100755 --- a/packages/linux-kernel/build-intel-qat.sh +++ b/packages/linux-kernel/build-intel-qat.sh @@ -2,6 +2,11 @@ CWD=$(pwd) KERNEL_VAR_FILE=${CWD}/kernel-vars +if ! dpkg-architecture -iamd64; then + echo "Intel-QAT is only buildable on amd64 platforms" + exit 0 +fi + if [ ! -f ${KERNEL_VAR_FILE} ]; then echo "Kernel variable file '${KERNEL_VAR_FILE}' does not exist, run ./build_kernel.sh first" exit 1 @@ -9,98 +14,99 @@ fi . ${KERNEL_VAR_FILE} -declare -a intel=( - "https://01.org/sites/default/files/downloads/qat1.7.l.4.9.0-00008.tar_0.gz" -) - -for url in "${intel[@]}" -do - cd ${CWD} - - DRIVER_FILE=$(basename ${url} | sed -e s/tar_0/tar/) - DRIVER_DIR="${DRIVER_FILE%.tar.gz}" - DRIVER_NAME="qat" - DRIVER_VERSION=$(echo ${DRIVER_DIR} | awk -F${DRIVER_NAME} '{print $2}') - DRIVER_VERSION_EXTRA="-0" - - # Build up Debian related variables required for packaging - DEBIAN_ARCH=$(dpkg --print-architecture) - DEBIAN_DIR="${CWD}/vyos-intel-${DRIVER_NAME}_${DRIVER_VERSION}${DRIVER_VERSION_EXTRA}_${DEBIAN_ARCH}" - DEBIAN_CONTROL="${DEBIAN_DIR}/DEBIAN/control" - DEBIAN_POSTINST="${CWD}/vyos-intel-qat.postinst" - - # Fetch Intel driver source from SourceForge - if [ -e ${DRIVER_FILE} ]; then - rm -f ${DRIVER_FILE} - fi - curl -L -o ${DRIVER_FILE} ${url} - if [ "$?" -ne "0" ]; then - exit 1 - fi - - # Unpack archive - if [ -d ${DRIVER_DIR} ]; then - rm -rf ${DRIVER_DIR} - fi - mkdir -p ${DRIVER_DIR} - tar -C ${DRIVER_DIR} -xf ${DRIVER_FILE} - - cd ${DRIVER_DIR} - if [ -z $KERNEL_DIR ]; then - echo "KERNEL_DIR not defined" - exit 1 - fi - - echo "I: Compile Kernel module for Intel ${DRIVER_NAME} driver" - mkdir -p ${DEBIAN_DIR}/lib/firmware ${DEBIAN_DIR}/usr/local/bin ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu ${DEBIAN_DIR}/etc/init.d - KERNEL_SOURCE_ROOT=${KERNEL_DIR} ./configure --enable-kapi --enable-qat-lkcf - make -j $(getconf _NPROCESSORS_ONLN) all - make INSTALL_MOD_PATH=${DEBIAN_DIR} INSTALL_FW_PATH=${DEBIAN_DIR} \ - qat-driver-install - - if [ "x$?" != "x0" ]; then - exit 1 - fi - - cp build/*.bin ${DEBIAN_DIR}/lib/firmware - cp build/*.so ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu - cp build/qat_service ${DEBIAN_DIR}/etc/init.d - cp build/adf_ctl ${DEBIAN_DIR}/usr/local/bin - cp build/usdm_drv.ko ${DEBIAN_DIR}/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/updates/drivers - chmod 644 ${DEBIAN_DIR}/lib/firmware/* - chmod 755 ${DEBIAN_DIR}/etc/init.d/* ${DEBIAN_DIR}/usr/local/bin/* - - if [ -f ${DEBIAN_DIR}.deb ]; then - rm ${DEBIAN_DIR}.deb - fi - - # build Debian package - echo "I: Building Debian package vyos-intel-${DRIVER_NAME}" - cd ${CWD} - - # delete non required files which are also present in the kernel package - # und thus lead to duplicated files - find ${DEBIAN_DIR} -name "modules.*" | xargs rm -f - - echo "#!/bin/sh" > ${DEBIAN_POSTINST} - echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST} - - fpm --input-type dir --output-type deb --name vyos-intel-${DRIVER_NAME} \ - --version ${DRIVER_VERSION}${DRIVER_VERSION_EXTRA} --deb-compression gz \ - --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \ - --description "Vendor based driver for Intel ${DRIVER_NAME}" \ - --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \ - --license "GPL2" -C ${DEBIAN_DIR} --after-install ${DEBIAN_POSTINST} - - echo "I: Cleanup ${DRIVER_NAME} source" - cd ${CWD} - if [ -e ${DRIVER_FILE} ]; then - rm -f ${DRIVER_FILE} - fi - if [ -d ${DRIVER_DIR} ]; then - rm -rf ${DRIVER_DIR} - fi - if [ -d ${DEBIAN_DIR} ]; then - rm -rf ${DEBIAN_DIR} - fi -done +url="https://dev.packages.vyos.net/source-mirror/QAT1.7.l.4.9.0-00008.tar.gz" + +cd ${CWD} + +DRIVER_FILE=$(basename ${url} | sed -e s/tar_0/tar/) +DRIVER_DIR="${DRIVER_FILE%.tar.gz}" +DRIVER_NAME="QAT" +DRIVER_VERSION=$(echo ${DRIVER_DIR} | awk -F${DRIVER_NAME} '{print $2}') +DRIVER_VERSION_EXTRA="-0" + +# Build up Debian related variables required for packaging +DEBIAN_ARCH=$(dpkg --print-architecture) +DEBIAN_DIR="${CWD}/vyos-intel-${DRIVER_NAME}_${DRIVER_VERSION}${DRIVER_VERSION_EXTRA}_${DEBIAN_ARCH}" +DEBIAN_CONTROL="${DEBIAN_DIR}/DEBIAN/control" +DEBIAN_POSTINST="${CWD}/vyos-intel-qat.postinst" + +# Fetch Intel driver source from SourceForge +if [ -e ${DRIVER_FILE} ]; then + rm -f ${DRIVER_FILE} +fi +curl -L -o ${DRIVER_FILE} ${url} +if [ "$?" -ne "0" ]; then + exit 1 +fi + +# Unpack archive +if [ -d ${DRIVER_DIR} ]; then + rm -rf ${DRIVER_DIR} +fi +mkdir -p ${DRIVER_DIR} +tar -C ${DRIVER_DIR} -xf ${DRIVER_FILE} + +cd ${DRIVER_DIR} +if [ -z $KERNEL_DIR ]; then + echo "KERNEL_DIR not defined" + exit 1 +fi + +echo "I: Compile Kernel module for Intel ${DRIVER_NAME} driver" +mkdir -p \ + ${DEBIAN_DIR}/lib/firmware \ + ${DEBIAN_DIR}/usr/sbin \ + ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu \ + ${DEBIAN_DIR}/etc/init.d + +KERNEL_SOURCE_ROOT=${KERNEL_DIR} ./configure --enable-kapi --enable-qat-lkcf +make -j $(getconf _NPROCESSORS_ONLN) all +make INSTALL_MOD_PATH=${DEBIAN_DIR} INSTALL_FW_PATH=${DEBIAN_DIR} \ + qat-driver-install adf-ctl-all + +if [ "x$?" != "x0" ]; then + exit 1 +fi + +cp quickassist/qat/fw/*.bin ${DEBIAN_DIR}/lib/firmware +cp build/*.so ${DEBIAN_DIR}/usr/lib/x86_64-linux-gnu +cp build/adf_ctl ${DEBIAN_DIR}/usr/sbin +cp quickassist/build_system/build_files/qat_service ${DEBIAN_DIR}/etc/init.d +cp build/usdm_drv.ko ${DEBIAN_DIR}/lib/modules/${KERNEL_VERSION}${KERNEL_SUFFIX}/updates/drivers + +chmod 644 ${DEBIAN_DIR}/lib/firmware/* +chmod 755 ${DEBIAN_DIR}/etc/init.d/* ${DEBIAN_DIR}/usr/local/bin/* + +if [ -f ${DEBIAN_DIR}.deb ]; then + rm ${DEBIAN_DIR}.deb +fi + +# build Debian package +echo "I: Building Debian package vyos-intel-${DRIVER_NAME}" +cd ${CWD} + +# delete non required files which are also present in the kernel package +# und thus lead to duplicated files +find ${DEBIAN_DIR} -name "modules.*" | xargs rm -f + +echo "#!/bin/sh" > ${DEBIAN_POSTINST} +echo "/sbin/depmod -a ${KERNEL_VERSION}${KERNEL_SUFFIX}" >> ${DEBIAN_POSTINST} + +fpm --input-type dir --output-type deb --name vyos-intel-${DRIVER_NAME} \ + --version ${DRIVER_VERSION}${DRIVER_VERSION_EXTRA} --deb-compression gz \ + --maintainer "VyOS Package Maintainers <maintainers@vyos.net>" \ + --description "Vendor based driver for Intel ${DRIVER_NAME}" \ + --depends linux-image-${KERNEL_VERSION}${KERNEL_SUFFIX} \ + --license "GPL2" -C ${DEBIAN_DIR} --after-install ${DEBIAN_POSTINST} + +echo "I: Cleanup ${DRIVER_NAME} source" +cd ${CWD} +if [ -e ${DRIVER_FILE} ]; then + rm -f ${DRIVER_FILE} +fi +if [ -d ${DRIVER_DIR} ]; then + rm -rf ${DRIVER_DIR} +fi +if [ -d ${DEBIAN_DIR} ]; then + rm -rf ${DEBIAN_DIR} +fi diff --git a/packages/linux-kernel/build-linux-firmware.sh b/packages/linux-kernel/build-linux-firmware.sh index 3e5274fa..7b108195 100755 --- a/packages/linux-kernel/build-linux-firmware.sh +++ b/packages/linux-kernel/build-linux-firmware.sh @@ -38,15 +38,46 @@ if [ -d ${VYOS_FIRMWARE_DIR} ]; then fi mkdir -p ${VYOS_FIRMWARE_DIR} -# Copy firmware file from linux firmware repository into +# Install firmware files to build directory +LINUX_FIRMWARE_BUILD_DIR="${LINUX_FIRMWARE}_${GIT_COMMIT}" + +if [ -d ${LINUX_FIRMWARE_BUILD_DIR} ]; then + rm -rf "${LINUX_FIRMWARE_BUILD_DIR}" +fi + +mkdir -p "${LINUX_FIRMWARE_BUILD_DIR}" + +( + cd ${LINUX_FIRMWARE} + ./copy-firmware.sh "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}" +) + +# Copy firmware file from linux firmware build directory into # assembly folder for the vyos-firmware package SED_REPLACE="s@${CWD}/${LINUX_FIRMWARE}/@@" for FILE in ${FW_FILES}; do - if [ -f ${LINUX_FIRMWARE}/${FILE} ]; then + # If file is a symlink install the symlink target as well + if [ -h "${LINUX_FIRMWARE_BUILD_DIR}/${FILE}" ]; then + TARGET="$(realpath --relative-to="${LINUX_FIRMWARE_BUILD_DIR}" "${LINUX_FIRMWARE_BUILD_DIR}/${FILE}")" + TARGET_DIR="${VYOS_FIRMWARE_DIR}/lib/firmware/$(dirname "${TARGET}")" + + if [ ! -f "${TARGET_DIR}/$(basename "${TARGET}")" ]; then + if [ -f "${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" ]; then + mkdir -p "${TARGET_DIR}" + + echo "I: install firmware: ${TARGET}" + cp "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${TARGET}" "${TARGET_DIR}" + else + echo "I: firmware file not found: ${TARGET}" + fi + fi + fi + + if [ -f ${LINUX_FIRMWARE_BUILD_DIR}/${FILE} ]; then FW_DIR="${VYOS_FIRMWARE_DIR}/lib/firmware/$(dirname ${FILE})" - mkdir -p ${FW_DIR} + mkdir -p "${FW_DIR}" echo "I: install firmware: ${FILE}" - cp ${CWD}/${LINUX_FIRMWARE}/${FILE} ${FW_DIR} + cp -P "${CWD}/${LINUX_FIRMWARE_BUILD_DIR}/${FILE}" "${FW_DIR}" else echo "I: firmware file not found: ${FILE}" fi @@ -59,4 +90,5 @@ fpm --input-type dir --output-type deb --name ${VYOS_FIRMWARE_NAME} \ --description "Binary firmware for various drivers in the Linux kernel" \ --architecture all --version ${GIT_COMMIT} --deb-compression gz -C ${VYOS_FIRMWARE_DIR} +rm -rf "${LINUX_FIRMWARE_BUILD_DIR}" rm -rf ${VYOS_FIRMWARE_DIR} diff --git a/packages/linux-kernel/patches/kernel/0001-linkstate-ip-device-attribute.patch b/packages/linux-kernel/patches/kernel/0001-linkstate-ip-device-attribute.patch index 2be1a3c8..fb94c163 100644 --- a/packages/linux-kernel/patches/kernel/0001-linkstate-ip-device-attribute.patch +++ b/packages/linux-kernel/patches/kernel/0001-linkstate-ip-device-attribute.patch @@ -19,7 +19,7 @@ Backport of earlier Vyatta patch. 8 files changed, 39 insertions(+) diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt -index 8af3771a3ebf..93408cc52991 100644 +index 5cf601c94e35..12457ee20f22 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1245,6 +1245,19 @@ rp_filter - INTEGER @@ -43,7 +43,7 @@ index 8af3771a3ebf..93408cc52991 100644 1 - Allows you to have multiple network interfaces on the same subnet, and have the ARPs for each interface be answered diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h -index 3515ca64e638..dcae58193580 100644 +index b68fca08be27..9cdfccdbb9fb 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h @@ -133,6 +133,7 @@ static inline void ipv4_devconf_setall(struct in_device *in_dev) @@ -55,7 +55,7 @@ index 3515ca64e638..dcae58193580 100644 struct in_ifaddr { struct hlist_node hash; diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h -index ea7c7906591e..57f656ea2783 100644 +index d5c507311efb..066ad20f2b39 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -76,6 +76,7 @@ struct ipv6_devconf { @@ -91,7 +91,7 @@ index 9c0f4a92bcff..619edd130cfd 100644 }; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c -index a27d034c85cc..b62b62abe907 100644 +index 4c013f8800f0..409050b2bc44 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -2550,6 +2550,8 @@ static struct devinet_sysctl_table { @@ -104,10 +104,10 @@ index a27d034c85cc..b62b62abe907 100644 }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index 635b2482fa20..ce1405ecf6f6 100644 +index c523236d934e..1bd2b92a017f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c -@@ -5477,6 +5477,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, +@@ -5507,6 +5507,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode; array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy; array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass; @@ -115,7 +115,7 @@ index 635b2482fa20..ce1405ecf6f6 100644 } static inline size_t inet6_ifla6_size(void) -@@ -6849,6 +6850,14 @@ static const struct ctl_table addrconf_sysctl[] = { +@@ -6879,6 +6880,14 @@ static const struct ctl_table addrconf_sysctl[] = { .mode = 0644, .proc_handler = addrconf_sysctl_disable_policy, }, @@ -131,10 +131,10 @@ index 635b2482fa20..ce1405ecf6f6 100644 .procname = "ndisc_tclass", .data = &ipv6_devconf.ndisc_tclass, diff --git a/net/ipv6/route.c b/net/ipv6/route.c -index 46df6345bb99..2b930a2c4fdb 100644 +index 209d52ebbd19..edf7b5e9466a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c -@@ -686,6 +686,15 @@ static inline void rt6_probe(struct fib6_nh *fib6_nh) +@@ -687,6 +687,15 @@ static inline void rt6_probe(struct fib6_nh *fib6_nh) } #endif @@ -150,7 +150,7 @@ index 46df6345bb99..2b930a2c4fdb 100644 /* * Default Router Selection (RFC 2461 6.3.6) */ -@@ -727,6 +736,8 @@ static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif, +@@ -728,6 +737,8 @@ static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif, if (!m && (strict & RT6_LOOKUP_F_IFACE)) return RT6_NUD_FAIL_HARD; @@ -160,5 +160,5 @@ index 46df6345bb99..2b930a2c4fdb 100644 m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(fib6_flags)) << 2; #endif -- -2.20.1 +2.39.2 diff --git a/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch b/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch index 21f4cd60..8f4b003d 100644 --- a/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch +++ b/packages/linux-kernel/patches/kernel/0002-inotify-support-for-stackable-filesystems.patch @@ -44,7 +44,7 @@ index 6736e47d94d8..84d9b31300c0 100644 + + If unsure, say N. diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c -index 81ffc8629fc4..cacedffa6534 100644 +index b949b2c02f4b..5bbb53db64a4 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -15,6 +15,7 @@ @@ -186,7 +186,7 @@ index 81ffc8629fc4..cacedffa6534 100644 struct inotify_inode_mark *i_mark) { diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c -index d6b724beb304..380ac598f2e4 100644 +index f5cf0938f298..c3bb42c9d291 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -15,6 +15,7 @@ @@ -197,7 +197,7 @@ index d6b724beb304..380ac598f2e4 100644 #include "overlayfs.h" MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); -@@ -1758,6 +1759,18 @@ static void ovl_inode_init_once(void *foo) +@@ -1767,6 +1768,18 @@ static void ovl_inode_init_once(void *foo) inode_init_once(&oi->vfs_inode); } @@ -216,7 +216,7 @@ index d6b724beb304..380ac598f2e4 100644 static int __init ovl_init(void) { int err; -@@ -1772,13 +1785,21 @@ static int __init ovl_init(void) +@@ -1781,13 +1794,21 @@ static int __init ovl_init(void) err = register_filesystem(&ovl_fs_type); if (err) @@ -239,7 +239,7 @@ index d6b724beb304..380ac598f2e4 100644 unregister_filesystem(&ovl_fs_type); /* -@@ -1787,7 +1808,6 @@ static void __exit ovl_exit(void) +@@ -1796,7 +1817,6 @@ static void __exit ovl_exit(void) */ rcu_barrier(); kmem_cache_destroy(ovl_inode_cachep); @@ -292,5 +292,5 @@ index 6a24905f6e1e..4484f0760588 100644 + #endif /* _LINUX_INOTIFY_H */ -- -2.20.1 +2.39.2 diff --git a/packages/linux-kernel/patches/kernel/0004-revert-net-sched-retire-tcindex-classifier.patch b/packages/linux-kernel/patches/kernel/0004-revert-net-sched-retire-tcindex-classifier.patch new file mode 100644 index 00000000..2eb806a7 --- /dev/null +++ b/packages/linux-kernel/patches/kernel/0004-revert-net-sched-retire-tcindex-classifier.patch @@ -0,0 +1,786 @@ +From 58559e68b5a93bebf630c5ac99981ec054612583 Mon Sep 17 00:00:00 2001 +From: Christian Breunig <christian@breunig.cc> +Date: Fri, 24 Nov 2023 09:28:56 +0100 +Subject: [PATCH] Revert "net/sched: Retire tcindex classifier" + +This reverts commit 7a6fb69bbcb21e9ce13bdf18c008c268874f0480. +--- + net/sched/Kconfig | 11 + + net/sched/Makefile | 1 + + net/sched/cls_tcindex.c | 730 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 742 insertions(+) + create mode 100644 net/sched/cls_tcindex.c + +diff --git a/net/sched/Kconfig b/net/sched/Kconfig +index 46f2847a071e..131e653e9945 100644 +--- a/net/sched/Kconfig ++++ b/net/sched/Kconfig +@@ -469,6 +469,17 @@ config NET_CLS_BASIC + To compile this code as a module, choose M here: the + module will be called cls_basic. + ++config NET_CLS_TCINDEX ++ tristate "Traffic-Control Index (TCINDEX)" ++ select NET_CLS ++ ---help--- ++ Say Y here if you want to be able to classify packets based on ++ traffic control indices. You will want this feature if you want ++ to implement Differentiated Services together with DSMARK. ++ ++ To compile this code as a module, choose M here: the ++ module will be called cls_tcindex. ++ + config NET_CLS_ROUTE4 + tristate "Routing decision (ROUTE)" + depends on INET +diff --git a/net/sched/Makefile b/net/sched/Makefile +index fb2b90648a20..b2dcc40d92da 100644 +--- a/net/sched/Makefile ++++ b/net/sched/Makefile +@@ -65,6 +65,7 @@ obj-$(CONFIG_NET_SCH_TAPRIO) += sch_taprio.o + obj-$(CONFIG_NET_CLS_U32) += cls_u32.o + obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o + obj-$(CONFIG_NET_CLS_FW) += cls_fw.o ++obj-$(CONFIG_NET_CLS_TCINDEX) += cls_tcindex.o + obj-$(CONFIG_NET_CLS_BASIC) += cls_basic.o + obj-$(CONFIG_NET_CLS_FLOW) += cls_flow.o + obj-$(CONFIG_NET_CLS_CGROUP) += cls_cgroup.o +diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c +new file mode 100644 +index 000000000000..768cf7cf65b4 +--- /dev/null ++++ b/net/sched/cls_tcindex.c +@@ -0,0 +1,730 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * net/sched/cls_tcindex.c Packet classifier for skb->tc_index ++ * ++ * Written 1998,1999 by Werner Almesberger, EPFL ICA ++ */ ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/skbuff.h> ++#include <linux/errno.h> ++#include <linux/slab.h> ++#include <linux/refcount.h> ++#include <net/act_api.h> ++#include <net/netlink.h> ++#include <net/pkt_cls.h> ++#include <net/sch_generic.h> ++ ++/* ++ * Passing parameters to the root seems to be done more awkwardly than really ++ * necessary. At least, u32 doesn't seem to use such dirty hacks. To be ++ * verified. FIXME. ++ */ ++ ++#define PERFECT_HASH_THRESHOLD 64 /* use perfect hash if not bigger */ ++#define DEFAULT_HASH_SIZE 64 /* optimized for diffserv */ ++ ++ ++struct tcindex_data; ++ ++struct tcindex_filter_result { ++ struct tcf_exts exts; ++ struct tcf_result res; ++ struct tcindex_data *p; ++ struct rcu_work rwork; ++}; ++ ++struct tcindex_filter { ++ u16 key; ++ struct tcindex_filter_result result; ++ struct tcindex_filter __rcu *next; ++ struct rcu_work rwork; ++}; ++ ++ ++struct tcindex_data { ++ struct tcindex_filter_result *perfect; /* perfect hash; NULL if none */ ++ struct tcindex_filter __rcu **h; /* imperfect hash; */ ++ struct tcf_proto *tp; ++ u16 mask; /* AND key with mask */ ++ u32 shift; /* shift ANDed key to the right */ ++ u32 hash; /* hash table size; 0 if undefined */ ++ u32 alloc_hash; /* allocated size */ ++ u32 fall_through; /* 0: only classify if explicit match */ ++ refcount_t refcnt; /* a temporary refcnt for perfect hash */ ++ struct rcu_work rwork; ++}; ++ ++static inline int tcindex_filter_is_set(struct tcindex_filter_result *r) ++{ ++ return tcf_exts_has_actions(&r->exts) || r->res.classid; ++} ++ ++static void tcindex_data_get(struct tcindex_data *p) ++{ ++ refcount_inc(&p->refcnt); ++} ++ ++static void tcindex_data_put(struct tcindex_data *p) ++{ ++ if (refcount_dec_and_test(&p->refcnt)) { ++ kfree(p->perfect); ++ kfree(p->h); ++ kfree(p); ++ } ++} ++ ++static struct tcindex_filter_result *tcindex_lookup(struct tcindex_data *p, ++ u16 key) ++{ ++ if (p->perfect) { ++ struct tcindex_filter_result *f = p->perfect + key; ++ ++ return tcindex_filter_is_set(f) ? f : NULL; ++ } else if (p->h) { ++ struct tcindex_filter __rcu **fp; ++ struct tcindex_filter *f; ++ ++ fp = &p->h[key % p->hash]; ++ for (f = rcu_dereference_bh_rtnl(*fp); ++ f; ++ fp = &f->next, f = rcu_dereference_bh_rtnl(*fp)) ++ if (f->key == key) ++ return &f->result; ++ } ++ ++ return NULL; ++} ++ ++ ++static int tcindex_classify(struct sk_buff *skb, const struct tcf_proto *tp, ++ struct tcf_result *res) ++{ ++ struct tcindex_data *p = rcu_dereference_bh(tp->root); ++ struct tcindex_filter_result *f; ++ int key = (skb->tc_index & p->mask) >> p->shift; ++ ++ pr_debug("tcindex_classify(skb %p,tp %p,res %p),p %p\n", ++ skb, tp, res, p); ++ ++ f = tcindex_lookup(p, key); ++ if (!f) { ++ struct Qdisc *q = tcf_block_q(tp->chain->block); ++ ++ if (!p->fall_through) ++ return -1; ++ res->classid = TC_H_MAKE(TC_H_MAJ(q->handle), key); ++ res->class = 0; ++ pr_debug("alg 0x%x\n", res->classid); ++ return 0; ++ } ++ *res = f->res; ++ pr_debug("map 0x%x\n", res->classid); ++ ++ return tcf_exts_exec(skb, &f->exts, res); ++} ++ ++ ++static void *tcindex_get(struct tcf_proto *tp, u32 handle) ++{ ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ struct tcindex_filter_result *r; ++ ++ pr_debug("tcindex_get(tp %p,handle 0x%08x)\n", tp, handle); ++ if (p->perfect && handle >= p->alloc_hash) ++ return NULL; ++ r = tcindex_lookup(p, handle); ++ return r && tcindex_filter_is_set(r) ? r : NULL; ++} ++ ++static int tcindex_init(struct tcf_proto *tp) ++{ ++ struct tcindex_data *p; ++ ++ pr_debug("tcindex_init(tp %p)\n", tp); ++ p = kzalloc(sizeof(struct tcindex_data), GFP_KERNEL); ++ if (!p) ++ return -ENOMEM; ++ ++ p->mask = 0xffff; ++ p->hash = DEFAULT_HASH_SIZE; ++ p->fall_through = 1; ++ refcount_set(&p->refcnt, 1); /* Paired with tcindex_destroy_work() */ ++ ++ rcu_assign_pointer(tp->root, p); ++ return 0; ++} ++ ++static void __tcindex_destroy_rexts(struct tcindex_filter_result *r) ++{ ++ tcf_exts_destroy(&r->exts); ++ tcf_exts_put_net(&r->exts); ++ tcindex_data_put(r->p); ++} ++ ++static void tcindex_destroy_rexts_work(struct work_struct *work) ++{ ++ struct tcindex_filter_result *r; ++ ++ r = container_of(to_rcu_work(work), ++ struct tcindex_filter_result, ++ rwork); ++ rtnl_lock(); ++ __tcindex_destroy_rexts(r); ++ rtnl_unlock(); ++} ++ ++static void __tcindex_destroy_fexts(struct tcindex_filter *f) ++{ ++ tcf_exts_destroy(&f->result.exts); ++ tcf_exts_put_net(&f->result.exts); ++ kfree(f); ++} ++ ++static void tcindex_destroy_fexts_work(struct work_struct *work) ++{ ++ struct tcindex_filter *f = container_of(to_rcu_work(work), ++ struct tcindex_filter, ++ rwork); ++ ++ rtnl_lock(); ++ __tcindex_destroy_fexts(f); ++ rtnl_unlock(); ++} ++ ++static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last, ++ bool rtnl_held, struct netlink_ext_ack *extack) ++{ ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ struct tcindex_filter_result *r = arg; ++ struct tcindex_filter __rcu **walk; ++ struct tcindex_filter *f = NULL; ++ ++ pr_debug("tcindex_delete(tp %p,arg %p),p %p\n", tp, arg, p); ++ if (p->perfect) { ++ if (!r->res.class) ++ return -ENOENT; ++ } else { ++ int i; ++ ++ for (i = 0; i < p->hash; i++) { ++ walk = p->h + i; ++ for (f = rtnl_dereference(*walk); f; ++ walk = &f->next, f = rtnl_dereference(*walk)) { ++ if (&f->result == r) ++ goto found; ++ } ++ } ++ return -ENOENT; ++ ++found: ++ rcu_assign_pointer(*walk, rtnl_dereference(f->next)); ++ } ++ tcf_unbind_filter(tp, &r->res); ++ /* all classifiers are required to call tcf_exts_destroy() after rcu ++ * grace period, since converted-to-rcu actions are relying on that ++ * in cleanup() callback ++ */ ++ if (f) { ++ if (tcf_exts_get_net(&f->result.exts)) ++ tcf_queue_work(&f->rwork, tcindex_destroy_fexts_work); ++ else ++ __tcindex_destroy_fexts(f); ++ } else { ++ tcindex_data_get(p); ++ ++ if (tcf_exts_get_net(&r->exts)) ++ tcf_queue_work(&r->rwork, tcindex_destroy_rexts_work); ++ else ++ __tcindex_destroy_rexts(r); ++ } ++ ++ *last = false; ++ return 0; ++} ++ ++static void tcindex_destroy_work(struct work_struct *work) ++{ ++ struct tcindex_data *p = container_of(to_rcu_work(work), ++ struct tcindex_data, ++ rwork); ++ ++ tcindex_data_put(p); ++} ++ ++static inline int ++valid_perfect_hash(struct tcindex_data *p) ++{ ++ return p->hash > (p->mask >> p->shift); ++} ++ ++static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = { ++ [TCA_TCINDEX_HASH] = { .type = NLA_U32 }, ++ [TCA_TCINDEX_MASK] = { .type = NLA_U16 }, ++ [TCA_TCINDEX_SHIFT] = { .type = NLA_U32 }, ++ [TCA_TCINDEX_FALL_THROUGH] = { .type = NLA_U32 }, ++ [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 }, ++}; ++ ++static int tcindex_filter_result_init(struct tcindex_filter_result *r, ++ struct tcindex_data *p, ++ struct net *net) ++{ ++ memset(r, 0, sizeof(*r)); ++ r->p = p; ++ return tcf_exts_init(&r->exts, net, TCA_TCINDEX_ACT, ++ TCA_TCINDEX_POLICE); ++} ++ ++static void tcindex_free_perfect_hash(struct tcindex_data *cp); ++ ++static void tcindex_partial_destroy_work(struct work_struct *work) ++{ ++ struct tcindex_data *p = container_of(to_rcu_work(work), ++ struct tcindex_data, ++ rwork); ++ ++ rtnl_lock(); ++ if (p->perfect) ++ tcindex_free_perfect_hash(p); ++ kfree(p); ++ rtnl_unlock(); ++} ++ ++static void tcindex_free_perfect_hash(struct tcindex_data *cp) ++{ ++ int i; ++ ++ for (i = 0; i < cp->hash; i++) ++ tcf_exts_destroy(&cp->perfect[i].exts); ++ kfree(cp->perfect); ++} ++ ++static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp) ++{ ++ int i, err = 0; ++ ++ cp->perfect = kcalloc(cp->hash, sizeof(struct tcindex_filter_result), ++ GFP_KERNEL | __GFP_NOWARN); ++ if (!cp->perfect) ++ return -ENOMEM; ++ ++ for (i = 0; i < cp->hash; i++) { ++ err = tcf_exts_init(&cp->perfect[i].exts, net, ++ TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); ++ if (err < 0) ++ goto errout; ++ cp->perfect[i].p = cp; ++ } ++ ++ return 0; ++ ++errout: ++ tcindex_free_perfect_hash(cp); ++ return err; ++} ++ ++static int ++tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, ++ u32 handle, struct tcindex_data *p, ++ struct tcindex_filter_result *r, struct nlattr **tb, ++ struct nlattr *est, bool ovr, struct netlink_ext_ack *extack) ++{ ++ struct tcindex_filter_result new_filter_result; ++ struct tcindex_data *cp = NULL, *oldp; ++ struct tcindex_filter *f = NULL; /* make gcc behave */ ++ struct tcf_result cr = {}; ++ int err, balloc = 0; ++ struct tcf_exts e; ++ ++ err = tcf_exts_init(&e, net, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); ++ if (err < 0) ++ return err; ++ err = tcf_exts_validate(net, tp, tb, est, &e, ovr, true, extack); ++ if (err < 0) ++ goto errout; ++ ++ err = -ENOMEM; ++ /* tcindex_data attributes must look atomic to classifier/lookup so ++ * allocate new tcindex data and RCU assign it onto root. Keeping ++ * perfect hash and hash pointers from old data. ++ */ ++ cp = kzalloc(sizeof(*cp), GFP_KERNEL); ++ if (!cp) ++ goto errout; ++ ++ cp->mask = p->mask; ++ cp->shift = p->shift; ++ cp->hash = p->hash; ++ cp->alloc_hash = p->alloc_hash; ++ cp->fall_through = p->fall_through; ++ cp->tp = tp; ++ refcount_set(&cp->refcnt, 1); /* Paired with tcindex_destroy_work() */ ++ ++ if (tb[TCA_TCINDEX_HASH]) ++ cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); ++ ++ if (tb[TCA_TCINDEX_MASK]) ++ cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); ++ ++ if (tb[TCA_TCINDEX_SHIFT]) { ++ cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); ++ if (cp->shift > 16) { ++ err = -EINVAL; ++ goto errout; ++ } ++ } ++ if (!cp->hash) { ++ /* Hash not specified, use perfect hash if the upper limit ++ * of the hashing index is below the threshold. ++ */ ++ if ((cp->mask >> cp->shift) < PERFECT_HASH_THRESHOLD) ++ cp->hash = (cp->mask >> cp->shift) + 1; ++ else ++ cp->hash = DEFAULT_HASH_SIZE; ++ } ++ ++ if (p->perfect) { ++ int i; ++ ++ if (tcindex_alloc_perfect_hash(net, cp) < 0) ++ goto errout; ++ cp->alloc_hash = cp->hash; ++ for (i = 0; i < min(cp->hash, p->hash); i++) ++ cp->perfect[i].res = p->perfect[i].res; ++ balloc = 1; ++ } ++ cp->h = p->h; ++ ++ err = tcindex_filter_result_init(&new_filter_result, cp, net); ++ if (err < 0) ++ goto errout_alloc; ++ if (r) ++ cr = r->res; ++ ++ err = -EBUSY; ++ ++ /* Hash already allocated, make sure that we still meet the ++ * requirements for the allocated hash. ++ */ ++ if (cp->perfect) { ++ if (!valid_perfect_hash(cp) || ++ cp->hash > cp->alloc_hash) ++ goto errout_alloc; ++ } else if (cp->h && cp->hash != cp->alloc_hash) { ++ goto errout_alloc; ++ } ++ ++ err = -EINVAL; ++ if (tb[TCA_TCINDEX_FALL_THROUGH]) ++ cp->fall_through = nla_get_u32(tb[TCA_TCINDEX_FALL_THROUGH]); ++ ++ if (!cp->perfect && !cp->h) ++ cp->alloc_hash = cp->hash; ++ ++ /* Note: this could be as restrictive as if (handle & ~(mask >> shift)) ++ * but then, we'd fail handles that may become valid after some future ++ * mask change. While this is extremely unlikely to ever matter, ++ * the check below is safer (and also more backwards-compatible). ++ */ ++ if (cp->perfect || valid_perfect_hash(cp)) ++ if (handle >= cp->alloc_hash) ++ goto errout_alloc; ++ ++ ++ err = -ENOMEM; ++ if (!cp->perfect && !cp->h) { ++ if (valid_perfect_hash(cp)) { ++ if (tcindex_alloc_perfect_hash(net, cp) < 0) ++ goto errout_alloc; ++ balloc = 1; ++ } else { ++ struct tcindex_filter __rcu **hash; ++ ++ hash = kcalloc(cp->hash, ++ sizeof(struct tcindex_filter *), ++ GFP_KERNEL); ++ ++ if (!hash) ++ goto errout_alloc; ++ ++ cp->h = hash; ++ balloc = 2; ++ } ++ } ++ ++ if (cp->perfect) ++ r = cp->perfect + handle; ++ else ++ r = tcindex_lookup(cp, handle) ? : &new_filter_result; ++ ++ if (r == &new_filter_result) { ++ f = kzalloc(sizeof(*f), GFP_KERNEL); ++ if (!f) ++ goto errout_alloc; ++ f->key = handle; ++ f->next = NULL; ++ err = tcindex_filter_result_init(&f->result, cp, net); ++ if (err < 0) { ++ kfree(f); ++ goto errout_alloc; ++ } ++ } ++ ++ if (tb[TCA_TCINDEX_CLASSID]) { ++ cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]); ++ tcf_bind_filter(tp, &cr, base); ++ } ++ ++ oldp = p; ++ r->res = cr; ++ tcf_exts_change(&r->exts, &e); ++ ++ rcu_assign_pointer(tp->root, cp); ++ ++ if (r == &new_filter_result) { ++ struct tcindex_filter *nfp; ++ struct tcindex_filter __rcu **fp; ++ ++ f->result.res = r->res; ++ tcf_exts_change(&f->result.exts, &r->exts); ++ ++ fp = cp->h + (handle % cp->hash); ++ for (nfp = rtnl_dereference(*fp); ++ nfp; ++ fp = &nfp->next, nfp = rtnl_dereference(*fp)) ++ ; /* nothing */ ++ ++ rcu_assign_pointer(*fp, f); ++ } else { ++ tcf_exts_destroy(&new_filter_result.exts); ++ } ++ ++ if (oldp) ++ tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work); ++ return 0; ++ ++errout_alloc: ++ if (balloc == 1) ++ tcindex_free_perfect_hash(cp); ++ else if (balloc == 2) ++ kfree(cp->h); ++ tcf_exts_destroy(&new_filter_result.exts); ++errout: ++ kfree(cp); ++ tcf_exts_destroy(&e); ++ return err; ++} ++ ++static int ++tcindex_change(struct net *net, struct sk_buff *in_skb, ++ struct tcf_proto *tp, unsigned long base, u32 handle, ++ struct nlattr **tca, void **arg, bool ovr, ++ bool rtnl_held, struct netlink_ext_ack *extack) ++{ ++ struct nlattr *opt = tca[TCA_OPTIONS]; ++ struct nlattr *tb[TCA_TCINDEX_MAX + 1]; ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ struct tcindex_filter_result *r = *arg; ++ int err; ++ ++ pr_debug("tcindex_change(tp %p,handle 0x%08x,tca %p,arg %p),opt %p," ++ "p %p,r %p,*arg %p\n", ++ tp, handle, tca, arg, opt, p, r, arg ? *arg : NULL); ++ ++ if (!opt) ++ return 0; ++ ++ err = nla_parse_nested_deprecated(tb, TCA_TCINDEX_MAX, opt, ++ tcindex_policy, NULL); ++ if (err < 0) ++ return err; ++ ++ return tcindex_set_parms(net, tp, base, handle, p, r, tb, ++ tca[TCA_RATE], ovr, extack); ++} ++ ++static void tcindex_walk(struct tcf_proto *tp, struct tcf_walker *walker, ++ bool rtnl_held) ++{ ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ struct tcindex_filter *f, *next; ++ int i; ++ ++ pr_debug("tcindex_walk(tp %p,walker %p),p %p\n", tp, walker, p); ++ if (p->perfect) { ++ for (i = 0; i < p->hash; i++) { ++ if (!p->perfect[i].res.class) ++ continue; ++ if (walker->count >= walker->skip) { ++ if (walker->fn(tp, p->perfect + i, walker) < 0) { ++ walker->stop = 1; ++ return; ++ } ++ } ++ walker->count++; ++ } ++ } ++ if (!p->h) ++ return; ++ for (i = 0; i < p->hash; i++) { ++ for (f = rtnl_dereference(p->h[i]); f; f = next) { ++ next = rtnl_dereference(f->next); ++ if (walker->count >= walker->skip) { ++ if (walker->fn(tp, &f->result, walker) < 0) { ++ walker->stop = 1; ++ return; ++ } ++ } ++ walker->count++; ++ } ++ } ++} ++ ++static void tcindex_destroy(struct tcf_proto *tp, bool rtnl_held, ++ struct netlink_ext_ack *extack) ++{ ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ int i; ++ ++ pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); ++ ++ if (p->perfect) { ++ for (i = 0; i < p->hash; i++) { ++ struct tcindex_filter_result *r = p->perfect + i; ++ ++ /* tcf_queue_work() does not guarantee the ordering we ++ * want, so we have to take this refcnt temporarily to ++ * ensure 'p' is freed after all tcindex_filter_result ++ * here. Imperfect hash does not need this, because it ++ * uses linked lists rather than an array. ++ */ ++ tcindex_data_get(p); ++ ++ tcf_unbind_filter(tp, &r->res); ++ if (tcf_exts_get_net(&r->exts)) ++ tcf_queue_work(&r->rwork, ++ tcindex_destroy_rexts_work); ++ else ++ __tcindex_destroy_rexts(r); ++ } ++ } ++ ++ for (i = 0; p->h && i < p->hash; i++) { ++ struct tcindex_filter *f, *next; ++ bool last; ++ ++ for (f = rtnl_dereference(p->h[i]); f; f = next) { ++ next = rtnl_dereference(f->next); ++ tcindex_delete(tp, &f->result, &last, rtnl_held, NULL); ++ } ++ } ++ ++ tcf_queue_work(&p->rwork, tcindex_destroy_work); ++} ++ ++ ++static int tcindex_dump(struct net *net, struct tcf_proto *tp, void *fh, ++ struct sk_buff *skb, struct tcmsg *t, bool rtnl_held) ++{ ++ struct tcindex_data *p = rtnl_dereference(tp->root); ++ struct tcindex_filter_result *r = fh; ++ struct nlattr *nest; ++ ++ pr_debug("tcindex_dump(tp %p,fh %p,skb %p,t %p),p %p,r %p\n", ++ tp, fh, skb, t, p, r); ++ pr_debug("p->perfect %p p->h %p\n", p->perfect, p->h); ++ ++ nest = nla_nest_start_noflag(skb, TCA_OPTIONS); ++ if (nest == NULL) ++ goto nla_put_failure; ++ ++ if (!fh) { ++ t->tcm_handle = ~0; /* whatever ... */ ++ if (nla_put_u32(skb, TCA_TCINDEX_HASH, p->hash) || ++ nla_put_u16(skb, TCA_TCINDEX_MASK, p->mask) || ++ nla_put_u32(skb, TCA_TCINDEX_SHIFT, p->shift) || ++ nla_put_u32(skb, TCA_TCINDEX_FALL_THROUGH, p->fall_through)) ++ goto nla_put_failure; ++ nla_nest_end(skb, nest); ++ } else { ++ if (p->perfect) { ++ t->tcm_handle = r - p->perfect; ++ } else { ++ struct tcindex_filter *f; ++ struct tcindex_filter __rcu **fp; ++ int i; ++ ++ t->tcm_handle = 0; ++ for (i = 0; !t->tcm_handle && i < p->hash; i++) { ++ fp = &p->h[i]; ++ for (f = rtnl_dereference(*fp); ++ !t->tcm_handle && f; ++ fp = &f->next, f = rtnl_dereference(*fp)) { ++ if (&f->result == r) ++ t->tcm_handle = f->key; ++ } ++ } ++ } ++ pr_debug("handle = %d\n", t->tcm_handle); ++ if (r->res.class && ++ nla_put_u32(skb, TCA_TCINDEX_CLASSID, r->res.classid)) ++ goto nla_put_failure; ++ ++ if (tcf_exts_dump(skb, &r->exts) < 0) ++ goto nla_put_failure; ++ nla_nest_end(skb, nest); ++ ++ if (tcf_exts_dump_stats(skb, &r->exts) < 0) ++ goto nla_put_failure; ++ } ++ ++ return skb->len; ++ ++nla_put_failure: ++ nla_nest_cancel(skb, nest); ++ return -1; ++} ++ ++static void tcindex_bind_class(void *fh, u32 classid, unsigned long cl, ++ void *q, unsigned long base) ++{ ++ struct tcindex_filter_result *r = fh; ++ ++ if (r && r->res.classid == classid) { ++ if (cl) ++ __tcf_bind_filter(q, &r->res, base); ++ else ++ __tcf_unbind_filter(q, &r->res); ++ } ++} ++ ++static struct tcf_proto_ops cls_tcindex_ops __read_mostly = { ++ .kind = "tcindex", ++ .classify = tcindex_classify, ++ .init = tcindex_init, ++ .destroy = tcindex_destroy, ++ .get = tcindex_get, ++ .change = tcindex_change, ++ .delete = tcindex_delete, ++ .walk = tcindex_walk, ++ .dump = tcindex_dump, ++ .bind_class = tcindex_bind_class, ++ .owner = THIS_MODULE, ++}; ++ ++static int __init init_tcindex(void) ++{ ++ return register_tcf_proto_ops(&cls_tcindex_ops); ++} ++ ++static void __exit exit_tcindex(void) ++{ ++ unregister_tcf_proto_ops(&cls_tcindex_ops); ++} ++ ++module_init(init_tcindex) ++module_exit(exit_tcindex) ++MODULE_LICENSE("GPL"); +-- +2.39.2 + diff --git a/packages/linux-kernel/patches/vyos-drivers-realtek-r8152/0001-Fixed-compatibility-with-kernel-5.4.254.patch b/packages/linux-kernel/patches/vyos-drivers-realtek-r8152/0001-Fixed-compatibility-with-kernel-5.4.254.patch new file mode 100644 index 00000000..d4e9321b --- /dev/null +++ b/packages/linux-kernel/patches/vyos-drivers-realtek-r8152/0001-Fixed-compatibility-with-kernel-5.4.254.patch @@ -0,0 +1,27 @@ +From 65e00ae524f82cffb57abf3fa3f8dbac8a2bda7a Mon Sep 17 00:00:00 2001 +From: Taras Pudiak <taras@vyos.io> +Date: Wed, 30 Aug 2023 14:59:38 +0300 +Subject: [PATCH] Fixed compatibility with kernel 5.4.254 + +--- + compatibility.h | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/compatibility.h b/compatibility.h +index d1e044d..9eee6a9 100644 +--- a/compatibility.h ++++ b/compatibility.h +@@ -612,10 +612,6 @@ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,8,0) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,9,0) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,12,0) */ +- static inline void eth_hw_addr_set(struct net_device *dev, const u8 *addr) +- { +- memcpy(dev->dev_addr, addr, 6); +- } + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) */ + #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(5,19,0) */ + +-- +2.34.1 + diff --git a/packages/linux-kernel/x86_64_vyos_defconfig b/packages/linux-kernel/x86_64_vyos_defconfig index a6c72ed4..6e3ed66a 100644 --- a/packages/linux-kernel/x86_64_vyos_defconfig +++ b/packages/linux-kernel/x86_64_vyos_defconfig @@ -2642,7 +2642,11 @@ CONFIG_LIBIPW=m CONFIG_IWLEGACY=m CONFIG_IWL4965=m CONFIG_IWL3945=m - +# stmicro driver +CONFIG_NET_VENDOR_STMICRO=y +CONFIG_STMMAC_ETH=m +CONFIG_DWMAC_INTEL=m +CONFIG_STMMAC_PCI=m # # iwl3945 / iwl4965 Debugging Options # diff --git a/packages/ocserv/Jenkinsfile b/packages/ocserv/Jenkinsfile index 235e5b07..686cde80 100644 --- a/packages/ocserv/Jenkinsfile +++ b/packages/ocserv/Jenkinsfile @@ -22,9 +22,9 @@ def pkgList = [ ['name': 'ocserv', - 'scmCommit': 'debian/0.12.2-3', + 'scmCommit': 'debian/1.1.6-3', 'scmUrl': 'https://salsa.debian.org/debian/ocserv/', - 'buildCmd': 'dpkg-buildpackage -uc -us -tc -b'], + 'buildCmd': 'dpkg-buildpackage -uc -us -tc -b -d'], ] // Start package build using library function from https://github.com/vyos/vyos-build |