|
| 1 | +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h |
| 2 | +index cd4a8268894a..92b93cd62802 100644 |
| 3 | +--- a/include/linux/skbuff.h |
| 4 | ++++ b/include/linux/skbuff.h |
| 5 | +@@ -1018,6 +1018,11 @@ struct sk_buff { |
| 6 | + u64 kcov_handle; |
| 7 | + #endif |
| 8 | + |
| 9 | ++ struct { |
| 10 | ++ __be64 high, low; |
| 11 | ++ } id; |
| 12 | ++ __be64 sid; |
| 13 | ++ |
| 14 | + ); /* end headers group */ |
| 15 | + |
| 16 | + /* These elements must be at the end, see alloc_skb() for details. */ |
| 17 | +diff --git a/include/net/sock.h b/include/net/sock.h |
| 18 | +index 5bed1ea7a722..502397a79d0a 100644 |
| 19 | +--- a/include/net/sock.h |
| 20 | ++++ b/include/net/sock.h |
| 21 | +@@ -537,6 +537,11 @@ struct sock { |
| 22 | + #endif |
| 23 | + struct rcu_head sk_rcu; |
| 24 | + netns_tracker ns_tracker; |
| 25 | ++ |
| 26 | ++ struct { |
| 27 | ++ __be64 high, low; |
| 28 | ++ } sk_pkt_id; |
| 29 | ++ __be64 sk_pkt_sid; |
| 30 | + }; |
| 31 | + |
| 32 | + enum sk_pacing { |
| 33 | +diff --git a/include/uapi/linux/ioam6.h b/include/uapi/linux/ioam6.h |
| 34 | +index ac4de376f0ce..b145f9e8d431 100644 |
| 35 | +--- a/include/uapi/linux/ioam6.h |
| 36 | ++++ b/include/uapi/linux/ioam6.h |
| 37 | +@@ -126,6 +126,11 @@ struct ioam6_trace_hdr { |
| 38 | + #error "Please fix <asm/byteorder.h>" |
| 39 | + #endif |
| 40 | + |
| 41 | ++ struct { |
| 42 | ++ __be64 high, low; |
| 43 | ++ } pkt_id; |
| 44 | ++ __be64 pkt_sid; |
| 45 | ++ |
| 46 | + #define IOAM6_TRACE_DATA_SIZE_MAX 244 |
| 47 | + __u8 data[0]; |
| 48 | + } __attribute__((packed)); |
| 49 | +diff --git a/include/uapi/linux/ioam6_genl.h b/include/uapi/linux/ioam6_genl.h |
| 50 | +index ca4b22833754..0272d0b9e173 100644 |
| 51 | +--- a/include/uapi/linux/ioam6_genl.h |
| 52 | ++++ b/include/uapi/linux/ioam6_genl.h |
| 53 | +@@ -26,6 +26,12 @@ enum { |
| 54 | + |
| 55 | + IOAM6_ATTR_PAD, |
| 56 | + |
| 57 | ++ /* Packet Identification */ |
| 58 | ++ IOAM6_ATTR_SOCKFD, /* unsigned int */ |
| 59 | ++ IOAM6_ATTR_ID_HIGH, /* u64 */ |
| 60 | ++ IOAM6_ATTR_ID_LOW, /* u64 */ |
| 61 | ++ IOAM6_ATTR_SUBID, /* u64 */ |
| 62 | ++ |
| 63 | + __IOAM6_ATTR_MAX, |
| 64 | + }; |
| 65 | + |
| 66 | +@@ -44,6 +50,10 @@ enum { |
| 67 | + |
| 68 | + IOAM6_CMD_NS_SET_SCHEMA, |
| 69 | + |
| 70 | ++ /* Packet Identification */ |
| 71 | ++ IOAM6_CMD_PKT_ID_ENABLE, |
| 72 | ++ IOAM6_CMD_PKT_ID_DISABLE, |
| 73 | ++ |
| 74 | + __IOAM6_CMD_MAX, |
| 75 | + }; |
| 76 | + |
| 77 | +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c |
| 78 | +index f7309452bdce..17e4589a9bb0 100644 |
| 79 | +--- a/net/ipv4/tcp.c |
| 80 | ++++ b/net/ipv4/tcp.c |
| 81 | +@@ -1299,9 +1299,14 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) |
| 82 | + int copy = 0; |
| 83 | + |
| 84 | + skb = tcp_write_queue_tail(sk); |
| 85 | +- if (skb) |
| 86 | ++ if (skb) { |
| 87 | + copy = size_goal - skb->len; |
| 88 | + |
| 89 | ++ skb->id.high = READ_ONCE(sk->sk_pkt_id.high); |
| 90 | ++ skb->id.low = READ_ONCE(sk->sk_pkt_id.low); |
| 91 | ++ skb->sid = READ_ONCE(sk->sk_pkt_sid); |
| 92 | ++ } |
| 93 | ++ |
| 94 | + if (copy <= 0 || !tcp_skb_can_collapse_to(skb)) { |
| 95 | + bool first_skb; |
| 96 | + |
| 97 | +@@ -1320,6 +1325,10 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) |
| 98 | + if (!skb) |
| 99 | + goto wait_for_space; |
| 100 | + |
| 101 | ++ skb->id.high = READ_ONCE(sk->sk_pkt_id.high); |
| 102 | ++ skb->id.low = READ_ONCE(sk->sk_pkt_id.low); |
| 103 | ++ skb->sid = READ_ONCE(sk->sk_pkt_sid); |
| 104 | ++ |
| 105 | + process_backlog++; |
| 106 | + |
| 107 | + tcp_skb_entail(sk, skb); |
| 108 | +diff --git a/net/ipv6/ioam6.c b/net/ipv6/ioam6.c |
| 109 | +index 1098131ed90c..c9560a07acc4 100644 |
| 110 | +--- a/net/ipv6/ioam6.c |
| 111 | ++++ b/net/ipv6/ioam6.c |
| 112 | +@@ -104,6 +104,17 @@ static const struct nla_policy ioam6_genl_policy_ns_sc[] = { |
| 113 | + [IOAM6_ATTR_SC_NONE] = { .type = NLA_FLAG }, |
| 114 | + }; |
| 115 | + |
| 116 | ++static const struct nla_policy ioam6_genl_policy_pktid_enable[] = { |
| 117 | ++ [IOAM6_ATTR_SOCKFD] = { .type = NLA_U32 }, |
| 118 | ++ [IOAM6_ATTR_ID_HIGH] = { .type = NLA_U64 }, |
| 119 | ++ [IOAM6_ATTR_ID_LOW] = { .type = NLA_U64 }, |
| 120 | ++ [IOAM6_ATTR_SUBID] = { .type = NLA_U64 }, |
| 121 | ++}; |
| 122 | ++ |
| 123 | ++static const struct nla_policy ioam6_genl_policy_pktid_disable[] = { |
| 124 | ++ [IOAM6_ATTR_SOCKFD] = { .type = NLA_U32 }, |
| 125 | ++}; |
| 126 | ++ |
| 127 | + static int ioam6_genl_addns(struct sk_buff *skb, struct genl_info *info) |
| 128 | + { |
| 129 | + struct ioam6_pernet_data *nsdata; |
| 130 | +@@ -553,6 +564,108 @@ static int ioam6_genl_ns_set_schema(struct sk_buff *skb, struct genl_info *info) |
| 131 | + return err; |
| 132 | + } |
| 133 | + |
| 134 | ++static int ioam6_genl_pktid_enable(struct sk_buff *skb, struct genl_info *info) |
| 135 | ++{ |
| 136 | ++ u64 id_h, id_l, sid; |
| 137 | ++ struct socket *sock; |
| 138 | ++ struct fd f; |
| 139 | ++ bool slow; |
| 140 | ++ int err; |
| 141 | ++ |
| 142 | ++ if (!info->attrs[IOAM6_ATTR_SOCKFD] || |
| 143 | ++ !info->attrs[IOAM6_ATTR_ID_HIGH] || |
| 144 | ++ !info->attrs[IOAM6_ATTR_ID_LOW] || |
| 145 | ++ !info->attrs[IOAM6_ATTR_SUBID]) { |
| 146 | ++ err = -EINVAL; |
| 147 | ++ goto out; |
| 148 | ++ } |
| 149 | ++ |
| 150 | ++ f = fdget_raw(nla_get_u32(info->attrs[IOAM6_ATTR_SOCKFD])); |
| 151 | ++ if (!f.file) { |
| 152 | ++ err = -EBADF; |
| 153 | ++ goto out; |
| 154 | ++ } |
| 155 | ++ |
| 156 | ++ if (!S_ISSOCK(f.file->f_path.dentry->d_inode->i_mode)) { |
| 157 | ++ err = -ENOTSOCK; |
| 158 | ++ goto release; |
| 159 | ++ } |
| 160 | ++ |
| 161 | ++ sock = sock_from_file(f.file); |
| 162 | ++ if (!sock) { |
| 163 | ++ err = -ENOTSOCK; |
| 164 | ++ goto release; |
| 165 | ++ } |
| 166 | ++ |
| 167 | ++ if (!sock->sk || sock->sk->sk_family != AF_INET6) { |
| 168 | ++ err = -ESOCKTNOSUPPORT; |
| 169 | ++ goto release; |
| 170 | ++ } |
| 171 | ++ |
| 172 | ++ id_h = cpu_to_be64(nla_get_u64(info->attrs[IOAM6_ATTR_ID_HIGH])); |
| 173 | ++ id_l = cpu_to_be64(nla_get_u64(info->attrs[IOAM6_ATTR_ID_LOW])); |
| 174 | ++ sid = cpu_to_be64(nla_get_u64(info->attrs[IOAM6_ATTR_SUBID])); |
| 175 | ++ |
| 176 | ++ slow = lock_sock_fast(sock->sk); |
| 177 | ++ WRITE_ONCE(sock->sk->sk_pkt_id.high, id_h); |
| 178 | ++ WRITE_ONCE(sock->sk->sk_pkt_id.low, id_l); |
| 179 | ++ WRITE_ONCE(sock->sk->sk_pkt_sid, sid); |
| 180 | ++ unlock_sock_fast(sock->sk, slow); |
| 181 | ++ |
| 182 | ++ err = 0; |
| 183 | ++release: |
| 184 | ++ fdput(f); |
| 185 | ++out: |
| 186 | ++ return err; |
| 187 | ++} |
| 188 | ++ |
| 189 | ++static int ioam6_genl_pktid_disable(struct sk_buff *skb, struct genl_info *info) |
| 190 | ++{ |
| 191 | ++ struct socket *sock; |
| 192 | ++ struct fd f; |
| 193 | ++ bool slow; |
| 194 | ++ int err; |
| 195 | ++ |
| 196 | ++ if (!info->attrs[IOAM6_ATTR_SOCKFD]) { |
| 197 | ++ err = -EINVAL; |
| 198 | ++ goto out; |
| 199 | ++ } |
| 200 | ++ |
| 201 | ++ f = fdget_raw(nla_get_u32(info->attrs[IOAM6_ATTR_SOCKFD])); |
| 202 | ++ if (!f.file) { |
| 203 | ++ err = -EBADF; |
| 204 | ++ goto out; |
| 205 | ++ } |
| 206 | ++ |
| 207 | ++ if (!S_ISSOCK(f.file->f_path.dentry->d_inode->i_mode)) { |
| 208 | ++ err = -ENOTSOCK; |
| 209 | ++ goto release; |
| 210 | ++ } |
| 211 | ++ |
| 212 | ++ sock = sock_from_file(f.file); |
| 213 | ++ if (!sock) { |
| 214 | ++ err = -ENOTSOCK; |
| 215 | ++ goto release; |
| 216 | ++ } |
| 217 | ++ |
| 218 | ++ if (!sock->sk || sock->sk->sk_family != AF_INET6) { |
| 219 | ++ err = -ESOCKTNOSUPPORT; |
| 220 | ++ goto release; |
| 221 | ++ } |
| 222 | ++ |
| 223 | ++ slow = lock_sock_fast(sock->sk); |
| 224 | ++ WRITE_ONCE(sock->sk->sk_pkt_id.high, 0); |
| 225 | ++ WRITE_ONCE(sock->sk->sk_pkt_id.low, 0); |
| 226 | ++ WRITE_ONCE(sock->sk->sk_pkt_sid, 0); |
| 227 | ++ unlock_sock_fast(sock->sk, slow); |
| 228 | ++ |
| 229 | ++ err = 0; |
| 230 | ++release: |
| 231 | ++ fdput(f); |
| 232 | ++out: |
| 233 | ++ return err; |
| 234 | ++} |
| 235 | ++ |
| 236 | + static const struct genl_ops ioam6_genl_ops[] = { |
| 237 | + { |
| 238 | + .cmd = IOAM6_CMD_ADD_NAMESPACE, |
| 239 | +@@ -610,6 +723,22 @@ static const struct genl_ops ioam6_genl_ops[] = { |
| 240 | + .policy = ioam6_genl_policy_ns_sc, |
| 241 | + .maxattr = ARRAY_SIZE(ioam6_genl_policy_ns_sc) - 1, |
| 242 | + }, |
| 243 | ++ { |
| 244 | ++ .cmd = IOAM6_CMD_PKT_ID_ENABLE, |
| 245 | ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
| 246 | ++ .doit = ioam6_genl_pktid_enable, |
| 247 | ++ .flags = GENL_ADMIN_PERM, |
| 248 | ++ .policy = ioam6_genl_policy_pktid_enable, |
| 249 | ++ .maxattr = ARRAY_SIZE(ioam6_genl_policy_pktid_enable) - 1, |
| 250 | ++ }, |
| 251 | ++ { |
| 252 | ++ .cmd = IOAM6_CMD_PKT_ID_DISABLE, |
| 253 | ++ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, |
| 254 | ++ .doit = ioam6_genl_pktid_disable, |
| 255 | ++ .flags = GENL_ADMIN_PERM, |
| 256 | ++ .policy = ioam6_genl_policy_pktid_disable, |
| 257 | ++ .maxattr = ARRAY_SIZE(ioam6_genl_policy_pktid_disable) - 1, |
| 258 | ++ }, |
| 259 | + }; |
| 260 | + |
| 261 | + static struct genl_family ioam6_genl_family __ro_after_init = { |
| 262 | +diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c |
| 263 | +index f6f5b83dd954..54722bbe57f9 100644 |
| 264 | +--- a/net/ipv6/ioam6_iptunnel.c |
| 265 | ++++ b/net/ipv6/ioam6_iptunnel.c |
| 266 | +@@ -212,6 +212,10 @@ static int ioam6_do_fill(struct net *net, struct sk_buff *skb) |
| 267 | + + sizeof(struct ipv6_hopopt_hdr) + 2 |
| 268 | + + sizeof(struct ioam6_hdr)); |
| 269 | + |
| 270 | ++ trace->pkt_id.high = skb->id.high; |
| 271 | ++ trace->pkt_id.low = skb->id.low; |
| 272 | ++ trace->pkt_sid = skb->sid; |
| 273 | ++ |
| 274 | + ns = ioam6_namespace(net, trace->namespace_id); |
| 275 | + if (ns) |
| 276 | + ioam6_fill_trace_data(skb, ns, trace, false); |
0 commit comments