14
14
#include <net/genetlink.h>
15
15
#include <net/psample.h>
16
16
#include <linux/spinlock.h>
17
+ #include <net/ip_tunnels.h>
18
+ #include <net/dst_metadata.h>
17
19
18
20
#define PSAMPLE_MAX_PACKET_SIZE 0xffff
19
21
@@ -207,10 +209,155 @@ void psample_group_put(struct psample_group *group)
207
209
}
208
210
EXPORT_SYMBOL_GPL (psample_group_put );
209
211
212
+ static int __psample_ip_tun_to_nlattr (struct sk_buff * skb ,
213
+ struct ip_tunnel_info * tun_info )
214
+ {
215
+ unsigned short tun_proto = ip_tunnel_info_af (tun_info );
216
+ const void * tun_opts = ip_tunnel_info_opts (tun_info );
217
+ const struct ip_tunnel_key * tun_key = & tun_info -> key ;
218
+ int tun_opts_len = tun_info -> options_len ;
219
+
220
+ if (tun_key -> tun_flags & TUNNEL_KEY &&
221
+ nla_put_be64 (skb , PSAMPLE_TUNNEL_KEY_ATTR_ID , tun_key -> tun_id ,
222
+ PSAMPLE_TUNNEL_KEY_ATTR_PAD ))
223
+ return - EMSGSIZE ;
224
+
225
+ if (tun_info -> mode & IP_TUNNEL_INFO_BRIDGE &&
226
+ nla_put_flag (skb , PSAMPLE_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE ))
227
+ return - EMSGSIZE ;
228
+
229
+ switch (tun_proto ) {
230
+ case AF_INET :
231
+ if (tun_key -> u .ipv4 .src &&
232
+ nla_put_in_addr (skb , PSAMPLE_TUNNEL_KEY_ATTR_IPV4_SRC ,
233
+ tun_key -> u .ipv4 .src ))
234
+ return - EMSGSIZE ;
235
+ if (tun_key -> u .ipv4 .dst &&
236
+ nla_put_in_addr (skb , PSAMPLE_TUNNEL_KEY_ATTR_IPV4_DST ,
237
+ tun_key -> u .ipv4 .dst ))
238
+ return - EMSGSIZE ;
239
+ break ;
240
+ case AF_INET6 :
241
+ if (!ipv6_addr_any (& tun_key -> u .ipv6 .src ) &&
242
+ nla_put_in6_addr (skb , PSAMPLE_TUNNEL_KEY_ATTR_IPV6_SRC ,
243
+ & tun_key -> u .ipv6 .src ))
244
+ return - EMSGSIZE ;
245
+ if (!ipv6_addr_any (& tun_key -> u .ipv6 .dst ) &&
246
+ nla_put_in6_addr (skb , PSAMPLE_TUNNEL_KEY_ATTR_IPV6_DST ,
247
+ & tun_key -> u .ipv6 .dst ))
248
+ return - EMSGSIZE ;
249
+ break ;
250
+ }
251
+ if (tun_key -> tos &&
252
+ nla_put_u8 (skb , PSAMPLE_TUNNEL_KEY_ATTR_TOS , tun_key -> tos ))
253
+ return - EMSGSIZE ;
254
+ if (nla_put_u8 (skb , PSAMPLE_TUNNEL_KEY_ATTR_TTL , tun_key -> ttl ))
255
+ return - EMSGSIZE ;
256
+ if ((tun_key -> tun_flags & TUNNEL_DONT_FRAGMENT ) &&
257
+ nla_put_flag (skb , PSAMPLE_TUNNEL_KEY_ATTR_DONT_FRAGMENT ))
258
+ return - EMSGSIZE ;
259
+ if ((tun_key -> tun_flags & TUNNEL_CSUM ) &&
260
+ nla_put_flag (skb , PSAMPLE_TUNNEL_KEY_ATTR_CSUM ))
261
+ return - EMSGSIZE ;
262
+ if (tun_key -> tp_src &&
263
+ nla_put_be16 (skb , PSAMPLE_TUNNEL_KEY_ATTR_TP_SRC , tun_key -> tp_src ))
264
+ return - EMSGSIZE ;
265
+ if (tun_key -> tp_dst &&
266
+ nla_put_be16 (skb , PSAMPLE_TUNNEL_KEY_ATTR_TP_DST , tun_key -> tp_dst ))
267
+ return - EMSGSIZE ;
268
+ if ((tun_key -> tun_flags & TUNNEL_OAM ) &&
269
+ nla_put_flag (skb , PSAMPLE_TUNNEL_KEY_ATTR_OAM ))
270
+ return - EMSGSIZE ;
271
+ if (tun_opts_len ) {
272
+ if (tun_key -> tun_flags & TUNNEL_GENEVE_OPT &&
273
+ nla_put (skb , PSAMPLE_TUNNEL_KEY_ATTR_GENEVE_OPTS ,
274
+ tun_opts_len , tun_opts ))
275
+ return - EMSGSIZE ;
276
+ else if (tun_key -> tun_flags & TUNNEL_ERSPAN_OPT &&
277
+ nla_put (skb , PSAMPLE_TUNNEL_KEY_ATTR_ERSPAN_OPTS ,
278
+ tun_opts_len , tun_opts ))
279
+ return - EMSGSIZE ;
280
+ }
281
+
282
+ return 0 ;
283
+ }
284
+
285
+ static int psample_ip_tun_to_nlattr (struct sk_buff * skb ,
286
+ struct ip_tunnel_info * tun_info )
287
+ {
288
+ struct nlattr * nla ;
289
+ int err ;
290
+
291
+ nla = nla_nest_start_noflag (skb , PSAMPLE_ATTR_TUNNEL );
292
+ if (!nla )
293
+ return - EMSGSIZE ;
294
+
295
+ err = __psample_ip_tun_to_nlattr (skb , tun_info );
296
+ if (err ) {
297
+ nla_nest_cancel (skb , nla );
298
+ return err ;
299
+ }
300
+
301
+ nla_nest_end (skb , nla );
302
+
303
+ return 0 ;
304
+ }
305
+
306
+ static int psample_tunnel_meta_len (struct ip_tunnel_info * tun_info )
307
+ {
308
+ unsigned short tun_proto = ip_tunnel_info_af (tun_info );
309
+ const struct ip_tunnel_key * tun_key = & tun_info -> key ;
310
+ int tun_opts_len = tun_info -> options_len ;
311
+ int sum = 0 ;
312
+
313
+ if (tun_key -> tun_flags & TUNNEL_KEY )
314
+ sum += nla_total_size (sizeof (u64 ));
315
+
316
+ if (tun_info -> mode & IP_TUNNEL_INFO_BRIDGE )
317
+ sum += nla_total_size (0 );
318
+
319
+ switch (tun_proto ) {
320
+ case AF_INET :
321
+ if (tun_key -> u .ipv4 .src )
322
+ sum += nla_total_size (sizeof (u32 ));
323
+ if (tun_key -> u .ipv4 .dst )
324
+ sum += nla_total_size (sizeof (u32 ));
325
+ break ;
326
+ case AF_INET6 :
327
+ if (!ipv6_addr_any (& tun_key -> u .ipv6 .src ))
328
+ sum += nla_total_size (sizeof (struct in6_addr ));
329
+ if (!ipv6_addr_any (& tun_key -> u .ipv6 .dst ))
330
+ sum += nla_total_size (sizeof (struct in6_addr ));
331
+ break ;
332
+ }
333
+ if (tun_key -> tos )
334
+ sum += nla_total_size (sizeof (u8 ));
335
+ sum += nla_total_size (sizeof (u8 )); /* TTL */
336
+ if (tun_key -> tun_flags & TUNNEL_DONT_FRAGMENT )
337
+ sum += nla_total_size (0 );
338
+ if (tun_key -> tun_flags & TUNNEL_CSUM )
339
+ sum += nla_total_size (0 );
340
+ if (tun_key -> tp_src )
341
+ sum += nla_total_size (sizeof (u16 ));
342
+ if (tun_key -> tp_dst )
343
+ sum += nla_total_size (sizeof (u16 ));
344
+ if (tun_key -> tun_flags & TUNNEL_OAM )
345
+ sum += nla_total_size (0 );
346
+ if (tun_opts_len ) {
347
+ if (tun_key -> tun_flags & TUNNEL_GENEVE_OPT )
348
+ sum += nla_total_size (tun_opts_len );
349
+ else if (tun_key -> tun_flags & TUNNEL_ERSPAN_OPT )
350
+ sum += nla_total_size (tun_opts_len );
351
+ }
352
+
353
+ return sum ;
354
+ }
355
+
210
356
void psample_sample_packet (struct psample_group * group , struct sk_buff * skb ,
211
357
u32 trunc_size , int in_ifindex , int out_ifindex ,
212
358
u32 sample_rate )
213
359
{
360
+ struct ip_tunnel_info * tun_info ;
214
361
struct sk_buff * nl_skb ;
215
362
int data_len ;
216
363
int meta_len ;
@@ -224,6 +371,10 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
224
371
nla_total_size (sizeof (u32 )) + /* group_num */
225
372
nla_total_size (sizeof (u32 )); /* seq */
226
373
374
+ tun_info = skb_tunnel_info (skb );
375
+ if (tun_info )
376
+ meta_len += psample_tunnel_meta_len (tun_info );
377
+
227
378
data_len = min (skb -> len , trunc_size );
228
379
if (meta_len + nla_total_size (data_len ) > PSAMPLE_MAX_PACKET_SIZE )
229
380
data_len = PSAMPLE_MAX_PACKET_SIZE - meta_len - NLA_HDRLEN
@@ -278,6 +429,12 @@ void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
278
429
goto error ;
279
430
}
280
431
432
+ if (tun_info ) {
433
+ ret = psample_ip_tun_to_nlattr (nl_skb , tun_info );
434
+ if (unlikely (ret < 0 ))
435
+ goto error ;
436
+ }
437
+
281
438
genlmsg_end (nl_skb , data );
282
439
genlmsg_multicast_netns (& psample_nl_family , group -> net , nl_skb , 0 ,
283
440
PSAMPLE_NL_MCGRP_SAMPLE , GFP_ATOMIC );
0 commit comments