Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfrm: iptfs: add tracepoint functionality

Add tracepoints to the IP-TFS code.

Signed-off-by: Christian Hopps <chopps@labn.net>
Tested-by: Antony Antony <antony.antony@secunet.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Christian Hopps and committed by
Steffen Klassert
ed58b186 6be02e3e

+288 -1
+218
net/xfrm/trace_iptfs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* xfrm_trace_iptfs.h 3 + * 4 + * August 12 2023, Christian Hopps <chopps@labn.net> 5 + * 6 + * Copyright (c) 2023, LabN Consulting, L.L.C. 7 + */ 8 + 9 + #undef TRACE_SYSTEM 10 + #define TRACE_SYSTEM iptfs 11 + 12 + #if !defined(_TRACE_IPTFS_H) || defined(TRACE_HEADER_MULTI_READ) 13 + #define _TRACE_IPTFS_H 14 + 15 + #include <linux/kernel.h> 16 + #include <linux/skbuff.h> 17 + #include <linux/tracepoint.h> 18 + #include <net/ip.h> 19 + 20 + struct xfrm_iptfs_data; 21 + 22 + TRACE_EVENT(iptfs_egress_recv, 23 + TP_PROTO(struct sk_buff *skb, struct xfrm_iptfs_data *xtfs, u16 blkoff), 24 + TP_ARGS(skb, xtfs, blkoff), 25 + TP_STRUCT__entry(__field(struct sk_buff *, skb) 26 + __field(void *, head) 27 + __field(void *, head_pg_addr) 28 + __field(void *, pg0addr) 29 + __field(u32, skb_len) 30 + __field(u32, data_len) 31 + __field(u32, headroom) 32 + __field(u32, tailroom) 33 + __field(u32, tail) 34 + __field(u32, end) 35 + __field(u32, pg0off) 36 + __field(u8, head_frag) 37 + __field(u8, frag_list) 38 + __field(u8, nr_frags) 39 + __field(u16, blkoff)), 40 + TP_fast_assign(__entry->skb = skb; 41 + __entry->head = skb->head; 42 + __entry->skb_len = skb->len; 43 + __entry->data_len = skb->data_len; 44 + __entry->headroom = skb_headroom(skb); 45 + __entry->tailroom = skb_tailroom(skb); 46 + __entry->tail = (u32)skb->tail; 47 + __entry->end = (u32)skb->end; 48 + __entry->head_frag = skb->head_frag; 49 + __entry->frag_list = (bool)skb_shinfo(skb)->frag_list; 50 + __entry->nr_frags = skb_shinfo(skb)->nr_frags; 51 + __entry->blkoff = blkoff; 52 + __entry->head_pg_addr = page_address(virt_to_head_page(skb->head)); 53 + __entry->pg0addr = (__entry->nr_frags 54 + ? page_address(netmem_to_page(skb_shinfo(skb)->frags[0].netmem)) 55 + : NULL); 56 + __entry->pg0off = (__entry->nr_frags 57 + ? skb_shinfo(skb)->frags[0].offset 58 + : 0); 59 + ), 60 + TP_printk("EGRESS: skb=%p len=%u data_len=%u headroom=%u head_frag=%u frag_list=%u nr_frags=%u blkoff=%u\n\t\ttailroom=%u tail=%u end=%u head=%p hdpgaddr=%p pg0->addr=%p pg0->data=%p pg0->off=%u", 61 + __entry->skb, __entry->skb_len, __entry->data_len, __entry->headroom, 62 + __entry->head_frag, __entry->frag_list, __entry->nr_frags, __entry->blkoff, 63 + __entry->tailroom, __entry->tail, __entry->end, __entry->head, 64 + __entry->head_pg_addr, __entry->pg0addr, __entry->pg0addr + __entry->pg0off, 65 + __entry->pg0off) 66 + ) 67 + 68 + DECLARE_EVENT_CLASS(iptfs_ingress_preq_event, 69 + TP_PROTO(struct sk_buff *skb, struct xfrm_iptfs_data *xtfs, 70 + u32 pmtu, u8 was_gso), 71 + TP_ARGS(skb, xtfs, pmtu, was_gso), 72 + TP_STRUCT__entry(__field(struct sk_buff *, skb) 73 + __field(u32, skb_len) 74 + __field(u32, data_len) 75 + __field(u32, pmtu) 76 + __field(u32, queue_size) 77 + __field(u32, proto_seq) 78 + __field(u8, proto) 79 + __field(u8, was_gso) 80 + ), 81 + TP_fast_assign(__entry->skb = skb; 82 + __entry->skb_len = skb->len; 83 + __entry->data_len = skb->data_len; 84 + __entry->queue_size = 85 + xtfs->cfg.max_queue_size - xtfs->queue_size; 86 + __entry->proto = __trace_ip_proto(ip_hdr(skb)); 87 + __entry->proto_seq = __trace_ip_proto_seq(ip_hdr(skb)); 88 + __entry->pmtu = pmtu; 89 + __entry->was_gso = was_gso; 90 + ), 91 + TP_printk("INGRPREQ: skb=%p len=%u data_len=%u qsize=%u proto=%u proto_seq=%u pmtu=%u was_gso=%u", 92 + __entry->skb, __entry->skb_len, __entry->data_len, 93 + __entry->queue_size, __entry->proto, __entry->proto_seq, 94 + __entry->pmtu, __entry->was_gso)); 95 + 96 + DEFINE_EVENT(iptfs_ingress_preq_event, iptfs_enqueue, 97 + TP_PROTO(struct sk_buff *skb, struct xfrm_iptfs_data *xtfs, u32 pmtu, u8 was_gso), 98 + TP_ARGS(skb, xtfs, pmtu, was_gso)); 99 + 100 + DEFINE_EVENT(iptfs_ingress_preq_event, iptfs_no_queue_space, 101 + TP_PROTO(struct sk_buff *skb, struct xfrm_iptfs_data *xtfs, u32 pmtu, u8 was_gso), 102 + TP_ARGS(skb, xtfs, pmtu, was_gso)); 103 + 104 + DEFINE_EVENT(iptfs_ingress_preq_event, iptfs_too_big, 105 + TP_PROTO(struct sk_buff *skb, struct xfrm_iptfs_data *xtfs, u32 pmtu, u8 was_gso), 106 + TP_ARGS(skb, xtfs, pmtu, was_gso)); 107 + 108 + DECLARE_EVENT_CLASS(iptfs_ingress_postq_event, 109 + TP_PROTO(struct sk_buff *skb, u32 mtu, u16 blkoff, struct iphdr *iph), 110 + TP_ARGS(skb, mtu, blkoff, iph), 111 + TP_STRUCT__entry(__field(struct sk_buff *, skb) 112 + __field(u32, skb_len) 113 + __field(u32, data_len) 114 + __field(u32, mtu) 115 + __field(u32, proto_seq) 116 + __field(u16, blkoff) 117 + __field(u8, proto)), 118 + TP_fast_assign(__entry->skb = skb; 119 + __entry->skb_len = skb->len; 120 + __entry->data_len = skb->data_len; 121 + __entry->mtu = mtu; 122 + __entry->blkoff = blkoff; 123 + __entry->proto = iph ? __trace_ip_proto(iph) : 0; 124 + __entry->proto_seq = iph ? __trace_ip_proto_seq(iph) : 0; 125 + ), 126 + TP_printk("INGRPSTQ: skb=%p len=%u data_len=%u mtu=%u blkoff=%u proto=%u proto_seq=%u", 127 + __entry->skb, __entry->skb_len, __entry->data_len, __entry->mtu, 128 + __entry->blkoff, __entry->proto, __entry->proto_seq)); 129 + 130 + DEFINE_EVENT(iptfs_ingress_postq_event, iptfs_first_dequeue, 131 + TP_PROTO(struct sk_buff *skb, u32 mtu, u16 blkoff, 132 + struct iphdr *iph), 133 + TP_ARGS(skb, mtu, blkoff, iph)); 134 + 135 + DEFINE_EVENT(iptfs_ingress_postq_event, iptfs_first_fragmenting, 136 + TP_PROTO(struct sk_buff *skb, u32 mtu, u16 blkoff, 137 + struct iphdr *iph), 138 + TP_ARGS(skb, mtu, blkoff, iph)); 139 + 140 + DEFINE_EVENT(iptfs_ingress_postq_event, iptfs_first_final_fragment, 141 + TP_PROTO(struct sk_buff *skb, u32 mtu, u16 blkoff, 142 + struct iphdr *iph), 143 + TP_ARGS(skb, mtu, blkoff, iph)); 144 + 145 + DEFINE_EVENT(iptfs_ingress_postq_event, iptfs_first_toobig, 146 + TP_PROTO(struct sk_buff *skb, u32 mtu, u16 blkoff, 147 + struct iphdr *iph), 148 + TP_ARGS(skb, mtu, blkoff, iph)); 149 + 150 + TRACE_EVENT(iptfs_ingress_nth_peek, 151 + TP_PROTO(struct sk_buff *skb, u32 remaining), 152 + TP_ARGS(skb, remaining), 153 + TP_STRUCT__entry(__field(struct sk_buff *, skb) 154 + __field(u32, skb_len) 155 + __field(u32, remaining)), 156 + TP_fast_assign(__entry->skb = skb; 157 + __entry->skb_len = skb->len; 158 + __entry->remaining = remaining; 159 + ), 160 + TP_printk("INGRPSTQ: NTHPEEK: skb=%p len=%u remaining=%u", 161 + __entry->skb, __entry->skb_len, __entry->remaining)); 162 + 163 + TRACE_EVENT(iptfs_ingress_nth_add, TP_PROTO(struct sk_buff *skb, u8 share_ok), 164 + TP_ARGS(skb, share_ok), 165 + TP_STRUCT__entry(__field(struct sk_buff *, skb) 166 + __field(u32, skb_len) 167 + __field(u32, data_len) 168 + __field(u8, share_ok) 169 + __field(u8, head_frag) 170 + __field(u8, pp_recycle) 171 + __field(u8, cloned) 172 + __field(u8, shared) 173 + __field(u8, nr_frags) 174 + __field(u8, frag_list) 175 + ), 176 + TP_fast_assign(__entry->skb = skb; 177 + __entry->skb_len = skb->len; 178 + __entry->data_len = skb->data_len; 179 + __entry->share_ok = share_ok; 180 + __entry->head_frag = skb->head_frag; 181 + __entry->pp_recycle = skb->pp_recycle; 182 + __entry->cloned = skb_cloned(skb); 183 + __entry->shared = skb_shared(skb); 184 + __entry->nr_frags = skb_shinfo(skb)->nr_frags; 185 + __entry->frag_list = (bool)skb_shinfo(skb)->frag_list; 186 + ), 187 + TP_printk("INGRPSTQ: NTHADD: skb=%p len=%u data_len=%u share_ok=%u head_frag=%u pp_recycle=%u cloned=%u shared=%u nr_frags=%u frag_list=%u", 188 + __entry->skb, __entry->skb_len, __entry->data_len, __entry->share_ok, 189 + __entry->head_frag, __entry->pp_recycle, __entry->cloned, __entry->shared, 190 + __entry->nr_frags, __entry->frag_list)); 191 + 192 + DECLARE_EVENT_CLASS(iptfs_timer_event, 193 + TP_PROTO(struct xfrm_iptfs_data *xtfs, u64 time_val), 194 + TP_ARGS(xtfs, time_val), 195 + TP_STRUCT__entry(__field(u64, time_val) 196 + __field(u64, set_time)), 197 + TP_fast_assign(__entry->time_val = time_val; 198 + __entry->set_time = xtfs->iptfs_settime; 199 + ), 200 + TP_printk("TIMER: set_time=%llu time_val=%llu", 201 + __entry->set_time, __entry->time_val)); 202 + 203 + DEFINE_EVENT(iptfs_timer_event, iptfs_timer_start, 204 + TP_PROTO(struct xfrm_iptfs_data *xtfs, u64 time_val), 205 + TP_ARGS(xtfs, time_val)); 206 + 207 + DEFINE_EVENT(iptfs_timer_event, iptfs_timer_expire, 208 + TP_PROTO(struct xfrm_iptfs_data *xtfs, u64 time_val), 209 + TP_ARGS(xtfs, time_val)); 210 + 211 + #endif /* _TRACE_IPTFS_H */ 212 + 213 + /* This part must be outside protection */ 214 + #undef TRACE_INCLUDE_PATH 215 + #define TRACE_INCLUDE_PATH ../../net/xfrm 216 + #undef TRACE_INCLUDE_FILE 217 + #define TRACE_INCLUDE_FILE trace_iptfs 218 + #include <trace/define_trace.h>
+70 -1
net/xfrm/xfrm_iptfs.c
··· 19 19 #include <crypto/aead.h> 20 20 21 21 #include "xfrm_inout.h" 22 + #include "trace_iptfs.h" 22 23 23 24 /* IPTFS encap (header) values. */ 24 25 #define IPTFS_SUBTYPE_BASIC 0 ··· 132 131 * @ecn_queue_size: octets above with ECN mark. 133 132 * @init_delay_ns: nanoseconds to wait to send initial IPTFS packet. 134 133 * @iptfs_timer: output timer. 134 + * @iptfs_settime: time the output timer was set. 135 135 * @payload_mtu: max payload size. 136 136 * @w_seq_set: true after first seq received. 137 137 * @w_wantseq: waiting for this seq number as next to process (in order). ··· 157 155 u32 ecn_queue_size; /* octets above which ECN mark */ 158 156 u64 init_delay_ns; /* nanoseconds */ 159 157 struct hrtimer iptfs_timer; /* output timer */ 158 + time64_t iptfs_settime; /* time timer was set */ 160 159 u32 payload_mtu; /* max payload size */ 161 160 162 161 /* Tunnel input reordering */ ··· 183 180 /* ================= */ 184 181 /* Utility Functions */ 185 182 /* ================= */ 183 + 184 + #ifdef TRACEPOINTS_ENABLED 185 + static u32 __trace_ip_proto(struct iphdr *iph) 186 + { 187 + if (iph->version == 4) 188 + return iph->protocol; 189 + return ((struct ipv6hdr *)iph)->nexthdr; 190 + } 191 + 192 + static u32 __trace_ip_proto_seq(struct iphdr *iph) 193 + { 194 + void *nexthdr; 195 + u32 protocol = 0; 196 + 197 + if (iph->version == 4) { 198 + nexthdr = (void *)(iph + 1); 199 + protocol = iph->protocol; 200 + } else if (iph->version == 6) { 201 + nexthdr = (void *)(((struct ipv6hdr *)(iph)) + 1); 202 + protocol = ((struct ipv6hdr *)(iph))->nexthdr; 203 + } 204 + switch (protocol) { 205 + case IPPROTO_ICMP: 206 + return ntohs(((struct icmphdr *)nexthdr)->un.echo.sequence); 207 + case IPPROTO_ICMPV6: 208 + return ntohs(((struct icmp6hdr *)nexthdr)->icmp6_sequence); 209 + case IPPROTO_TCP: 210 + return ntohl(((struct tcphdr *)nexthdr)->seq); 211 + case IPPROTO_UDP: 212 + return ntohs(((struct udphdr *)nexthdr)->source); 213 + default: 214 + return 0; 215 + } 216 + } 217 + #endif /*TRACEPOINTS_ENABLED*/ 186 218 187 219 static u64 __esp_seq(struct sk_buff *skb) 188 220 { ··· 498 460 } 499 461 return len; 500 462 } 463 + 464 + /* ================================== */ 465 + /* IPTFS Trace Event Definitions */ 466 + /* ================================== */ 467 + 468 + #define CREATE_TRACE_POINTS 469 + #include "trace_iptfs.h" 501 470 502 471 /* ================================== */ 503 472 /* IPTFS Receiving (egress) Functions */ ··· 1231 1186 } 1232 1187 data = sizeof(*ipth); 1233 1188 1189 + trace_iptfs_egress_recv(skb, xtfs, be16_to_cpu(ipth->block_offset)); 1190 + 1234 1191 /* Set data past the basic header */ 1235 1192 if (ipth->subtype == IPTFS_SUBTYPE_CC) { 1236 1193 /* Copy the rest of the CC header */ ··· 1877 1830 */ 1878 1831 if (!ok) { 1879 1832 nospace: 1833 + trace_iptfs_no_queue_space(skb, xtfs, pmtu, was_gso); 1880 1834 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOQSPACE); 1881 1835 kfree_skb_reason(skb, SKB_DROP_REASON_FULL_RING); 1882 1836 continue; ··· 1887 1839 * enqueue. 1888 1840 */ 1889 1841 if (xtfs->cfg.dont_frag && iptfs_is_too_big(sk, skb, pmtu)) { 1842 + trace_iptfs_too_big(skb, xtfs, pmtu, was_gso); 1890 1843 kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG); 1891 1844 continue; 1892 1845 } ··· 1896 1847 ok = iptfs_enqueue(xtfs, skb); 1897 1848 if (!ok) 1898 1849 goto nospace; 1850 + 1851 + trace_iptfs_enqueue(skb, xtfs, pmtu, was_gso); 1899 1852 } 1900 1853 1901 1854 /* Start a delay timer if we don't have one yet */ 1902 - if (!hrtimer_is_queued(&xtfs->iptfs_timer)) 1855 + if (!hrtimer_is_queued(&xtfs->iptfs_timer)) { 1903 1856 hrtimer_start(&xtfs->iptfs_timer, xtfs->init_delay_ns, IPTFS_HRTIMER_MODE); 1857 + xtfs->iptfs_settime = ktime_get_raw_fast_ns(); 1858 + trace_iptfs_timer_start(xtfs, xtfs->init_delay_ns); 1859 + } 1904 1860 1905 1861 spin_unlock_bh(&x->lock); 1906 1862 return 0; ··· 1988 1934 struct sk_buff *nskb = *skbp; 1989 1935 u32 copy_len, offset; 1990 1936 u32 to_copy = skb->len - mtu; 1937 + u32 blkoff = 0; 1991 1938 int err = 0; 1992 1939 1993 1940 INIT_LIST_HEAD(&sublist); ··· 2000 1945 to_copy = skb->len - offset; 2001 1946 while (to_copy) { 2002 1947 /* Send all but last fragment to allow agg. append */ 1948 + trace_iptfs_first_fragmenting(nskb, mtu, to_copy, NULL); 2003 1949 list_add_tail(&nskb->list, &sublist); 2004 1950 2005 1951 /* FUTURE: if the packet has an odd/non-aligning length we could ··· 2019 1963 iptfs_output_prepare_skb(nskb, to_copy); 2020 1964 offset += copy_len; 2021 1965 to_copy -= copy_len; 1966 + blkoff = to_copy; 2022 1967 } 2023 1968 skb_abort_seq_read(&skbseq); 2024 1969 2025 1970 /* return last fragment that will be unsent (or NULL) */ 2026 1971 *skbp = nskb; 1972 + if (nskb) 1973 + trace_iptfs_first_final_fragment(nskb, mtu, blkoff, NULL); 2027 1974 2028 1975 /* trim the original skb to MTU */ 2029 1976 if (!err) ··· 2100 2041 } 2101 2042 2102 2043 /* We've split gso up before queuing */ 2044 + 2045 + trace_iptfs_first_dequeue(skb, mtu, 0, ip_hdr(skb)); 2103 2046 2104 2047 /* Consider the buffer Tx'd and no longer owned */ 2105 2048 skb_orphan(skb); ··· 2198 2137 */ 2199 2138 XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTERROR); 2200 2139 2140 + trace_iptfs_first_toobig(skb, mtu, 0, ip_hdr(skb)); 2201 2141 kfree_skb_reason(skb, SKB_DROP_REASON_PKT_TOO_BIG); 2202 2142 continue; 2203 2143 } ··· 2245 2183 * case. 2246 2184 */ 2247 2185 while ((skb2 = skb_peek(list))) { 2186 + trace_iptfs_ingress_nth_peek(skb2, remaining); 2248 2187 if (skb2->len > remaining) 2249 2188 break; 2250 2189 ··· 2283 2220 skb->len += skb2->len; 2284 2221 remaining -= skb2->len; 2285 2222 2223 + trace_iptfs_ingress_nth_add(skb2, share_ok); 2224 + 2286 2225 if (share_ok) { 2287 2226 iptfs_consume_frags(skb, skb2); 2288 2227 } else { ··· 2307 2242 struct sk_buff_head list; 2308 2243 struct xfrm_iptfs_data *xtfs; 2309 2244 struct xfrm_state *x; 2245 + time64_t settime; 2310 2246 2311 2247 xtfs = container_of(me, typeof(*xtfs), iptfs_timer); 2312 2248 x = xtfs->x; ··· 2324 2258 __skb_queue_head_init(&list); 2325 2259 skb_queue_splice_init(&xtfs->queue, &list); 2326 2260 xtfs->queue_size = 0; 2261 + settime = xtfs->iptfs_settime; 2327 2262 spin_unlock(&x->lock); 2328 2263 2329 2264 /* After the above unlock, packets can begin queuing again, and the ··· 2332 2265 * context (not from this one since we are running at softirq level 2333 2266 * already). 2334 2267 */ 2268 + 2269 + trace_iptfs_timer_expire(xtfs, (unsigned long long)(ktime_get_raw_fast_ns() - settime)); 2335 2270 2336 2271 iptfs_output_queued(x, &list); 2337 2272