From b81e0f2b58be37628b2e12f8dffdd63c84573e75 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 16 May 2025 10:00:00 +0200 Subject: [PATCH 01/16] net: airoha: Add FLOW_CLS_STATS callback support Introduce per-flow stats accounting to the flowtable hw offload in the airoha_eth driver. Flow stats are split in the PPE and NPU modules: - PPE: accounts for high 32bit of per-flow stats - NPU: accounts for low 32bit of per-flow stats FLOW_CLS_STATS can be enabled or disabled at compile time. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250516-airoha-en7581-flowstats-v2-2-06d5fbf28984@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/Kconfig | 7 + drivers/net/ethernet/airoha/airoha_eth.h | 33 +++ drivers/net/ethernet/airoha/airoha_npu.c | 52 +++- drivers/net/ethernet/airoha/airoha_npu.h | 4 +- drivers/net/ethernet/airoha/airoha_ppe.c | 269 ++++++++++++++++-- .../net/ethernet/airoha/airoha_ppe_debugfs.c | 9 +- 6 files changed, 354 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/airoha/Kconfig b/drivers/net/ethernet/airoha/Kconfig index 1a4cf6a259f6..ad3ce501e7a5 100644 --- a/drivers/net/ethernet/airoha/Kconfig +++ b/drivers/net/ethernet/airoha/Kconfig @@ -24,4 +24,11 @@ config NET_AIROHA This driver supports the gigabit ethernet MACs in the Airoha SoC family. +config NET_AIROHA_FLOW_STATS + default y + bool "Airoha flow stats" + depends on NET_AIROHA && NET_AIROHA_NPU + help + Enable Aiorha flowtable statistic counters. + endif #NET_VENDOR_AIROHA diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 53f39083a8b0..531a3c49c156 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -50,6 +50,14 @@ #define PPE_NUM 2 #define PPE1_SRAM_NUM_ENTRIES (8 * 1024) #define PPE_SRAM_NUM_ENTRIES (2 * PPE1_SRAM_NUM_ENTRIES) +#ifdef CONFIG_NET_AIROHA_FLOW_STATS +#define PPE1_STATS_NUM_ENTRIES (4 * 1024) +#else +#define PPE1_STATS_NUM_ENTRIES 0 +#endif /* CONFIG_NET_AIROHA_FLOW_STATS */ +#define PPE_STATS_NUM_ENTRIES (2 * PPE1_STATS_NUM_ENTRIES) +#define PPE1_SRAM_NUM_DATA_ENTRIES (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES) +#define PPE_SRAM_NUM_DATA_ENTRIES (2 * PPE1_SRAM_NUM_DATA_ENTRIES) #define PPE_DRAM_NUM_ENTRIES (16 * 1024) #define PPE_NUM_ENTRIES (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES) #define PPE_HASH_MASK (PPE_NUM_ENTRIES - 1) @@ -261,6 +269,8 @@ struct airoha_foe_mac_info { u16 pppoe_id; u16 src_mac_lo; + + u32 meter; }; #define AIROHA_FOE_IB1_UNBIND_PREBIND BIT(24) @@ -296,6 +306,11 @@ struct airoha_foe_mac_info { #define AIROHA_FOE_TUNNEL BIT(6) #define AIROHA_FOE_TUNNEL_ID GENMASK(5, 0) +#define AIROHA_FOE_TUNNEL_MTU GENMASK(31, 16) +#define AIROHA_FOE_ACNT_GRP3 GENMASK(15, 9) +#define AIROHA_FOE_METER_GRP3 GENMASK(8, 5) +#define AIROHA_FOE_METER_GRP2 GENMASK(4, 0) + struct airoha_foe_bridge { u32 dest_mac_hi; @@ -379,6 +394,8 @@ struct airoha_foe_ipv6 { u32 ib2; struct airoha_foe_mac_info_common l2; + + u32 meter; }; struct airoha_foe_entry { @@ -397,6 +414,16 @@ struct airoha_foe_entry { }; }; +struct airoha_foe_stats { + u32 bytes; + u32 packets; +}; + +struct airoha_foe_stats64 { + u64 bytes; + u64 packets; +}; + struct airoha_flow_data { struct ethhdr eth; @@ -447,6 +474,7 @@ struct airoha_flow_table_entry { struct hlist_node l2_subflow_node; /* PPE L2 subflow entry */ u32 hash; + struct airoha_foe_stats64 stats; enum airoha_flow_entry_type type; struct rhash_head node; @@ -523,6 +551,9 @@ struct airoha_ppe { struct hlist_head *foe_flow; u16 foe_check_time[PPE_NUM_ENTRIES]; + struct airoha_foe_stats *foe_stats; + dma_addr_t foe_stats_dma; + struct dentry *debugfs_dir; }; @@ -582,6 +613,8 @@ int airoha_ppe_init(struct airoha_eth *eth); void airoha_ppe_deinit(struct airoha_eth *eth); struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash); +void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, + struct airoha_foe_stats64 *stats); #ifdef CONFIG_DEBUG_FS int airoha_ppe_debugfs_init(struct airoha_ppe *ppe); diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c index 51c6fbd7b7b7..0e5b8c21b9aa 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.c +++ b/drivers/net/ethernet/airoha/airoha_npu.c @@ -12,6 +12,7 @@ #include #include +#include "airoha_eth.h" #include "airoha_npu.h" #define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin" @@ -72,6 +73,7 @@ enum { PPE_FUNC_SET_WAIT_HWNAT_INIT, PPE_FUNC_SET_WAIT_HWNAT_DEINIT, PPE_FUNC_SET_WAIT_API, + PPE_FUNC_SET_WAIT_FLOW_STATS_SETUP, }; enum { @@ -115,6 +117,10 @@ struct ppe_mbox_data { u32 size; u32 data; } set_info; + struct { + u32 npu_stats_addr; + u32 foe_stats_addr; + } stats_info; }; }; @@ -351,7 +357,40 @@ out: return err; } -struct airoha_npu *airoha_npu_get(struct device *dev) +static int airoha_npu_stats_setup(struct airoha_npu *npu, + dma_addr_t foe_stats_addr) +{ + int err, size = PPE_STATS_NUM_ENTRIES * sizeof(*npu->stats); + struct ppe_mbox_data *ppe_data; + + if (!size) /* flow stats are disabled */ + return 0; + + ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC); + if (!ppe_data) + return -ENOMEM; + + ppe_data->func_type = NPU_OP_SET; + ppe_data->func_id = PPE_FUNC_SET_WAIT_FLOW_STATS_SETUP; + ppe_data->stats_info.foe_stats_addr = foe_stats_addr; + + err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, ppe_data, + sizeof(*ppe_data)); + if (err) + goto out; + + npu->stats = devm_ioremap(npu->dev, + ppe_data->stats_info.npu_stats_addr, + size); + if (!npu->stats) + err = -ENOMEM; +out: + kfree(ppe_data); + + return err; +} + +struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr) { struct platform_device *pdev; struct device_node *np; @@ -389,6 +428,17 @@ struct airoha_npu *airoha_npu_get(struct device *dev) goto error_module_put; } + if (stats_addr) { + int err; + + err = airoha_npu_stats_setup(npu, *stats_addr); + if (err) { + dev_err(dev, "failed to allocate npu stats buffer\n"); + npu = ERR_PTR(err); + goto error_module_put; + } + } + return npu; error_module_put: diff --git a/drivers/net/ethernet/airoha/airoha_npu.h b/drivers/net/ethernet/airoha/airoha_npu.h index a2b8ae4d9473..98ec3be74ce4 100644 --- a/drivers/net/ethernet/airoha/airoha_npu.h +++ b/drivers/net/ethernet/airoha/airoha_npu.h @@ -17,6 +17,8 @@ struct airoha_npu { struct work_struct wdt_work; } cores[NPU_NUM_CORES]; + struct airoha_foe_stats __iomem *stats; + struct { int (*ppe_init)(struct airoha_npu *npu); int (*ppe_deinit)(struct airoha_npu *npu); @@ -30,5 +32,5 @@ struct airoha_npu { } ops; }; -struct airoha_npu *airoha_npu_get(struct device *dev); +struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr); void airoha_npu_put(struct airoha_npu *npu); diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 6e9787c2843b..70598ba9f5ad 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -102,7 +102,7 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) if (airoha_ppe2_is_enabled(eth)) { sram_num_entries = - PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_ENTRIES); + PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_DATA_ENTRIES); airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), PPE_SRAM_TB_NUM_ENTRY_MASK | PPE_DRAM_TB_NUM_ENTRY_MASK, @@ -119,7 +119,7 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) dram_num_entries)); } else { sram_num_entries = - PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_ENTRIES); + PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_DATA_ENTRIES); airoha_fe_rmw(eth, REG_PPE_TB_CFG(0), PPE_SRAM_TB_NUM_ENTRY_MASK | PPE_DRAM_TB_NUM_ENTRY_MASK, @@ -417,6 +417,77 @@ static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe) return hash; } +static u32 airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, u32 hash) +{ + if (!airoha_ppe2_is_enabled(ppe->eth)) + return hash; + + return hash >= PPE_STATS_NUM_ENTRIES ? hash - PPE1_STATS_NUM_ENTRIES + : hash; +} + +static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe, + struct airoha_npu *npu, + int index) +{ + memset_io(&npu->stats[index], 0, sizeof(*npu->stats)); + memset(&ppe->foe_stats[index], 0, sizeof(*ppe->foe_stats)); +} + +static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe, + struct airoha_npu *npu) +{ + int i; + + for (i = 0; i < PPE_STATS_NUM_ENTRIES; i++) + airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i); +} + +static void airoha_ppe_foe_flow_stats_update(struct airoha_ppe *ppe, + struct airoha_npu *npu, + struct airoha_foe_entry *hwe, + u32 hash) +{ + int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1); + u32 index, pse_port, val, *data, *ib2, *meter; + u8 nbq; + + index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); + if (index >= PPE_STATS_NUM_ENTRIES) + return; + + if (type == PPE_PKT_TYPE_BRIDGE) { + data = &hwe->bridge.data; + ib2 = &hwe->bridge.ib2; + meter = &hwe->bridge.l2.meter; + } else if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) { + data = &hwe->ipv6.data; + ib2 = &hwe->ipv6.ib2; + meter = &hwe->ipv6.meter; + } else { + data = &hwe->ipv4.data; + ib2 = &hwe->ipv4.ib2; + meter = &hwe->ipv4.l2.meter; + } + + airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, index); + + val = FIELD_GET(AIROHA_FOE_CHANNEL | AIROHA_FOE_QID, *data); + *data = (*data & ~AIROHA_FOE_ACTDP) | + FIELD_PREP(AIROHA_FOE_ACTDP, val); + + val = *ib2 & (AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT | + AIROHA_FOE_IB2_PSE_QOS | AIROHA_FOE_IB2_FAST_PATH); + *meter |= FIELD_PREP(AIROHA_FOE_TUNNEL_MTU, val); + + pse_port = FIELD_GET(AIROHA_FOE_IB2_PSE_PORT, *ib2); + nbq = pse_port == 1 ? 6 : 5; + *ib2 &= ~(AIROHA_FOE_IB2_NBQ | AIROHA_FOE_IB2_PSE_PORT | + AIROHA_FOE_IB2_PSE_QOS); + *ib2 |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, 6) | + FIELD_PREP(AIROHA_FOE_IB2_NBQ, nbq); +} + struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash) { @@ -470,6 +541,8 @@ static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe); u32 ts = airoha_ppe_get_timestamp(ppe); struct airoha_eth *eth = ppe->eth; + struct airoha_npu *npu; + int err = 0; memcpy(&hwe->d, &e->d, sizeof(*hwe) - sizeof(hwe->ib1)); wmb(); @@ -478,25 +551,28 @@ static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe, e->ib1 |= FIELD_PREP(AIROHA_FOE_IB1_BIND_TIMESTAMP, ts); hwe->ib1 = e->ib1; + rcu_read_lock(); + + npu = rcu_dereference(eth->npu); + if (!npu) { + err = -ENODEV; + goto unlock; + } + + airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash); + if (hash < PPE_SRAM_NUM_ENTRIES) { dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe); bool ppe2 = airoha_ppe2_is_enabled(eth) && hash >= PPE1_SRAM_NUM_ENTRIES; - struct airoha_npu *npu; - int err = -ENODEV; - rcu_read_lock(); - npu = rcu_dereference(eth->npu); - if (npu) - err = npu->ops.ppe_foe_commit_entry(npu, addr, - sizeof(*hwe), hash, - ppe2); - rcu_read_unlock(); - - return err; + err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe), + hash, ppe2); } +unlock: + rcu_read_unlock(); - return 0; + return err; } static void airoha_ppe_foe_remove_flow(struct airoha_ppe *ppe, @@ -582,6 +658,7 @@ airoha_ppe_foe_commit_subflow_entry(struct airoha_ppe *ppe, l2->common.etype = ETH_P_IPV6; hwe.bridge.ib2 = e->data.bridge.ib2; + hwe.bridge.data = e->data.bridge.data; airoha_ppe_foe_commit_entry(ppe, &hwe, hash); return 0; @@ -681,6 +758,98 @@ static int airoha_ppe_foe_flow_commit_entry(struct airoha_ppe *ppe, return 0; } +static int airoha_ppe_get_entry_idle_time(struct airoha_ppe *ppe, u32 ib1) +{ + u32 state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); + u32 ts, ts_mask, now = airoha_ppe_get_timestamp(ppe); + int idle; + + if (state == AIROHA_FOE_STATE_BIND) { + ts = FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, ib1); + ts_mask = AIROHA_FOE_IB1_BIND_TIMESTAMP; + } else { + ts = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, ib1); + now = FIELD_GET(AIROHA_FOE_IB1_UNBIND_TIMESTAMP, now); + ts_mask = AIROHA_FOE_IB1_UNBIND_TIMESTAMP; + } + idle = now - ts; + + return idle < 0 ? idle + ts_mask + 1 : idle; +} + +static void +airoha_ppe_foe_flow_l2_entry_update(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e) +{ + int min_idle = airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); + struct airoha_flow_table_entry *iter; + struct hlist_node *n; + + lockdep_assert_held(&ppe_lock); + + hlist_for_each_entry_safe(iter, n, &e->l2_flows, l2_subflow_node) { + struct airoha_foe_entry *hwe; + u32 ib1, state; + int idle; + + hwe = airoha_ppe_foe_get_entry(ppe, iter->hash); + ib1 = READ_ONCE(hwe->ib1); + + state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, ib1); + if (state != AIROHA_FOE_STATE_BIND) { + iter->hash = 0xffff; + airoha_ppe_foe_remove_flow(ppe, iter); + continue; + } + + idle = airoha_ppe_get_entry_idle_time(ppe, ib1); + if (idle >= min_idle) + continue; + + min_idle = idle; + e->data.ib1 &= ~AIROHA_FOE_IB1_BIND_TIMESTAMP; + e->data.ib1 |= ib1 & AIROHA_FOE_IB1_BIND_TIMESTAMP; + } +} + +static void airoha_ppe_foe_flow_entry_update(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e) +{ + struct airoha_foe_entry *hwe_p, hwe = {}; + + spin_lock_bh(&ppe_lock); + + if (e->type == FLOW_TYPE_L2) { + airoha_ppe_foe_flow_l2_entry_update(ppe, e); + goto unlock; + } + + if (e->hash == 0xffff) + goto unlock; + + hwe_p = airoha_ppe_foe_get_entry(ppe, e->hash); + if (!hwe_p) + goto unlock; + + memcpy(&hwe, hwe_p, sizeof(*hwe_p)); + if (!airoha_ppe_foe_compare_entry(e, &hwe)) { + e->hash = 0xffff; + goto unlock; + } + + e->data.ib1 = hwe.ib1; +unlock: + spin_unlock_bh(&ppe_lock); +} + +static int airoha_ppe_entry_idle_time(struct airoha_ppe *ppe, + struct airoha_flow_table_entry *e) +{ + airoha_ppe_foe_flow_entry_update(ppe, e); + + return airoha_ppe_get_entry_idle_time(ppe, e->data.ib1); +} + static int airoha_ppe_flow_offload_replace(struct airoha_gdm_port *port, struct flow_cls_offload *f) { @@ -896,6 +1065,60 @@ static int airoha_ppe_flow_offload_destroy(struct airoha_gdm_port *port, return 0; } +void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash, + struct airoha_foe_stats64 *stats) +{ + u32 index = airoha_ppe_foe_get_flow_stats_index(ppe, hash); + struct airoha_eth *eth = ppe->eth; + struct airoha_npu *npu; + + if (index >= PPE_STATS_NUM_ENTRIES) + return; + + rcu_read_lock(); + + npu = rcu_dereference(eth->npu); + if (npu) { + u64 packets = ppe->foe_stats[index].packets; + u64 bytes = ppe->foe_stats[index].bytes; + struct airoha_foe_stats npu_stats; + + memcpy_fromio(&npu_stats, &npu->stats[index], + sizeof(*npu->stats)); + stats->packets = packets << 32 | npu_stats.packets; + stats->bytes = bytes << 32 | npu_stats.bytes; + } + + rcu_read_unlock(); +} + +static int airoha_ppe_flow_offload_stats(struct airoha_gdm_port *port, + struct flow_cls_offload *f) +{ + struct airoha_eth *eth = port->qdma->eth; + struct airoha_flow_table_entry *e; + u32 idle; + + e = rhashtable_lookup(ð->flow_table, &f->cookie, + airoha_flow_table_params); + if (!e) + return -ENOENT; + + idle = airoha_ppe_entry_idle_time(eth->ppe, e); + f->stats.lastused = jiffies - idle * HZ; + + if (e->hash != 0xffff) { + struct airoha_foe_stats64 stats = {}; + + airoha_ppe_foe_entry_get_stats(eth->ppe, e->hash, &stats); + f->stats.pkts += (stats.packets - e->stats.packets); + f->stats.bytes += (stats.bytes - e->stats.bytes); + e->stats = stats; + } + + return 0; +} + static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, struct flow_cls_offload *f) { @@ -904,6 +1127,8 @@ static int airoha_ppe_flow_offload_cmd(struct airoha_gdm_port *port, return airoha_ppe_flow_offload_replace(port, f); case FLOW_CLS_DESTROY: return airoha_ppe_flow_offload_destroy(port, f); + case FLOW_CLS_STATS: + return airoha_ppe_flow_offload_stats(port, f); default: break; } @@ -929,11 +1154,12 @@ static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe, static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth) { - struct airoha_npu *npu = airoha_npu_get(eth->dev); + struct airoha_npu *npu = airoha_npu_get(eth->dev, + ð->ppe->foe_stats_dma); if (IS_ERR(npu)) { request_module("airoha-npu"); - npu = airoha_npu_get(eth->dev); + npu = airoha_npu_get(eth->dev, ð->ppe->foe_stats_dma); } return npu; @@ -956,6 +1182,8 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth) if (err) goto error_npu_put; + airoha_ppe_foe_flow_stats_reset(eth->ppe, npu); + rcu_assign_pointer(eth->npu, npu); synchronize_rcu(); @@ -1027,6 +1255,15 @@ int airoha_ppe_init(struct airoha_eth *eth) if (!ppe->foe_flow) return -ENOMEM; + foe_size = PPE_STATS_NUM_ENTRIES * sizeof(*ppe->foe_stats); + if (foe_size) { + ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size, + &ppe->foe_stats_dma, + GFP_KERNEL); + if (!ppe->foe_stats) + return -ENOMEM; + } + err = rhashtable_init(ð->flow_table, &airoha_flow_table_params); if (err) return err; diff --git a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c index 3cdc6fd53fc7..05a756233f6a 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c +++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c @@ -61,6 +61,7 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private, u16 *src_port = NULL, *dest_port = NULL; struct airoha_foe_mac_info_common *l2; unsigned char h_source[ETH_ALEN] = {}; + struct airoha_foe_stats64 stats = {}; unsigned char h_dest[ETH_ALEN]; struct airoha_foe_entry *hwe; u32 type, state, ib2, data; @@ -144,14 +145,18 @@ static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private, cpu_to_be16(hwe->ipv4.l2.src_mac_lo); } + airoha_ppe_foe_entry_get_stats(ppe, i, &stats); + *((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi); *((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo); *((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi); seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x" - " vlan=%d,%d ib1=%08x ib2=%08x\n", + " vlan=%d,%d ib1=%08x ib2=%08x" + " packets=%llu bytes=%llu\n", h_source, h_dest, l2->etype, data, - l2->vlan1, l2->vlan2, hwe->ib1, ib2); + l2->vlan1, l2->vlan2, hwe->ib1, ib2, + stats.packets, stats.bytes); } return 0; -- 2.51.0 From a98326c151ea3d92e9496858cc2dacccd0870941 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Fri, 16 May 2025 10:00:01 +0200 Subject: [PATCH 02/16] net: airoha: ppe: Disable packet keepalive Since netfilter flowtable entries are now refreshed by flow-stats polling, we can disable hw packet keepalive used to periodically send packets belonging to offloaded flows to the kernel in order to refresh flowtable entries. Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Link: https://patch.msgid.link/20250516-airoha-en7581-flowstats-v2-3-06d5fbf28984@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_ppe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index 70598ba9f5ad..2d273937f19c 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -84,6 +84,7 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) airoha_fe_rmw(eth, REG_PPE_TB_CFG(i), PPE_TB_CFG_SEARCH_MISS_MASK | + PPE_TB_CFG_KEEPALIVE_MASK | PPE_TB_ENTRY_SIZE_MASK, FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) | FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0)); -- 2.51.0 From 8b8762eeec59b959fbca60afffe21265bce67168 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:05 -0700 Subject: [PATCH 03/16] tools: ynl-gen: add makefile deps for neigh Kory is reporting build issues after recent additions to YNL if the system headers are old. Link: https://lore.kernel.org/20250519164949.597d6e92@kmaincent-XPS-13-7390 Reported-by: Kory Maincent Fixes: 0939a418b3b0 ("tools: ynl: submsg: reverse parse / error reporting") Tested-by: Kory Maincent Link: https://patch.msgid.link/20250520161916.413298-2-kuba@kernel.org Signed-off-by: Jakub Kicinski --- include/uapi/linux/neighbour.h | 4 ++-- tools/net/ynl/Makefile.deps | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/neighbour.h b/include/uapi/linux/neighbour.h index 5e67a7eaf4a7..b851c36ad25d 100644 --- a/include/uapi/linux/neighbour.h +++ b/include/uapi/linux/neighbour.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef __LINUX_NEIGHBOUR_H -#define __LINUX_NEIGHBOUR_H +#ifndef _UAPI__LINUX_NEIGHBOUR_H +#define _UAPI__LINUX_NEIGHBOUR_H #include #include diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index e5a5cb1b2cff..8c378356fc87 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -35,7 +35,8 @@ CFLAGS_rt-addr:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ $(call get_hdr_inc,__LINUX_IF_ADDR_H,if_addr.h) CFLAGS_rt-link:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ $(call get_hdr_inc,_LINUX_IF_LINK_H,if_link.h) -CFLAGS_rt-neigh:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) +CFLAGS_rt-neigh:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ + $(call get_hdr_inc,__LINUX_NEIGHBOUR_H,neighbour.h) CFLAGS_rt-route:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) CFLAGS_rt-rule:=$(call get_hdr_inc,__LINUX_FIB_RULES_H,fib_rules.h) CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h) -- 2.51.0 From e9033a846eb9a8ca21dee880b9ac2f5988ceb5f0 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:06 -0700 Subject: [PATCH 04/16] netlink: specs: tc: remove duplicate nests tc-act-stats-attrs and tca-stats-attrs are almost identical. The only difference is that the latter has sub-message decoding for app, rather than declaring it as a binary attr. tc-act-police-attrs and tc-police-attrs are identical but for the TODO annotations. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-3-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 78 ++--------------------------- 1 file changed, 4 insertions(+), 74 deletions(-) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index 953aa837958b..c7e6a734cd12 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -1452,7 +1452,7 @@ attribute-sets: - name: stats type: nest - nested-attributes: tc-act-stats-attrs + nested-attributes: tca-stats-attrs - name: pad type: pad @@ -1471,38 +1471,6 @@ attribute-sets: - name: in-hw-count type: u32 - - - name: tc-act-stats-attrs - attributes: - - - name: basic - type: binary - struct: gnet-stats-basic - - - name: rate-est - type: binary - struct: gnet-stats-rate-est - - - name: queue - type: binary - struct: gnet-stats-queue - - - name: app - type: binary - - - name: rate-est64 - type: binary - struct: gnet-stats-rate-est64 - - - name: pad - type: pad - - - name: basic-hw - type: binary - struct: gnet-stats-basic - - - name: pkt64 - type: u64 - name: tc-act-bpf-attrs attributes: @@ -1797,44 +1765,6 @@ attribute-sets: - name: key-ex type: binary - - - name: tc-act-police-attrs - attributes: - - - name: tbf - type: binary - struct: tc-police - - - name: rate - type: binary # TODO - - - name: peakrate - type: binary # TODO - - - name: avrate - type: u32 - - - name: result - type: u32 - - - name: tm - type: binary - struct: tcf-t - - - name: pad - type: pad - - - name: rate64 - type: u64 - - - name: peakrate64 - type: u64 - - - name: pktrate64 - type: u64 - - - name: pktburst64 - type: u64 - name: tc-act-simple-attrs attributes: @@ -3327,10 +3257,10 @@ attribute-sets: struct: tc-police - name: rate - type: binary + type: binary # TODO - name: peakrate - type: binary + type: binary # TODO - name: avrate type: u32 @@ -3817,7 +3747,7 @@ sub-messages: attribute-set: tc-act-pedit-attrs - value: police - attribute-set: tc-act-police-attrs + attribute-set: tc-police-attrs - value: sample attribute-set: tc-act-sample-attrs -- 2.51.0 From eb1f803f9851e1bf40924a06c1db349540290bac Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:07 -0700 Subject: [PATCH 05/16] netlink: specs: tc: use tc-gact instead of tc-gen as struct name There is a define in the uAPI header called tc_gen which expands to the "generic" TC action fields. This helps other actions include the base fields without having to deal with nested structs. A couple of actions (sample, gact) do not define extra fields, so the spec used a common tc-gen struct for both of them. Unfortunately this struct does not exist in C. Let's use gact's (generic act's) struct for basic actions. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-4-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index c7e6a734cd12..697fdd1219d5 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -1186,7 +1186,7 @@ definitions: name: firstuse type: u64 - - name: tc-gen + name: tc-gact type: struct members: - @@ -3457,7 +3457,7 @@ attribute-sets: - name: parms type: binary - struct: tc-gen + struct: tc-gact - name: rate type: u32 @@ -3480,7 +3480,7 @@ attribute-sets: - name: parms type: binary - struct: tc-gen + struct: tc-gact - name: prob type: binary -- 2.51.0 From f9aec8025ab5fc440fcc56f31298750d9b039acc Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:08 -0700 Subject: [PATCH 06/16] netlink: specs: tc: add C naming info Add naming info needed by C code gen. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-5-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 95 +++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index 697fdd1219d5..8d5e5cb439e4 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -2,6 +2,7 @@ name: tc protocol: netlink-raw +uapi-header: linux/pkt_cls.h protonum: 0 doc: @@ -12,6 +13,7 @@ definitions: - name: tcmsg type: struct + header: linux/rtnetlink.h members: - name: family @@ -34,6 +36,7 @@ definitions: type: u32 - name: tc-cls-flags + enum-name: type: flags entries: - skip-hw @@ -43,6 +46,8 @@ definitions: - verbose - name: tc-flower-key-ctrl-flags + name-prefix: tca-flower-key-flags- + enum-name: type: flags entries: - frag @@ -630,6 +635,7 @@ definitions: - name: tc-ratespec type: struct + header: linux/pkt_sched.h members: - name: cell-log @@ -1378,6 +1384,7 @@ definitions: attribute-sets: - name: tc-attrs + name-prefix: tca- attributes: - name: kind @@ -1437,6 +1444,7 @@ attribute-sets: type: string - name: tc-act-attrs + name-prefix: tca-act- attributes: - name: kind @@ -1473,6 +1481,8 @@ attribute-sets: type: u32 - name: tc-act-bpf-attrs + name-prefix: tca-act-bpf- + header: linux/tc_act/tc_bpf.h attributes: - name: tm @@ -1504,6 +1514,8 @@ attribute-sets: type: binary - name: tc-act-connmark-attrs + name-prefix: tca-connmark- + header: linux/tc_act/tc_connmark.h attributes: - name: parms @@ -1517,6 +1529,8 @@ attribute-sets: type: pad - name: tc-act-csum-attrs + name-prefix: tca-csum- + header: linux/tc_act/tc_csum.h attributes: - name: parms @@ -1530,6 +1544,8 @@ attribute-sets: type: pad - name: tc-act-ct-attrs + name-prefix: tca-ct- + header: linux/tc_act/tc_ct.h attributes: - name: parms @@ -1592,6 +1608,8 @@ attribute-sets: type: u8 - name: tc-act-ctinfo-attrs + name-prefix: tca-ctinfo- + header: linux/tc_act/tc_ctinfo.h attributes: - name: pad @@ -1626,6 +1644,8 @@ attribute-sets: type: u64 - name: tc-act-gate-attrs + name-prefix: tca-gate- + header: linux/tc_act/tc_gate.h attributes: - name: tm @@ -1660,6 +1680,8 @@ attribute-sets: type: s32 - name: tc-act-ife-attrs + name-prefix: tca-ife- + header: linux/tc_act/tc_ife.h attributes: - name: parms @@ -1685,6 +1707,8 @@ attribute-sets: type: pad - name: tc-act-mirred-attrs + name-prefix: tca-mirred- + header: linux/tc_act/tc_mirred.h attributes: - name: tm @@ -1701,6 +1725,8 @@ attribute-sets: type: binary - name: tc-act-mpls-attrs + name-prefix: tca-mpls- + header: linux/tc_act/tc_mpls.h attributes: - name: tm @@ -1731,6 +1757,8 @@ attribute-sets: type: u8 - name: tc-act-nat-attrs + name-prefix: tca-nat- + header: linux/tc_act/tc_nat.h attributes: - name: parms @@ -1744,6 +1772,8 @@ attribute-sets: type: pad - name: tc-act-pedit-attrs + name-prefix: tca-pedit- + header: linux/tc_act/tc_pedit.h attributes: - name: tm @@ -1767,6 +1797,8 @@ attribute-sets: type: binary - name: tc-act-simple-attrs + name-prefix: tca-def- + header: linux/tc_act/tc_defact.h attributes: - name: tm @@ -1783,6 +1815,8 @@ attribute-sets: type: pad - name: tc-act-skbedit-attrs + name-prefix: tca-skbedit- + header: linux/tc_act/tc_skbedit.h attributes: - name: tm @@ -1817,6 +1851,8 @@ attribute-sets: type: u16 - name: tc-act-skbmod-attrs + name-prefix: tca-skbmod- + header: linux/tc_act/tc_skbmod.h attributes: - name: tm @@ -1839,6 +1875,8 @@ attribute-sets: type: pad - name: tc-act-tunnel-key-attrs + name-prefix: tca-tunnel-key- + header: linux/tc_act/tc_tunnel_key.h attributes: - name: tm @@ -1889,6 +1927,8 @@ attribute-sets: type: flag - name: tc-act-vlan-attrs + name-prefix: tca-vlan- + header: linux/tc_act/tc_vlan.h attributes: - name: tm @@ -1918,6 +1958,7 @@ attribute-sets: type: binary - name: tc-basic-attrs + name-prefix: tca-basic- attributes: - name: classid @@ -1944,6 +1985,7 @@ attribute-sets: type: pad - name: tc-bpf-attrs + name-prefix: tca-bpf- attributes: - name: act @@ -1983,6 +2025,7 @@ attribute-sets: type: u32 - name: tc-cake-attrs + name-prefix: tca-cake- attributes: - name: pad @@ -2040,6 +2083,7 @@ attribute-sets: type: u32 - name: tc-cake-stats-attrs + name-prefix: tca-cake-stats- attributes: - name: pad @@ -2093,6 +2137,7 @@ attribute-sets: type: s32 - name: tc-cake-tin-stats-attrs + name-prefix: tca-cake-tin-stats- attributes: - name: pad @@ -2171,6 +2216,7 @@ attribute-sets: type: u32 - name: tc-cbs-attrs + name-prefix: tca-cbs- attributes: - name: parms @@ -2178,6 +2224,7 @@ attribute-sets: struct: tc-cbs-qopt - name: tc-cgroup-attrs + name-prefix: tca-cgroup- attributes: - name: act @@ -2193,6 +2240,7 @@ attribute-sets: type: binary - name: tc-choke-attrs + name-prefix: tca-choke- attributes: - name: parms @@ -2209,6 +2257,7 @@ attribute-sets: type: u32 - name: tc-codel-attrs + name-prefix: tca-codel- attributes: - name: target @@ -2227,12 +2276,15 @@ attribute-sets: type: u32 - name: tc-drr-attrs + name-prefix: tca-drr- attributes: - name: quantum type: u32 - name: tc-ematch-attrs + name-prefix: tca-ematch- + attr-max-name: tca-ematch-tree-max attributes: - name: tree-hdr @@ -2243,6 +2295,7 @@ attribute-sets: type: binary - name: tc-flow-attrs + name-prefix: tca-flow- attributes: - name: keys @@ -2283,6 +2336,7 @@ attribute-sets: type: u32 - name: tc-flower-attrs + name-prefix: tca-flower- attributes: - name: classid @@ -2709,6 +2763,7 @@ attribute-sets: enum-as-flags: true - name: tc-flower-key-enc-opts-attrs + name-prefix: tca-flower-key-enc-opts- attributes: - name: geneve @@ -2728,6 +2783,7 @@ attribute-sets: nested-attributes: tc-flower-key-enc-opt-gtp-attrs - name: tc-flower-key-enc-opt-geneve-attrs + name-prefix: tca-flower-key-enc-opt-geneve- attributes: - name: class @@ -2740,12 +2796,14 @@ attribute-sets: type: binary - name: tc-flower-key-enc-opt-vxlan-attrs + name-prefix: tca-flower-key-enc-opt-vxlan- attributes: - name: gbp type: u32 - name: tc-flower-key-enc-opt-erspan-attrs + name-prefix: tca-flower-key-enc-opt-erspan- attributes: - name: ver @@ -2761,6 +2819,7 @@ attribute-sets: type: u8 - name: tc-flower-key-enc-opt-gtp-attrs + name-prefix: tca-flower-key-enc-opt-gtp- attributes: - name: pdu-type @@ -2770,6 +2829,8 @@ attribute-sets: type: u8 - name: tc-flower-key-mpls-opt-attrs + name-prefix: tca-flower-key-mpls-opt- + attr-max-name: tca-flower-key-mpls-opt-lse-max attributes: - name: lse-depth @@ -2788,6 +2849,7 @@ attribute-sets: type: u32 - name: tc-flower-key-cfm-attrs + name-prefix: tca-flower-key-cfm- attributes: - name: md-level @@ -2797,6 +2859,7 @@ attribute-sets: type: u8 - name: tc-fw-attrs + name-prefix: tca-fw- attributes: - name: classid @@ -2818,6 +2881,7 @@ attribute-sets: type: u32 - name: tc-gred-attrs + name-prefix: tca-gred- attributes: - name: parms @@ -2843,6 +2907,7 @@ attribute-sets: nested-attributes: tca-gred-vq-list-attrs - name: tca-gred-vq-list-attrs + name-prefix: tca-gred-vq- attributes: - name: entry @@ -2851,6 +2916,7 @@ attribute-sets: multi-attr: true - name: tca-gred-vq-entry-attrs + name-prefix: tca-gred-vq- attributes: - name: pad @@ -2902,6 +2968,7 @@ attribute-sets: type: binary - name: tc-hhf-attrs + name-prefix: tca-hhf- attributes: - name: backlog-limit @@ -2926,6 +2993,7 @@ attribute-sets: type: u32 - name: tc-htb-attrs + name-prefix: tca-htb- attributes: - name: parms @@ -2958,6 +3026,7 @@ attribute-sets: type: flag - name: tc-matchall-attrs + name-prefix: tca-matchall- attributes: - name: classid @@ -2979,6 +3048,7 @@ attribute-sets: type: pad - name: tc-etf-attrs + name-prefix: tca-etf- attributes: - name: parms @@ -2986,6 +3056,7 @@ attribute-sets: struct: tc-etf-qopt - name: tc-ets-attrs + name-prefix: tca-ets- attributes: - name: nbands @@ -3011,6 +3082,7 @@ attribute-sets: multi-attr: true - name: tc-fq-attrs + name-prefix: tca-fq- attributes: - name: plimit @@ -3082,6 +3154,7 @@ attribute-sets: doc: Weights for each band - name: tc-fq-codel-attrs + name-prefix: tca-fq-codel- attributes: - name: target @@ -3118,6 +3191,7 @@ attribute-sets: type: u8 - name: tc-fq-pie-attrs + name-prefix: tca-fq-pie- attributes: - name: limit @@ -3157,6 +3231,7 @@ attribute-sets: type: u32 - name: tc-netem-attrs + name-prefix: tca-netem- attributes: - name: corr @@ -3210,6 +3285,7 @@ attribute-sets: type: u64 - name: tc-netem-loss-attrs + name-prefix: netem-loss- attributes: - name: gi @@ -3223,6 +3299,7 @@ attribute-sets: struct: tc-netem-gemodel - name: tc-pie-attrs + name-prefix: tca-pie- attributes: - name: target @@ -3250,6 +3327,7 @@ attribute-sets: type: u32 - name: tc-police-attrs + name-prefix: tca-police- attributes: - name: tbf @@ -3288,6 +3366,7 @@ attribute-sets: type: u64 - name: tc-qfq-attrs + name-prefix: tca-qfq- attributes: - name: weight @@ -3297,6 +3376,7 @@ attribute-sets: type: u32 - name: tc-red-attrs + name-prefix: tca-red- attributes: - name: parms @@ -3319,6 +3399,7 @@ attribute-sets: type: u32 - name: tc-route-attrs + name-prefix: tca-route4- attributes: - name: classid @@ -3343,6 +3424,7 @@ attribute-sets: nested-attributes: tc-act-attrs - name: tc-taprio-attrs + name-prefix: tca-taprio-attr- attributes: - name: priomap @@ -3386,6 +3468,7 @@ attribute-sets: nested-attributes: tc-taprio-tc-entry-attrs - name: tc-taprio-sched-entry-list + name-prefix: tca-taprio-sched- attributes: - name: entry @@ -3394,6 +3477,7 @@ attribute-sets: multi-attr: true - name: tc-taprio-sched-entry + name-prefix: tca-taprio-sched-entry- attributes: - name: index @@ -3409,6 +3493,7 @@ attribute-sets: type: u32 - name: tc-taprio-tc-entry-attrs + name-prefix: tca-taprio-tc-entry- attributes: - name: index @@ -3421,6 +3506,7 @@ attribute-sets: type: u32 - name: tc-tbf-attrs + name-prefix: tca-tbf- attributes: - name: parms @@ -3449,6 +3535,8 @@ attribute-sets: type: pad - name: tc-act-sample-attrs + name-prefix: tca-sample- + header: linux/tc_act/tc_sample.h attributes: - name: tm @@ -3472,6 +3560,8 @@ attribute-sets: type: pad - name: tc-act-gact-attrs + name-prefix: tca-gact- + header: linux/tc_act/tc_gact.h attributes: - name: tm @@ -3490,6 +3580,7 @@ attribute-sets: type: pad - name: tca-stab-attrs + name-prefix: tca-stab- attributes: - name: base @@ -3500,6 +3591,8 @@ attribute-sets: type: binary - name: tca-stats-attrs + name-prefix: tca-stats- + header: linux/gen_stats.h attributes: - name: basic @@ -3534,6 +3627,7 @@ attribute-sets: type: u64 - name: tc-u32-attrs + name-prefix: tca-u32- attributes: - name: classid @@ -3805,6 +3899,7 @@ sub-messages: operations: enum-model: directional + name-prefix: rtm- list: - name: newqdisc -- 2.51.0 From ba5a199b2401de3d5df1fba4d5dcd92908461a07 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:09 -0700 Subject: [PATCH 07/16] netlink: specs: tc: drop the family name prefix from attrs All attribute sets and messages are prefixed with tc-. The C codegen also adds the family name to all structs. We end up with names like struct tc_tc_act_attrs. Remove the tc- prefixes to shorten the names. This should not impact Python as the attr set names are never exposed to user, they are only used to refer to things internally, in the encoder / decoder. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-6-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 334 ++++++++++++++-------------- 1 file changed, 167 insertions(+), 167 deletions(-) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index 8d5e5cb439e4..6e8db7adde3c 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -35,7 +35,7 @@ definitions: name: info type: u32 - - name: tc-cls-flags + name: cls-flags enum-name: type: flags entries: @@ -45,7 +45,7 @@ definitions: - not-in-nw - verbose - - name: tc-flower-key-ctrl-flags + name: flower-key-ctrl-flags name-prefix: tca-flower-key-flags- enum-name: type: flags @@ -1383,7 +1383,7 @@ definitions: type: s32 attribute-sets: - - name: tc-attrs + name: attrs name-prefix: tca- attributes: - @@ -1392,7 +1392,7 @@ attribute-sets: - name: options type: sub-message - sub-message: tc-options-msg + sub-message: options-msg selector: kind - name: stats @@ -1443,7 +1443,7 @@ attribute-sets: name: ext-warn-msg type: string - - name: tc-act-attrs + name: act-attrs name-prefix: tca-act- attributes: - @@ -1452,7 +1452,7 @@ attribute-sets: - name: options type: sub-message - sub-message: tc-act-options-msg + sub-message: act-options-msg selector: kind - name: index @@ -1480,7 +1480,7 @@ attribute-sets: name: in-hw-count type: u32 - - name: tc-act-bpf-attrs + name: act-bpf-attrs name-prefix: tca-act-bpf- header: linux/tc_act/tc_bpf.h attributes: @@ -1513,7 +1513,7 @@ attribute-sets: name: id type: binary - - name: tc-act-connmark-attrs + name: act-connmark-attrs name-prefix: tca-connmark- header: linux/tc_act/tc_connmark.h attributes: @@ -1528,7 +1528,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-csum-attrs + name: act-csum-attrs name-prefix: tca-csum- header: linux/tc_act/tc_csum.h attributes: @@ -1543,7 +1543,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-ct-attrs + name: act-ct-attrs name-prefix: tca-ct- header: linux/tc_act/tc_ct.h attributes: @@ -1607,7 +1607,7 @@ attribute-sets: name: helper-proto type: u8 - - name: tc-act-ctinfo-attrs + name: act-ctinfo-attrs name-prefix: tca-ctinfo- header: linux/tc_act/tc_ctinfo.h attributes: @@ -1643,7 +1643,7 @@ attribute-sets: name: stats-cpmark-set type: u64 - - name: tc-act-gate-attrs + name: act-gate-attrs name-prefix: tca-gate- header: linux/tc_act/tc_gate.h attributes: @@ -1679,7 +1679,7 @@ attribute-sets: name: clockid type: s32 - - name: tc-act-ife-attrs + name: act-ife-attrs name-prefix: tca-ife- header: linux/tc_act/tc_ife.h attributes: @@ -1706,7 +1706,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-mirred-attrs + name: act-mirred-attrs name-prefix: tca-mirred- header: linux/tc_act/tc_mirred.h attributes: @@ -1724,7 +1724,7 @@ attribute-sets: name: blockid type: binary - - name: tc-act-mpls-attrs + name: act-mpls-attrs name-prefix: tca-mpls- header: linux/tc_act/tc_mpls.h attributes: @@ -1756,7 +1756,7 @@ attribute-sets: name: bos type: u8 - - name: tc-act-nat-attrs + name: act-nat-attrs name-prefix: tca-nat- header: linux/tc_act/tc_nat.h attributes: @@ -1771,7 +1771,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-pedit-attrs + name: act-pedit-attrs name-prefix: tca-pedit- header: linux/tc_act/tc_pedit.h attributes: @@ -1796,7 +1796,7 @@ attribute-sets: name: key-ex type: binary - - name: tc-act-simple-attrs + name: act-simple-attrs name-prefix: tca-def- header: linux/tc_act/tc_defact.h attributes: @@ -1814,7 +1814,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-skbedit-attrs + name: act-skbedit-attrs name-prefix: tca-skbedit- header: linux/tc_act/tc_skbedit.h attributes: @@ -1850,7 +1850,7 @@ attribute-sets: name: queue-mapping-max type: u16 - - name: tc-act-skbmod-attrs + name: act-skbmod-attrs name-prefix: tca-skbmod- header: linux/tc_act/tc_skbmod.h attributes: @@ -1874,7 +1874,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-tunnel-key-attrs + name: act-tunnel-key-attrs name-prefix: tca-tunnel-key- header: linux/tc_act/tc_tunnel_key.h attributes: @@ -1926,7 +1926,7 @@ attribute-sets: name: no-frag type: flag - - name: tc-act-vlan-attrs + name: act-vlan-attrs name-prefix: tca-vlan- header: linux/tc_act/tc_vlan.h attributes: @@ -1957,7 +1957,7 @@ attribute-sets: name: push-eth-src type: binary - - name: tc-basic-attrs + name: basic-attrs name-prefix: tca-basic- attributes: - @@ -1966,16 +1966,16 @@ attribute-sets: - name: ematches type: nest - nested-attributes: tc-ematch-attrs + nested-attributes: ematch-attrs - name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: pcnt type: binary @@ -1984,18 +1984,18 @@ attribute-sets: name: pad type: pad - - name: tc-bpf-attrs + name: bpf-attrs name-prefix: tca-bpf- attributes: - name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: classid type: u32 @@ -2024,7 +2024,7 @@ attribute-sets: name: id type: u32 - - name: tc-cake-attrs + name: cake-attrs name-prefix: tca-cake- attributes: - @@ -2082,7 +2082,7 @@ attribute-sets: name: fwmark type: u32 - - name: tc-cake-stats-attrs + name: cake-stats-attrs name-prefix: tca-cake-stats- attributes: - @@ -2116,7 +2116,7 @@ attribute-sets: name: tin-stats type: indexed-array sub-type: nest - nested-attributes: tc-cake-tin-stats-attrs + nested-attributes: cake-tin-stats-attrs - name: deficit type: s32 @@ -2136,7 +2136,7 @@ attribute-sets: name: blue-timer-us type: s32 - - name: tc-cake-tin-stats-attrs + name: cake-tin-stats-attrs name-prefix: tca-cake-tin-stats- attributes: - @@ -2215,7 +2215,7 @@ attribute-sets: name: flow-quantum type: u32 - - name: tc-cbs-attrs + name: cbs-attrs name-prefix: tca-cbs- attributes: - @@ -2223,23 +2223,23 @@ attribute-sets: type: binary struct: tc-cbs-qopt - - name: tc-cgroup-attrs + name: cgroup-attrs name-prefix: tca-cgroup- attributes: - name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: ematches type: binary - - name: tc-choke-attrs + name: choke-attrs name-prefix: tca-choke- attributes: - @@ -2256,7 +2256,7 @@ attribute-sets: name: max-p type: u32 - - name: tc-codel-attrs + name: codel-attrs name-prefix: tca-codel- attributes: - @@ -2275,14 +2275,14 @@ attribute-sets: name: ce-threshold type: u32 - - name: tc-drr-attrs + name: drr-attrs name-prefix: tca-drr- attributes: - name: quantum type: u32 - - name: tc-ematch-attrs + name: ematch-attrs name-prefix: tca-ematch- attr-max-name: tca-ematch-tree-max attributes: @@ -2294,7 +2294,7 @@ attribute-sets: name: tree-list type: binary - - name: tc-flow-attrs + name: flow-attrs name-prefix: tca-flow- attributes: - @@ -2327,7 +2327,7 @@ attribute-sets: - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: ematches type: binary @@ -2335,7 +2335,7 @@ attribute-sets: name: perturb type: u32 - - name: tc-flower-attrs + name: flower-attrs name-prefix: tca-flower- attributes: - @@ -2348,7 +2348,7 @@ attribute-sets: name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: key-eth-dst type: binary @@ -2427,7 +2427,7 @@ attribute-sets: - name: flags type: u32 - enum: tc-cls-flags + enum: cls-flags enum-as-flags: true - name: key-vlan-id @@ -2532,13 +2532,13 @@ attribute-sets: name: key-flags type: u32 byte-order: big-endian - enum: tc-flower-key-ctrl-flags + enum: flower-key-ctrl-flags enum-as-flags: true - name: key-flags-mask type: u32 byte-order: big-endian - enum: tc-flower-key-ctrl-flags + enum: flower-key-ctrl-flags enum-as-flags: true - name: key-icmpv4-code @@ -2661,11 +2661,11 @@ attribute-sets: - name: key-enc-opts type: nest - nested-attributes: tc-flower-key-enc-opts-attrs + nested-attributes: flower-key-enc-opts-attrs - name: key-enc-opts-mask type: nest - nested-attributes: tc-flower-key-enc-opts-attrs + nested-attributes: flower-key-enc-opts-attrs - name: in-hw-count type: u32 @@ -2712,7 +2712,7 @@ attribute-sets: - name: key-mpls-opts type: nest - nested-attributes: tc-flower-key-mpls-opt-attrs + nested-attributes: flower-key-mpls-opt-attrs - name: key-hash type: u32 @@ -2740,7 +2740,7 @@ attribute-sets: - name: key-cfm type: nest - nested-attributes: tc-flower-key-cfm-attrs + nested-attributes: flower-key-cfm-attrs - name: key-spi type: u32 @@ -2753,36 +2753,36 @@ attribute-sets: name: key-enc-flags type: u32 byte-order: big-endian - enum: tc-flower-key-ctrl-flags + enum: flower-key-ctrl-flags enum-as-flags: true - name: key-enc-flags-mask type: u32 byte-order: big-endian - enum: tc-flower-key-ctrl-flags + enum: flower-key-ctrl-flags enum-as-flags: true - - name: tc-flower-key-enc-opts-attrs + name: flower-key-enc-opts-attrs name-prefix: tca-flower-key-enc-opts- attributes: - name: geneve type: nest - nested-attributes: tc-flower-key-enc-opt-geneve-attrs + nested-attributes: flower-key-enc-opt-geneve-attrs - name: vxlan type: nest - nested-attributes: tc-flower-key-enc-opt-vxlan-attrs + nested-attributes: flower-key-enc-opt-vxlan-attrs - name: erspan type: nest - nested-attributes: tc-flower-key-enc-opt-erspan-attrs + nested-attributes: flower-key-enc-opt-erspan-attrs - name: gtp type: nest - nested-attributes: tc-flower-key-enc-opt-gtp-attrs + nested-attributes: flower-key-enc-opt-gtp-attrs - - name: tc-flower-key-enc-opt-geneve-attrs + name: flower-key-enc-opt-geneve-attrs name-prefix: tca-flower-key-enc-opt-geneve- attributes: - @@ -2795,14 +2795,14 @@ attribute-sets: name: data type: binary - - name: tc-flower-key-enc-opt-vxlan-attrs + name: flower-key-enc-opt-vxlan-attrs name-prefix: tca-flower-key-enc-opt-vxlan- attributes: - name: gbp type: u32 - - name: tc-flower-key-enc-opt-erspan-attrs + name: flower-key-enc-opt-erspan-attrs name-prefix: tca-flower-key-enc-opt-erspan- attributes: - @@ -2818,7 +2818,7 @@ attribute-sets: name: hwid type: u8 - - name: tc-flower-key-enc-opt-gtp-attrs + name: flower-key-enc-opt-gtp-attrs name-prefix: tca-flower-key-enc-opt-gtp- attributes: - @@ -2828,7 +2828,7 @@ attribute-sets: name: qfi type: u8 - - name: tc-flower-key-mpls-opt-attrs + name: flower-key-mpls-opt-attrs name-prefix: tca-flower-key-mpls-opt- attr-max-name: tca-flower-key-mpls-opt-lse-max attributes: @@ -2848,7 +2848,7 @@ attribute-sets: name: lse-label type: u32 - - name: tc-flower-key-cfm-attrs + name: flower-key-cfm-attrs name-prefix: tca-flower-key-cfm- attributes: - @@ -2858,7 +2858,7 @@ attribute-sets: name: opcode type: u8 - - name: tc-fw-attrs + name: fw-attrs name-prefix: tca-fw- attributes: - @@ -2867,7 +2867,7 @@ attribute-sets: - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: indev type: string @@ -2875,12 +2875,12 @@ attribute-sets: name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: mask type: u32 - - name: tc-gred-attrs + name: gred-attrs name-prefix: tca-gred- attributes: - @@ -2955,7 +2955,7 @@ attribute-sets: name: flags type: u32 - - name: tc-hfsc-attrs + name: hfsc-attrs attributes: - name: rsc @@ -2967,7 +2967,7 @@ attribute-sets: name: usc type: binary - - name: tc-hhf-attrs + name: hhf-attrs name-prefix: tca-hhf- attributes: - @@ -2992,7 +2992,7 @@ attribute-sets: name: non-hh-weight type: u32 - - name: tc-htb-attrs + name: htb-attrs name-prefix: tca-htb- attributes: - @@ -3025,7 +3025,7 @@ attribute-sets: name: offload type: flag - - name: tc-matchall-attrs + name: matchall-attrs name-prefix: tca-matchall- attributes: - @@ -3035,7 +3035,7 @@ attribute-sets: name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: flags type: u32 @@ -3047,7 +3047,7 @@ attribute-sets: name: pad type: pad - - name: tc-etf-attrs + name: etf-attrs name-prefix: tca-etf- attributes: - @@ -3055,7 +3055,7 @@ attribute-sets: type: binary struct: tc-etf-qopt - - name: tc-ets-attrs + name: ets-attrs name-prefix: tca-ets- attributes: - @@ -3067,7 +3067,7 @@ attribute-sets: - name: quanta type: nest - nested-attributes: tc-ets-attrs + nested-attributes: ets-attrs - name: quanta-band type: u32 @@ -3075,13 +3075,13 @@ attribute-sets: - name: priomap type: nest - nested-attributes: tc-ets-attrs + nested-attributes: ets-attrs - name: priomap-band type: u8 multi-attr: true - - name: tc-fq-attrs + name: fq-attrs name-prefix: tca-fq- attributes: - @@ -3153,7 +3153,7 @@ attribute-sets: sub-type: s32 doc: Weights for each band - - name: tc-fq-codel-attrs + name: fq-codel-attrs name-prefix: tca-fq-codel- attributes: - @@ -3190,7 +3190,7 @@ attribute-sets: name: ce-threshold-mask type: u8 - - name: tc-fq-pie-attrs + name: fq-pie-attrs name-prefix: tca-fq-pie- attributes: - @@ -3230,7 +3230,7 @@ attribute-sets: name: dq-rate-estimator type: u32 - - name: tc-netem-attrs + name: netem-attrs name-prefix: tca-netem- attributes: - @@ -3252,7 +3252,7 @@ attribute-sets: - name: loss type: nest - nested-attributes: tc-netem-loss-attrs + nested-attributes: netem-loss-attrs - name: rate type: binary @@ -3284,7 +3284,7 @@ attribute-sets: name: prng-seed type: u64 - - name: tc-netem-loss-attrs + name: netem-loss-attrs name-prefix: netem-loss- attributes: - @@ -3298,7 +3298,7 @@ attribute-sets: doc: Gilbert Elliot models struct: tc-netem-gemodel - - name: tc-pie-attrs + name: pie-attrs name-prefix: tca-pie- attributes: - @@ -3326,7 +3326,7 @@ attribute-sets: name: dq-rate-estimator type: u32 - - name: tc-police-attrs + name: police-attrs name-prefix: tca-police- attributes: - @@ -3365,7 +3365,7 @@ attribute-sets: name: pktburst64 type: u64 - - name: tc-qfq-attrs + name: qfq-attrs name-prefix: tca-qfq- attributes: - @@ -3375,7 +3375,7 @@ attribute-sets: name: lmax type: u32 - - name: tc-red-attrs + name: red-attrs name-prefix: tca-red- attributes: - @@ -3398,7 +3398,7 @@ attribute-sets: name: mark-block type: u32 - - name: tc-route-attrs + name: route-attrs name-prefix: tca-route4- attributes: - @@ -3416,14 +3416,14 @@ attribute-sets: - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - - name: tc-taprio-attrs + name: taprio-attrs name-prefix: tca-taprio-attr- attributes: - @@ -3433,14 +3433,14 @@ attribute-sets: - name: sched-entry-list type: nest - nested-attributes: tc-taprio-sched-entry-list + nested-attributes: taprio-sched-entry-list - name: sched-base-time type: s64 - name: sched-single-entry type: nest - nested-attributes: tc-taprio-sched-entry + nested-attributes: taprio-sched-entry - name: sched-clockid type: s32 @@ -3465,18 +3465,18 @@ attribute-sets: - name: tc-entry type: nest - nested-attributes: tc-taprio-tc-entry-attrs + nested-attributes: taprio-tc-entry-attrs - - name: tc-taprio-sched-entry-list + name: taprio-sched-entry-list name-prefix: tca-taprio-sched- attributes: - name: entry type: nest - nested-attributes: tc-taprio-sched-entry + nested-attributes: taprio-sched-entry multi-attr: true - - name: tc-taprio-sched-entry + name: taprio-sched-entry name-prefix: tca-taprio-sched-entry- attributes: - @@ -3492,7 +3492,7 @@ attribute-sets: name: interval type: u32 - - name: tc-taprio-tc-entry-attrs + name: taprio-tc-entry-attrs name-prefix: tca-taprio-tc-entry- attributes: - @@ -3505,7 +3505,7 @@ attribute-sets: name: fp type: u32 - - name: tc-tbf-attrs + name: tbf-attrs name-prefix: tca-tbf- attributes: - @@ -3534,7 +3534,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-sample-attrs + name: act-sample-attrs name-prefix: tca-sample- header: linux/tc_act/tc_sample.h attributes: @@ -3559,7 +3559,7 @@ attribute-sets: name: pad type: pad - - name: tc-act-gact-attrs + name: act-gact-attrs name-prefix: tca-gact- header: linux/tc_act/tc_gact.h attributes: @@ -3626,7 +3626,7 @@ attribute-sets: name: pkt64 type: u64 - - name: tc-u32-attrs + name: u32-attrs name-prefix: tca-u32- attributes: - @@ -3648,12 +3648,12 @@ attribute-sets: - name: police type: nest - nested-attributes: tc-police-attrs + nested-attributes: police-attrs - name: act type: indexed-array sub-type: nest - nested-attributes: tc-act-attrs + nested-attributes: act-attrs - name: indev type: string @@ -3674,78 +3674,78 @@ attribute-sets: sub-messages: - - name: tc-options-msg + name: options-msg formats: - value: basic - attribute-set: tc-basic-attrs + attribute-set: basic-attrs - value: bpf - attribute-set: tc-bpf-attrs + attribute-set: bpf-attrs - value: bfifo fixed-header: tc-fifo-qopt - value: cake - attribute-set: tc-cake-attrs + attribute-set: cake-attrs - value: cbs - attribute-set: tc-cbs-attrs + attribute-set: cbs-attrs - value: cgroup - attribute-set: tc-cgroup-attrs + attribute-set: cgroup-attrs - value: choke - attribute-set: tc-choke-attrs + attribute-set: choke-attrs - value: clsact # no content - value: codel - attribute-set: tc-codel-attrs + attribute-set: codel-attrs - value: drr - attribute-set: tc-drr-attrs + attribute-set: drr-attrs - value: etf - attribute-set: tc-etf-attrs + attribute-set: etf-attrs - value: ets - attribute-set: tc-ets-attrs + attribute-set: ets-attrs - value: flow - attribute-set: tc-flow-attrs + attribute-set: flow-attrs - value: flower - attribute-set: tc-flower-attrs + attribute-set: flower-attrs - value: fq - attribute-set: tc-fq-attrs + attribute-set: fq-attrs - value: fq_codel - attribute-set: tc-fq-codel-attrs + attribute-set: fq-codel-attrs - value: fq_pie - attribute-set: tc-fq-pie-attrs + attribute-set: fq-pie-attrs - value: fw - attribute-set: tc-fw-attrs + attribute-set: fw-attrs - value: gred - attribute-set: tc-gred-attrs + attribute-set: gred-attrs - value: hfsc fixed-header: tc-hfsc-qopt - value: hhf - attribute-set: tc-hhf-attrs + attribute-set: hhf-attrs - value: htb - attribute-set: tc-htb-attrs + attribute-set: htb-attrs - value: ingress # no content - value: matchall - attribute-set: tc-matchall-attrs + attribute-set: matchall-attrs - value: mq # no content - @@ -3757,7 +3757,7 @@ sub-messages: - value: netem fixed-header: tc-netem-qopt - attribute-set: tc-netem-attrs + attribute-set: netem-attrs - value: pfifo fixed-header: tc-fifo-qopt @@ -3769,7 +3769,7 @@ sub-messages: fixed-header: tc-fifo-qopt - value: pie - attribute-set: tc-pie-attrs + attribute-set: pie-attrs - value: plug fixed-header: tc-plug-qopt @@ -3778,13 +3778,13 @@ sub-messages: fixed-header: tc-prio-qopt - value: qfq - attribute-set: tc-qfq-attrs + attribute-set: qfq-attrs - value: red - attribute-set: tc-red-attrs + attribute-set: red-attrs - value: route - attribute-set: tc-route-attrs + attribute-set: route-attrs - value: sfb fixed-header: tc-sfb-qopt @@ -3793,79 +3793,79 @@ sub-messages: fixed-header: tc-sfq-qopt-v1 - value: taprio - attribute-set: tc-taprio-attrs + attribute-set: taprio-attrs - value: tbf - attribute-set: tc-tbf-attrs + attribute-set: tbf-attrs - value: u32 - attribute-set: tc-u32-attrs + attribute-set: u32-attrs - - name: tc-act-options-msg + name: act-options-msg formats: - value: bpf - attribute-set: tc-act-bpf-attrs + attribute-set: act-bpf-attrs - value: connmark - attribute-set: tc-act-connmark-attrs + attribute-set: act-connmark-attrs - value: csum - attribute-set: tc-act-csum-attrs + attribute-set: act-csum-attrs - value: ct - attribute-set: tc-act-ct-attrs + attribute-set: act-ct-attrs - value: ctinfo - attribute-set: tc-act-ctinfo-attrs + attribute-set: act-ctinfo-attrs - value: gact - attribute-set: tc-act-gact-attrs + attribute-set: act-gact-attrs - value: gate - attribute-set: tc-act-gate-attrs + attribute-set: act-gate-attrs - value: ife - attribute-set: tc-act-ife-attrs + attribute-set: act-ife-attrs - value: mirred - attribute-set: tc-act-mirred-attrs + attribute-set: act-mirred-attrs - value: mpls - attribute-set: tc-act-mpls-attrs + attribute-set: act-mpls-attrs - value: nat - attribute-set: tc-act-nat-attrs + attribute-set: act-nat-attrs - value: pedit - attribute-set: tc-act-pedit-attrs + attribute-set: act-pedit-attrs - value: police - attribute-set: tc-police-attrs + attribute-set: police-attrs - value: sample - attribute-set: tc-act-sample-attrs + attribute-set: act-sample-attrs - value: simple - attribute-set: tc-act-simple-attrs + attribute-set: act-simple-attrs - value: skbedit - attribute-set: tc-act-skbedit-attrs + attribute-set: act-skbedit-attrs - value: skbmod - attribute-set: tc-act-skbmod-attrs + attribute-set: act-skbmod-attrs - value: tunnel_key - attribute-set: tc-act-tunnel-key-attrs + attribute-set: act-tunnel-key-attrs - value: vlan - attribute-set: tc-act-vlan-attrs + attribute-set: act-vlan-attrs - name: tca-stats-app-msg formats: - value: cake - attribute-set: tc-cake-stats-attrs + attribute-set: cake-stats-attrs - value: choke fixed-header: tc-choke-xstats @@ -3904,7 +3904,7 @@ operations: - name: newqdisc doc: Create new tc qdisc. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3919,7 +3919,7 @@ operations: - name: delqdisc doc: Delete existing tc qdisc. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3927,7 +3927,7 @@ operations: - name: getqdisc doc: Get / dump tc qdisc information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3951,7 +3951,7 @@ operations: - name: newtclass doc: Get / dump tc traffic class information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3960,7 +3960,7 @@ operations: - name: deltclass doc: Get / dump tc traffic class information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3968,7 +3968,7 @@ operations: - name: gettclass doc: Get / dump tc traffic class information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3979,7 +3979,7 @@ operations: - name: newtfilter doc: Get / dump tc filter information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3988,7 +3988,7 @@ operations: - name: deltfilter doc: Get / dump tc filter information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -3999,7 +3999,7 @@ operations: - name: gettfilter doc: Get / dump tc filter information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -4022,7 +4022,7 @@ operations: - name: newchain doc: Get / dump tc chain information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -4031,7 +4031,7 @@ operations: - name: delchain doc: Get / dump tc chain information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: @@ -4041,7 +4041,7 @@ operations: - name: getchain doc: Get / dump tc chain information. - attribute-set: tc-attrs + attribute-set: attrs fixed-header: tcmsg do: request: -- 2.51.0 From cb39645d9a6a8b84f2e820db7c2b49ebd4b18b2c Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:10 -0700 Subject: [PATCH 08/16] tools: ynl-gen: support passing selector to a nest In rtnetlink all submessages had the selector at the same level of nesting as the submessage. We could refer to the relevant attribute from the current struct. In TC, stats are one level of nesting deeper than "kind". Teach the code-gen about structs which need to be passed a selector by the caller for parsing. Because structs are "topologically sorted" one pass of propagating the selectors down is enough. For generating netlink message we depend on the presence bits so no selector passing needed there. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-7-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ynl_gen_c.py | 65 +++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index 1f8cc34ab3f0..c1508d8c1e7a 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -685,7 +685,11 @@ class TypeNest(Type): f"{self.enum_name}, {at}{var}->{self.c_name})") def _attr_get(self, ri, var): - get_lines = [f"if ({self.nested_render_name}_parse(&parg, attr))", + pns = self.family.pure_nested_structs[self.nested_attrs] + args = ["&parg", "attr"] + for sel in pns.external_selectors(): + args.append(f'{var}->{sel.name}') + get_lines = [f"if ({self.nested_render_name}_parse({', '.join(args)}))", "return YNL_PARSE_CB_ERROR;"] init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;", f"parg.data = &{var}->{self.c_name};"] @@ -890,15 +894,24 @@ class TypeSubMessage(TypeNest): def _attr_typol(self): typol = f'.type = YNL_PT_NEST, .nest = &{self.nested_render_name}_nest, ' - typol += f'.is_submsg = 1, .selector_type = {self.attr_set[self["selector"]].value} ' + typol += '.is_submsg = 1, ' + # Reverse-parsing of the policy (ynl_err_walk() in ynl.c) does not + # support external selectors. No family uses sub-messages with external + # selector for requests so this is fine for now. + if not self.selector.is_external(): + typol += f'.selector_type = {self.attr_set[self["selector"]].value} ' return typol def _attr_get(self, ri, var): sel = c_lower(self['selector']) - get_lines = [f'if (!{var}->{sel})', + if self.selector.is_external(): + sel_var = f"_sel_{sel}" + else: + sel_var = f"{var}->{sel}" + get_lines = [f'if (!{sel_var})', f'return ynl_submsg_failed(yarg, "%s", "%s");' % (self.name, self['selector']), - f"if ({self.nested_render_name}_parse(&parg, {var}->{sel}, attr))", + f"if ({self.nested_render_name}_parse(&parg, {sel_var}, attr))", "return YNL_PARSE_CB_ERROR;"] init_lines = [f"parg.rsp_policy = &{self.nested_render_name}_nest;", f"parg.data = &{var}->{self.c_name};"] @@ -914,7 +927,15 @@ class Selector: self.attr.is_selector = True self._external = False else: - raise Exception("Passing selectors from external nests not supported") + # The selector will need to get passed down thru the structs + self.attr = None + self._external = True + + def set_attr(self, attr): + self.attr = attr + + def is_external(self): + return self._external class Struct: @@ -976,6 +997,13 @@ class Struct: raise Exception("Inheriting different members not supported") self.inherited = [c_lower(x) for x in sorted(self._inherited)] + def external_selectors(self): + sels = [] + for name, attr in self.attr_list: + if isinstance(attr, TypeSubMessage) and attr.selector.is_external(): + sels.append(attr.selector) + return sels + def free_needs_iter(self): for _, attr in self.attr_list: if attr.free_needs_iter(): @@ -1222,6 +1250,7 @@ class Family(SpecFamily): self._load_root_sets() self._load_nested_sets() self._load_attr_use() + self._load_selector_passing() self._load_hooks() self.kernel_policy = self.yaml.get('kernel-policy', 'split') @@ -1436,6 +1465,30 @@ class Family(SpecFamily): if attr in rs_members['reply']: spec.set_reply() + def _load_selector_passing(self): + def all_structs(): + for k, v in reversed(self.pure_nested_structs.items()): + yield k, v + for k, _ in self.root_sets.items(): + yield k, None # we don't have a struct, but it must be terminal + + for attr_set, struct in all_structs(): + for _, spec in self.attr_sets[attr_set].items(): + if 'nested-attributes' in spec: + child_name = spec['nested-attributes'] + elif 'sub-message' in spec: + child_name = spec.sub_message + else: + continue + + child = self.pure_nested_structs.get(child_name) + for selector in child.external_selectors(): + if selector.name in self.attr_sets[attr_set]: + sel_attr = self.attr_sets[attr_set][selector.name] + selector.set_attr(sel_attr) + else: + raise Exception("Passing selector thru more than one layer not supported") + def _load_global_policy(self): global_set = set() attr_set_name = None @@ -2183,6 +2236,8 @@ def parse_rsp_submsg(ri, struct): def parse_rsp_nested_prototype(ri, struct, suffix=';'): func_args = ['struct ynl_parse_arg *yarg', 'const struct nlattr *nested'] + for sel in struct.external_selectors(): + func_args.append('const char *_sel_' + sel.name) if struct.submsg: func_args.insert(1, 'const char *sel') for arg in struct.inherited: -- 2.51.0 From a66a170b68af0d588f4eadb9e5813c4edefe24f5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:11 -0700 Subject: [PATCH 09/16] tools: ynl-gen: move fixed header info from RenderInfo to Struct RenderInfo describes a request-response exchange. Struct describes a parsed attribute set. For ease of parsing sub-messages with fixed headers move fixed header info from RenderInfo to Struct. No functional changes. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-8-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ynl_gen_c.py | 45 +++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index c1508d8c1e7a..bd1fadb2cf5a 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -939,7 +939,7 @@ class Selector: class Struct: - def __init__(self, family, space_name, type_list=None, + def __init__(self, family, space_name, type_list=None, fixed_header=None, inherited=None, submsg=None): self.family = family self.space_name = space_name @@ -947,6 +947,9 @@ class Struct: # Use list to catch comparisons with empty sets self._inherited = inherited if inherited is not None else [] self.inherited = [] + self.fixed_header = None + if fixed_header: + self.fixed_header = 'struct ' + c_lower(fixed_header) self.submsg = submsg self.nested = type_list is None @@ -1345,7 +1348,9 @@ class Family(SpecFamily): nested = spec['nested-attributes'] if nested not in self.root_sets: if nested not in self.pure_nested_structs: - self.pure_nested_structs[nested] = Struct(self, nested, inherited=inherit) + self.pure_nested_structs[nested] = \ + Struct(self, nested, inherited=inherit, + fixed_header=spec.get('fixed-header')) else: raise Exception(f'Using attr set as root and nested not supported - {nested}') @@ -1538,13 +1543,12 @@ class RenderInfo: self.op_mode = op_mode self.op = op - self.fixed_hdr = None + fixed_hdr = op.fixed_header if op else None self.fixed_hdr_len = 'ys->family->hdr_len' if op and op.fixed_header: - self.fixed_hdr = 'struct ' + c_lower(op.fixed_header) if op.fixed_header != family.fixed_header: if family.is_classic(): - self.fixed_hdr_len = f"sizeof({self.fixed_hdr})" + self.fixed_hdr_len = f"sizeof(struct {c_lower(fixed_hdr)})" else: raise Exception(f"Per-op fixed header not supported, yet") @@ -1584,12 +1588,17 @@ class RenderInfo: type_list = [] if op_dir in op[op_mode]: type_list = op[op_mode][op_dir]['attributes'] - self.struct[op_dir] = Struct(family, self.attr_set, type_list=type_list) + self.struct[op_dir] = Struct(family, self.attr_set, + fixed_header=fixed_hdr, + type_list=type_list) if op_mode == 'event': - self.struct['reply'] = Struct(family, self.attr_set, type_list=op['event']['attributes']) + self.struct['reply'] = Struct(family, self.attr_set, + fixed_header=fixed_hdr, + type_list=op['event']['attributes']) def type_empty(self, key): - return len(self.struct[key].attr_list) == 0 and self.fixed_hdr is None + return len(self.struct[key].attr_list) == 0 and \ + self.struct['request'].fixed_header is None def needs_nlflags(self, direction): return self.op_mode == 'do' and direction == 'request' and self.family.is_classic() @@ -2057,12 +2066,12 @@ def _multi_parse(ri, struct, init_lines, local_vars): if struct.nested: iter_line = "ynl_attr_for_each_nested(attr, nested)" else: - if ri.fixed_hdr: + if struct.fixed_header: local_vars += ['void *hdr;'] iter_line = "ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len)" if ri.op.fixed_header != ri.family.fixed_header: if ri.family.is_classic(): - iter_line = f"ynl_attr_for_each(attr, nlh, sizeof({ri.fixed_hdr}))" + iter_line = f"ynl_attr_for_each(attr, nlh, sizeof({struct.fixed_header}))" else: raise Exception(f"Per-op fixed header not supported, yet") @@ -2104,12 +2113,12 @@ def _multi_parse(ri, struct, init_lines, local_vars): for arg in struct.inherited: ri.cw.p(f'dst->{arg} = {arg};') - if ri.fixed_hdr: + if struct.fixed_header: if ri.family.is_classic(): ri.cw.p('hdr = ynl_nlmsg_data(nlh);') else: ri.cw.p('hdr = ynl_nlmsg_data_offset(nlh, sizeof(struct genlmsghdr));') - ri.cw.p(f"memcpy(&dst->_hdr, hdr, sizeof({ri.fixed_hdr}));") + ri.cw.p(f"memcpy(&dst->_hdr, hdr, sizeof({struct.fixed_header}));") for anest in sorted(all_multi): aspec = struct[anest] ri.cw.p(f"if (dst->{aspec.c_name})") @@ -2303,7 +2312,7 @@ def print_req(ri): ret_err = 'NULL' local_vars += [f'{type_name(ri, rdir(direction))} *rsp;'] - if ri.fixed_hdr: + if ri.struct["request"].fixed_header: local_vars += ['size_t hdr_len;', 'void *hdr;'] @@ -2327,7 +2336,7 @@ def print_req(ri): ri.cw.p(f"yrs.yarg.rsp_policy = &{ri.struct['reply'].render_name}_nest;") ri.cw.nl() - if ri.fixed_hdr: + if ri.struct['request'].fixed_header: ri.cw.p("hdr_len = sizeof(req->_hdr);") ri.cw.p("hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len);") ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);") @@ -2373,7 +2382,7 @@ def print_dump(ri): 'struct nlmsghdr *nlh;', 'int err;'] - if ri.fixed_hdr: + if ri.struct['request'].fixed_header: local_vars += ['size_t hdr_len;', 'void *hdr;'] @@ -2394,7 +2403,7 @@ def print_dump(ri): else: ri.cw.p(f"nlh = ynl_gemsg_start_dump(ys, {ri.nl.get_family_id()}, {ri.op.enum_name}, 1);") - if ri.fixed_hdr: + if ri.struct['request'].fixed_header: ri.cw.p("hdr_len = sizeof(req->_hdr);") ri.cw.p("hdr = ynl_nlmsg_put_extra_header(nlh, hdr_len);") ri.cw.p("memcpy(hdr, &req->_hdr, hdr_len);") @@ -2471,8 +2480,8 @@ def _print_type(ri, direction, struct): if ri.needs_nlflags(direction): ri.cw.p('__u16 _nlmsg_flags;') ri.cw.nl() - if ri.fixed_hdr: - ri.cw.p(ri.fixed_hdr + ' _hdr;') + if struct.fixed_header: + ri.cw.p(struct.fixed_header + ' _hdr;') ri.cw.nl() for type_filter in ['present', 'len', 'count']: -- 2.51.0 From 092b34b937353eaa6164ceb1f520b1f640aee54f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:12 -0700 Subject: [PATCH 10/16] tools: ynl-gen: support local attrs in _multi_parse The _multi_parse() helper calls the _attr_get() method of each attr, but it only respects what code the helper wants to emit, not what local variables it needs. Local variables will soon be needed, support them. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-9-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/pyynl/ynl_gen_c.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index bd1fadb2cf5a..f2a4404d0d21 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -2214,12 +2214,16 @@ def parse_rsp_submsg(ri, struct): parse_rsp_nested_prototype(ri, struct, suffix='') var = 'dst' + local_vars = {'const struct nlattr *attr = nested;', + f'{struct.ptr_name}{var} = yarg->data;', + 'struct ynl_parse_arg parg;'} - ri.cw.block_start() - ri.cw.write_func_lvar(['const struct nlattr *attr = nested;', - f'{struct.ptr_name}{var} = yarg->data;', - 'struct ynl_parse_arg parg;']) + for _, arg in struct.member_list(): + _, _, l_vars = arg._attr_get(ri, var) + local_vars |= set(l_vars) if l_vars else set() + ri.cw.block_start() + ri.cw.write_func_lvar(list(local_vars)) ri.cw.p('parg.ys = yarg->ys;') ri.cw.nl() -- 2.51.0 From 4e9806a8f49463074f9a5797c34e0740f4602910 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:13 -0700 Subject: [PATCH 11/16] tools: ynl-gen: support weird sub-message formats TC uses all possible sub-message formats: - nested attrs - fixed headers + nested attrs - fixed headers - empty Nested attrs are already supported for rt-link. Add support for remaining 3. The empty and fixed headers ones are fairly trivial, we can fake a Binary or Flags type instead of a Nest. For fixed headers + nest we need to teach nest parsing and nest put to handle fixed headers. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-10-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/lib/ynl-priv.h | 8 ++++-- tools/net/ynl/pyynl/ynl_gen_c.py | 48 ++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/tools/net/ynl/lib/ynl-priv.h b/tools/net/ynl/lib/ynl-priv.h index 416866f85820..824777d7e05e 100644 --- a/tools/net/ynl/lib/ynl-priv.h +++ b/tools/net/ynl/lib/ynl-priv.h @@ -213,11 +213,15 @@ static inline void *ynl_attr_data_end(const struct nlattr *attr) NLMSG_HDRLEN + fixed_hdr_sz); attr; \ (attr) = ynl_attr_next(ynl_nlmsg_end_addr(nlh), attr)) -#define ynl_attr_for_each_nested(attr, outer) \ +#define ynl_attr_for_each_nested_off(attr, outer, offset) \ for ((attr) = ynl_attr_first(outer, outer->nla_len, \ - sizeof(struct nlattr)); attr; \ + sizeof(struct nlattr) + offset); \ + attr; \ (attr) = ynl_attr_next(ynl_attr_data_end(outer), attr)) +#define ynl_attr_for_each_nested(attr, outer) \ + ynl_attr_for_each_nested_off(attr, outer, 0) + #define ynl_attr_for_each_payload(start, len, attr) \ for ((attr) = ynl_attr_first(start, len, 0); attr; \ (attr) = ynl_attr_next(start + len, attr)) diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py index f2a4404d0d21..76032e01c2e7 100755 --- a/tools/net/ynl/pyynl/ynl_gen_c.py +++ b/tools/net/ynl/pyynl/ynl_gen_c.py @@ -1372,12 +1372,25 @@ class Family(SpecFamily): attrs = [] for name, fmt in submsg.formats.items(): - attrs.append({ + attr = { "name": name, - "type": "nest", "parent-sub-message": spec, - "nested-attributes": fmt['attribute-set'] - }) + } + if 'attribute-set' in fmt: + attr |= { + "type": "nest", + "nested-attributes": fmt['attribute-set'], + } + if 'fixed-header' in fmt: + attr |= { "fixed-header": fmt["fixed-header"] } + elif 'fixed-header' in fmt: + attr |= { + "type": "binary", + "struct": fmt["fixed-header"], + } + else: + attr["type"] = "flag" + attrs.append(attr) self.attr_sets[nested] = AttrSet(self, { "name": nested, @@ -1921,8 +1934,11 @@ def put_typol_submsg(cw, struct): i = 0 for name, arg in struct.member_list(): - cw.p('[%d] = { .type = YNL_PT_SUBMSG, .name = "%s", .nest = &%s_nest, },' % - (i, name, arg.nested_render_name)) + nest = "" + if arg.type == 'nest': + nest = f" .nest = &{arg.nested_render_name}_nest," + cw.p('[%d] = { .type = YNL_PT_SUBMSG, .name = "%s",%s },' % + (i, name, nest)) i += 1 cw.block_end(line=';') @@ -2032,6 +2048,11 @@ def put_req_nested(ri, struct): if struct.submsg is None: local_vars.append('struct nlattr *nest;') init_lines.append("nest = ynl_attr_nest_start(nlh, attr_type);") + if struct.fixed_header: + local_vars.append('void *hdr;') + struct_sz = f'sizeof({struct.fixed_header})' + init_lines.append(f"hdr = ynl_nlmsg_put_extra_header(nlh, {struct_sz});") + init_lines.append(f"memcpy(hdr, &obj->_hdr, {struct_sz});") has_anest = False has_count = False @@ -2063,11 +2084,14 @@ def put_req_nested(ri, struct): def _multi_parse(ri, struct, init_lines, local_vars): + if struct.fixed_header: + local_vars += ['void *hdr;'] if struct.nested: - iter_line = "ynl_attr_for_each_nested(attr, nested)" - else: if struct.fixed_header: - local_vars += ['void *hdr;'] + iter_line = f"ynl_attr_for_each_nested_off(attr, nested, sizeof({struct.fixed_header}))" + else: + iter_line = "ynl_attr_for_each_nested(attr, nested)" + else: iter_line = "ynl_attr_for_each(attr, nlh, yarg->ys->family->hdr_len)" if ri.op.fixed_header != ri.family.fixed_header: if ri.family.is_classic(): @@ -2114,7 +2138,9 @@ def _multi_parse(ri, struct, init_lines, local_vars): ri.cw.p(f'dst->{arg} = {arg};') if struct.fixed_header: - if ri.family.is_classic(): + if struct.nested: + ri.cw.p('hdr = ynl_attr_data(nested);') + elif ri.family.is_classic(): ri.cw.p('hdr = ynl_nlmsg_data(nlh);') else: ri.cw.p('hdr = ynl_nlmsg_data_offset(nlh, sizeof(struct genlmsghdr));') @@ -2234,7 +2260,7 @@ def parse_rsp_submsg(ri, struct): ri.cw.block_start(line=f'{kw} (!strcmp(sel, "{name}"))') get_lines, init_lines, _ = arg._attr_get(ri, var) - for line in init_lines: + for line in init_lines or []: ri.cw.p(line) for line in get_lines: ri.cw.p(line) -- 2.51.0 From e06c9d25159c0b12518c68ffe3e400d49d5284e0 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:14 -0700 Subject: [PATCH 12/16] tools: ynl: enable codegen for TC We are ready to support most of TC. Enable C code gen. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-11-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/Makefile.deps | 7 +++++++ tools/net/ynl/generated/Makefile | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/net/ynl/Makefile.deps b/tools/net/ynl/Makefile.deps index 8c378356fc87..90686e241157 100644 --- a/tools/net/ynl/Makefile.deps +++ b/tools/net/ynl/Makefile.deps @@ -39,4 +39,11 @@ CFLAGS_rt-neigh:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ $(call get_hdr_inc,__LINUX_NEIGHBOUR_H,neighbour.h) CFLAGS_rt-route:=$(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) CFLAGS_rt-rule:=$(call get_hdr_inc,__LINUX_FIB_RULES_H,fib_rules.h) +CFLAGS_tc:= $(call get_hdr_inc,__LINUX_RTNETLINK_H,rtnetlink.h) \ + $(call get_hdr_inc,__LINUX_PKT_SCHED_H,pkt_sched.h) \ + $(call get_hdr_inc,__LINUX_PKT_CLS_H,pkt_cls.h) \ + $(call get_hdr_inc,_TC_CT_H,tc_act/tc_ct.h) \ + $(call get_hdr_inc,_TC_MIRRED_H,tc_act/tc_mirred.h) \ + $(call get_hdr_inc,_TC_SKBEDIT_H,tc_act/tc_skbedit.h) \ + $(call get_hdr_inc,_TC_TUNNEL_KEY_H,tc_act/tc_tunnel_key.h) CFLAGS_tcp_metrics:=$(call get_hdr_inc,_LINUX_TCP_METRICS_H,tcp_metrics.h) diff --git a/tools/net/ynl/generated/Makefile b/tools/net/ynl/generated/Makefile index 9208feed28c1..86e1e4a959a7 100644 --- a/tools/net/ynl/generated/Makefile +++ b/tools/net/ynl/generated/Makefile @@ -23,7 +23,7 @@ TOOL_RST:=../pyynl/ynl_gen_rst.py SPECS_DIR:=../../../../Documentation/netlink/specs SPECS_PATHS=$(wildcard $(SPECS_DIR)/*.yaml) -GENS_UNSUP=conntrack nftables tc +GENS_UNSUP=conntrack nftables GENS=$(filter-out ${GENS_UNSUP},$(patsubst $(SPECS_DIR)/%.yaml,%,${SPECS_PATHS})) SRCS=$(patsubst %,%-user.c,${GENS}) HDRS=$(patsubst %,%-user.h,${GENS}) -- 2.51.0 From 33baf6f73a7ce7ca6a05f9ac2c0758f34f04a423 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:15 -0700 Subject: [PATCH 13/16] netlink: specs: tc: add qdisc dump to TC spec Hook TC qdisc dump in the TC qdisc get, it only supported doit until now and dumping will be used by the sample code. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-12-kuba@kernel.org Signed-off-by: Jakub Kicinski --- Documentation/netlink/specs/tc.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/netlink/specs/tc.yaml b/Documentation/netlink/specs/tc.yaml index 6e8db7adde3c..cb7ea7d62e56 100644 --- a/Documentation/netlink/specs/tc.yaml +++ b/Documentation/netlink/specs/tc.yaml @@ -3929,7 +3929,7 @@ operations: doc: Get / dump tc qdisc information. attribute-set: attrs fixed-header: tcmsg - do: + do: &getqdisc-do request: value: 38 attributes: @@ -3948,6 +3948,7 @@ operations: - chain - ingress-block - egress-block + dump: *getqdisc-do - name: newtclass doc: Get / dump tc traffic class information. -- 2.51.0 From 4e4dc6db2b92bced802bdc19c8ef46a1821151be Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 20 May 2025 09:19:16 -0700 Subject: [PATCH 14/16] tools: ynl: add a sample for TC Add a very simple TC dump sample with decoding of fq_codel attrs: # ./tools/net/ynl/samples/tc dummy0: fq_codel limit: 10240p target: 5ms new_flow_cnt: 0 proving that selector passing (for stats) works. Reviewed-by: Donald Hunter Link: https://patch.msgid.link/20250520161916.413298-13-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/net/ynl/samples/.gitignore | 1 + tools/net/ynl/samples/tc.c | 80 ++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 tools/net/ynl/samples/tc.c diff --git a/tools/net/ynl/samples/.gitignore b/tools/net/ynl/samples/.gitignore index b3ec3fb0929f..7f5fca7682d7 100644 --- a/tools/net/ynl/samples/.gitignore +++ b/tools/net/ynl/samples/.gitignore @@ -6,3 +6,4 @@ page-pool rt-addr rt-link rt-route +tc diff --git a/tools/net/ynl/samples/tc.c b/tools/net/ynl/samples/tc.c new file mode 100644 index 000000000000..0bfff0fdd792 --- /dev/null +++ b/tools/net/ynl/samples/tc.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include + +#include + +#include + +#include "tc-user.h" + +static void tc_qdisc_print(struct tc_getqdisc_rsp *q) +{ + char ifname[IF_NAMESIZE]; + const char *name; + + name = if_indextoname(q->_hdr.tcm_ifindex, ifname); + if (name) + printf("%16s: ", name); + + if (q->_len.kind) { + printf("%s ", q->kind); + + if (q->options._present.fq_codel) { + struct tc_fq_codel_attrs *fq_codel; + struct tc_fq_codel_xstats *stats; + + fq_codel = &q->options.fq_codel; + stats = q->stats2.app.fq_codel; + + if (fq_codel->_present.limit) + printf("limit: %dp ", fq_codel->limit); + if (fq_codel->_present.target) + printf("target: %dms ", + (fq_codel->target + 500) / 1000); + if (q->stats2.app._len.fq_codel) + printf("new_flow_cnt: %d ", + stats->qdisc_stats.new_flow_count); + } + } + + printf("\n"); +} + +int main(int argc, char **argv) +{ + struct tc_getqdisc_req_dump *req; + struct tc_getqdisc_list *rsp; + struct ynl_error yerr; + struct ynl_sock *ys; + + ys = ynl_sock_create(&ynl_tc_family, &yerr); + if (!ys) { + fprintf(stderr, "YNL: %s\n", yerr.msg); + return 1; + } + + req = tc_getqdisc_req_dump_alloc(); + if (!req) + goto err_destroy; + + rsp = tc_getqdisc_dump(ys, req); + tc_getqdisc_req_dump_free(req); + if (!rsp) + goto err_close; + + if (ynl_dump_empty(rsp)) + fprintf(stderr, "Error: no addresses reported\n"); + ynl_dump_foreach(rsp, qdisc) + tc_qdisc_print(qdisc); + tc_getqdisc_list_free(rsp); + + ynl_sock_destroy(ys); + return 0; + +err_close: + fprintf(stderr, "YNL: %s\n", ys->err.msg); +err_destroy: + ynl_sock_destroy(ys); + return 2; +} -- 2.51.0 From 55d22ee0358597185f8f5272558ec7cf1a49eb41 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 19 May 2025 10:50:03 -0700 Subject: [PATCH 15/16] net: introduce CONFIG_NET_CRC32C Add a hidden kconfig symbol NET_CRC32C that will group together the functions that calculate CRC32C checksums of packets, so that these don't have to be built into NET-enabled kernels that don't need them. Make skb_crc32c_csum_help() (which is called only when IP_SCTP is enabled) conditional on this symbol, and make IP_SCTP select it. Signed-off-by: Eric Biggers Reviewed-by: Hannes Reinecke Link: https://patch.msgid.link/20250519175012.36581-2-ebiggers@kernel.org Signed-off-by: Jakub Kicinski --- net/Kconfig | 4 ++++ net/core/dev.c | 2 ++ net/sctp/Kconfig | 1 + 3 files changed, 7 insertions(+) diff --git a/net/Kconfig b/net/Kconfig index 202cc595e5e6..5b71a52987d3 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -75,6 +75,10 @@ config NET_DEVMEM config NET_SHAPER bool +config NET_CRC32C + bool + select CRC32 + menu "Networking options" source "net/packet/Kconfig" diff --git a/net/core/dev.c b/net/core/dev.c index 6d1a238dd440..c27607b7f8b0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3596,6 +3596,7 @@ out: } EXPORT_SYMBOL(skb_checksum_help); +#ifdef CONFIG_NET_CRC32C int skb_crc32c_csum_help(struct sk_buff *skb) { __le32 crc32c_csum; @@ -3635,6 +3636,7 @@ out: return ret; } EXPORT_SYMBOL(skb_crc32c_csum_help); +#endif /* CONFIG_NET_CRC32C */ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) { diff --git a/net/sctp/Kconfig b/net/sctp/Kconfig index d18a72df3654..3669ba351856 100644 --- a/net/sctp/Kconfig +++ b/net/sctp/Kconfig @@ -11,6 +11,7 @@ menuconfig IP_SCTP select CRYPTO select CRYPTO_HMAC select CRYPTO_SHA1 + select NET_CRC32C select NET_UDP_TUNNEL help Stream Control Transmission Protocol -- 2.51.0 From a5bd029c733b8ae790d5873e2afeb88b58e3a151 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Mon, 19 May 2025 10:50:04 -0700 Subject: [PATCH 16/16] net: add skb_crc32c() Add skb_crc32c(), which calculates the CRC32C of a sk_buff. It will replace __skb_checksum(), which unnecessarily supports arbitrary checksums. Compared to __skb_checksum(), skb_crc32c(): - Uses the correct type for CRC32C values (u32, not __wsum). - Does not require the caller to provide a skb_checksum_ops struct. - Is faster because it does not use indirect calls and does not use the very slow crc32c_combine(). According to commit 2817a336d4d5 ("net: skb_checksum: allow custom update/combine for walking skb") which added __skb_checksum(), the original motivation for the abstraction layer was to avoid code duplication for CRC32C and other checksums in the future. However: - No additional checksums showed up after CRC32C. __skb_checksum() is only used with the "regular" net checksum and CRC32C. - Indirect calls are expensive. Commit 2544af0344ba ("net: avoid indirect calls in L4 checksum calculation") worked around this using the INDIRECT_CALL_1 macro. But that only avoided the indirect call for the net checksum, and at the cost of an extra branch. - The checksums use different types (__wsum and u32), causing casts to be needed. - It made the checksums of fragments be combined (rather than chained) for both checksums, despite this being highly counterproductive for CRC32C due to how slow crc32c_combine() is. This can clearly be seen in commit 4c2f24549644 ("sctp: linearize early if it's not GSO") which tried to work around this performance bug. With a dedicated function for each checksum, we can instead just use the proper strategy for each checksum. As shown by the following tables, the new function skb_crc32c() is faster than __skb_checksum(), with the improvement varying greatly from 5% to 2500% depending on the case. The largest improvements come from fragmented packets, mainly due to eliminating the inefficient crc32c_combine(). But linear packets are improved too, especially shorter ones, mainly due to eliminating indirect calls. These benchmarks were done on AMD Zen 5. On that CPU, Linux uses IBRS instead of retpoline; an even greater improvement might be seen with retpoline: Linear sk_buffs Length in bytes __skb_checksum cycles skb_crc32c cycles =============== ===================== ================= 64 43 18 256 94 77 1420 204 161 16384 1735 1642 Nonlinear sk_buffs (even split between head and one fragment) Length in bytes __skb_checksum cycles skb_crc32c cycles =============== ===================== ================= 64 579 22 256 829 77 1420 1506 194 16384 4365 1682 Signed-off-by: Eric Biggers Reviewed-by: Hannes Reinecke Link: https://patch.msgid.link/20250519175012.36581-3-ebiggers@kernel.org Signed-off-by: Jakub Kicinski --- include/linux/skbuff.h | 1 + net/core/skbuff.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c7397b17bb08..7ccc6356acac 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -4203,6 +4203,7 @@ __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum, const struct skb_checksum_ops *ops); __wsum skb_checksum(const struct sk_buff *skb, int offset, int len, __wsum csum); +u32 skb_crc32c(const struct sk_buff *skb, int offset, int len, u32 crc); static inline void * __must_check __skb_header_pointer(const struct sk_buff *skb, int offset, int len, diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4159107f1666..94b977db47f9 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -3633,6 +3634,78 @@ __wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, } EXPORT_SYMBOL(skb_copy_and_csum_bits); +#ifdef CONFIG_NET_CRC32C +u32 skb_crc32c(const struct sk_buff *skb, int offset, int len, u32 crc) +{ + int start = skb_headlen(skb); + int i, copy = start - offset; + struct sk_buff *frag_iter; + + if (copy > 0) { + copy = min(copy, len); + crc = crc32c(crc, skb->data + offset, copy); + len -= copy; + if (len == 0) + return crc; + offset += copy; + } + + if (WARN_ON_ONCE(!skb_frags_readable(skb))) + return 0; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + WARN_ON(start > offset + len); + + end = start + skb_frag_size(frag); + copy = end - offset; + if (copy > 0) { + u32 p_off, p_len, copied; + struct page *p; + u8 *vaddr; + + copy = min(copy, len); + skb_frag_foreach_page(frag, + skb_frag_off(frag) + offset - start, + copy, p, p_off, p_len, copied) { + vaddr = kmap_atomic(p); + crc = crc32c(crc, vaddr + p_off, p_len); + kunmap_atomic(vaddr); + } + len -= copy; + if (len == 0) + return crc; + offset += copy; + } + start = end; + } + + skb_walk_frags(skb, frag_iter) { + int end; + + WARN_ON(start > offset + len); + + end = start + frag_iter->len; + copy = end - offset; + if (copy > 0) { + copy = min(copy, len); + crc = skb_crc32c(frag_iter, offset - start, copy, crc); + len -= copy; + if (len == 0) + return crc; + offset += copy; + } + start = end; + } + BUG_ON(len); + + return crc; +} +EXPORT_SYMBOL(skb_crc32c); +#endif /* CONFIG_NET_CRC32C */ + __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len) { __sum16 sum; -- 2.51.0