pktgen.c (c87866ede44ad7da6b296d732221dc34ce1b154d) pktgen.c (7e5a3ef6b4e6cf9b0a04b8906d02f7c896f5b85c)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Authors:
4 * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
5 * Uppsala University and
6 * Swedish University of Agricultural Sciences
7 *
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>

--- 161 unchanged lines hidden (view full) ---

170#include <linux/uaccess.h>
171#include <asm/dma.h>
172#include <asm/div64.h> /* do_div */
173
174#define VERSION "2.75"
175#define IP_NAME_SZ 32
176#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
177#define MPLS_STACK_BOTTOM htonl(0x00000100)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Authors:
4 * Copyright 2001, 2002 by Robert Olsson <robert.olsson@its.uu.se>
5 * Uppsala University and
6 * Swedish University of Agricultural Sciences
7 *
8 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>

--- 161 unchanged lines hidden (view full) ---

170#include <linux/uaccess.h>
171#include <asm/dma.h>
172#include <asm/div64.h> /* do_div */
173
174#define VERSION "2.75"
175#define IP_NAME_SZ 32
176#define MAX_MPLS_LABELS 16 /* This is the max label stack depth */
177#define MPLS_STACK_BOTTOM htonl(0x00000100)
178/* Max number of internet mix entries that can be specified in imix_weights. */
179#define MAX_IMIX_ENTRIES 20
180#define IMIX_PRECISION 100 /* Precision of IMIX distribution */
178
179#define func_enter() pr_debug("entering %s\n", __func__);
180
181#define PKT_FLAGS \
182 pf(IPV6) /* Interface in IPV6 Mode */ \
183 pf(IPSRC_RND) /* IP-Src Random */ \
184 pf(IPDST_RND) /* IP-Dst Random */ \
185 pf(TXSIZE_RND) /* Transmit size is random */ \

--- 51 unchanged lines hidden (view full) ---

237#define PG_PROC_DIR "pktgen"
238#define PGCTRL "pgctrl"
239
240#define MAX_CFLOWS 65536
241
242#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
243#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
244
181
182#define func_enter() pr_debug("entering %s\n", __func__);
183
184#define PKT_FLAGS \
185 pf(IPV6) /* Interface in IPV6 Mode */ \
186 pf(IPSRC_RND) /* IP-Src Random */ \
187 pf(IPDST_RND) /* IP-Dst Random */ \
188 pf(TXSIZE_RND) /* Transmit size is random */ \

--- 51 unchanged lines hidden (view full) ---

240#define PG_PROC_DIR "pktgen"
241#define PGCTRL "pgctrl"
242
243#define MAX_CFLOWS 65536
244
245#define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4)
246#define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4)
247
248struct imix_pkt {
249 u64 size;
250 u64 weight;
251 u64 count_so_far;
252};
253
245struct flow_state {
246 __be32 cur_daddr;
247 int count;
248#ifdef CONFIG_XFRM
249 struct xfrm_state *x;
250#endif
251 __u32 flags;
252};

--- 85 unchanged lines hidden (view full) ---

338 __u16 udp_dst_max; /* exclusive, dest UDP port */
339
340 /* DSCP + ECN */
341 __u8 tos; /* six MSB of (former) IPv4 TOS
342 are for dscp codepoint */
343 __u8 traffic_class; /* ditto for the (former) Traffic Class in IPv6
344 (see RFC 3260, sec. 4) */
345
254struct flow_state {
255 __be32 cur_daddr;
256 int count;
257#ifdef CONFIG_XFRM
258 struct xfrm_state *x;
259#endif
260 __u32 flags;
261};

--- 85 unchanged lines hidden (view full) ---

347 __u16 udp_dst_max; /* exclusive, dest UDP port */
348
349 /* DSCP + ECN */
350 __u8 tos; /* six MSB of (former) IPv4 TOS
351 are for dscp codepoint */
352 __u8 traffic_class; /* ditto for the (former) Traffic Class in IPv6
353 (see RFC 3260, sec. 4) */
354
355 /* IMIX */
356 unsigned int n_imix_entries;
357 struct imix_pkt imix_entries[MAX_IMIX_ENTRIES];
358 /* Maps 0-IMIX_PRECISION range to imix_entry based on probability*/
359 __u8 imix_distribution[IMIX_PRECISION];
360
346 /* MPLS */
347 unsigned int nr_labels; /* Depth of stack, 0 = no MPLS */
348 __be32 labels[MAX_MPLS_LABELS];
349
350 /* VLAN/SVLAN (802.1Q/Q-in-Q) */
351 __u8 vlan_p;
352 __u8 vlan_cfi;
353 __u16 vlan_id; /* 0xffff means no vlan tag */

--- 112 unchanged lines hidden (view full) ---

466 const char *ifname, bool exact);
467static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
468static void pktgen_run_all_threads(struct pktgen_net *pn);
469static void pktgen_reset_all_threads(struct pktgen_net *pn);
470static void pktgen_stop_all_threads(struct pktgen_net *pn);
471
472static void pktgen_stop(struct pktgen_thread *t);
473static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
361 /* MPLS */
362 unsigned int nr_labels; /* Depth of stack, 0 = no MPLS */
363 __be32 labels[MAX_MPLS_LABELS];
364
365 /* VLAN/SVLAN (802.1Q/Q-in-Q) */
366 __u8 vlan_p;
367 __u8 vlan_cfi;
368 __u16 vlan_id; /* 0xffff means no vlan tag */

--- 112 unchanged lines hidden (view full) ---

481 const char *ifname, bool exact);
482static int pktgen_device_event(struct notifier_block *, unsigned long, void *);
483static void pktgen_run_all_threads(struct pktgen_net *pn);
484static void pktgen_reset_all_threads(struct pktgen_net *pn);
485static void pktgen_stop_all_threads(struct pktgen_net *pn);
486
487static void pktgen_stop(struct pktgen_thread *t);
488static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);
489static void fill_imix_distribution(struct pktgen_dev *pkt_dev);
474
475/* Module parameters, defaults. */
476static int pg_count_d __read_mostly = 1000;
477static int pg_delay_d __read_mostly;
478static int pg_clone_skb_d __read_mostly;
479static int debug __read_mostly;
480
481static DEFINE_MUTEX(pktgen_thread_lock);

--- 65 unchanged lines hidden (view full) ---

547 unsigned int i;
548 u64 idle;
549
550 seq_printf(seq,
551 "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
552 (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size,
553 pkt_dev->max_pkt_size);
554
490
491/* Module parameters, defaults. */
492static int pg_count_d __read_mostly = 1000;
493static int pg_delay_d __read_mostly;
494static int pg_clone_skb_d __read_mostly;
495static int debug __read_mostly;
496
497static DEFINE_MUTEX(pktgen_thread_lock);

--- 65 unchanged lines hidden (view full) ---

563 unsigned int i;
564 u64 idle;
565
566 seq_printf(seq,
567 "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n",
568 (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size,
569 pkt_dev->max_pkt_size);
570
571 if (pkt_dev->n_imix_entries > 0) {
572 seq_puts(seq, " imix_weights: ");
573 for (i = 0; i < pkt_dev->n_imix_entries; i++) {
574 seq_printf(seq, "%llu,%llu ",
575 pkt_dev->imix_entries[i].size,
576 pkt_dev->imix_entries[i].weight);
577 }
578 seq_puts(seq, "\n");
579 }
580
555 seq_printf(seq,
556 " frags: %d delay: %llu clone_skb: %d ifname: %s\n",
557 pkt_dev->nfrags, (unsigned long long) pkt_dev->delay,
558 pkt_dev->clone_skb, pkt_dev->odevname);
559
560 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
561 pkt_dev->lflow);
562

--- 101 unchanged lines hidden (view full) ---

664 idle = pkt_dev->idle_acc;
665 do_div(idle, NSEC_PER_USEC);
666
667 seq_printf(seq,
668 "Current:\n pkts-sofar: %llu errors: %llu\n",
669 (unsigned long long)pkt_dev->sofar,
670 (unsigned long long)pkt_dev->errors);
671
581 seq_printf(seq,
582 " frags: %d delay: %llu clone_skb: %d ifname: %s\n",
583 pkt_dev->nfrags, (unsigned long long) pkt_dev->delay,
584 pkt_dev->clone_skb, pkt_dev->odevname);
585
586 seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows,
587 pkt_dev->lflow);
588

--- 101 unchanged lines hidden (view full) ---

690 idle = pkt_dev->idle_acc;
691 do_div(idle, NSEC_PER_USEC);
692
693 seq_printf(seq,
694 "Current:\n pkts-sofar: %llu errors: %llu\n",
695 (unsigned long long)pkt_dev->sofar,
696 (unsigned long long)pkt_dev->errors);
697
698 if (pkt_dev->n_imix_entries > 0) {
699 int i;
700
701 seq_puts(seq, " imix_size_counts: ");
702 for (i = 0; i < pkt_dev->n_imix_entries; i++) {
703 seq_printf(seq, "%llu,%llu ",
704 pkt_dev->imix_entries[i].size,
705 pkt_dev->imix_entries[i].count_so_far);
706 }
707 seq_puts(seq, "\n");
708 }
709
672 seq_printf(seq,
673 " started: %lluus stopped: %lluus idle: %lluus\n",
674 (unsigned long long) ktime_to_us(pkt_dev->started_at),
675 (unsigned long long) ktime_to_us(stopped),
676 (unsigned long long) idle);
677
678 seq_printf(seq,
679 " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",

--- 107 unchanged lines hidden (view full) ---

787 default:
788 break;
789 }
790 }
791done_str:
792 return i;
793}
794
710 seq_printf(seq,
711 " started: %lluus stopped: %lluus idle: %lluus\n",
712 (unsigned long long) ktime_to_us(pkt_dev->started_at),
713 (unsigned long long) ktime_to_us(stopped),
714 (unsigned long long) idle);
715
716 seq_printf(seq,
717 " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n",

--- 107 unchanged lines hidden (view full) ---

825 default:
826 break;
827 }
828 }
829done_str:
830 return i;
831}
832
833/* Parses imix entries from user buffer.
834 * The user buffer should consist of imix entries separated by spaces
835 * where each entry consists of size and weight delimited by commas.
836 * "size1,weight_1 size2,weight_2 ... size_n,weight_n" for example.
837 */
838static ssize_t get_imix_entries(const char __user *buffer,
839 struct pktgen_dev *pkt_dev)
840{
841 const int max_digits = 10;
842 int i = 0;
843 long len;
844 char c;
845
846 pkt_dev->n_imix_entries = 0;
847
848 do {
849 unsigned long weight;
850 unsigned long size;
851
852 len = num_arg(&buffer[i], max_digits, &size);
853 if (len < 0)
854 return len;
855 i += len;
856 if (get_user(c, &buffer[i]))
857 return -EFAULT;
858 /* Check for comma between size_i and weight_i */
859 if (c != ',')
860 return -EINVAL;
861 i++;
862
863 if (size < 14 + 20 + 8)
864 size = 14 + 20 + 8;
865
866 len = num_arg(&buffer[i], max_digits, &weight);
867 if (len < 0)
868 return len;
869 if (weight <= 0)
870 return -EINVAL;
871
872 pkt_dev->imix_entries[pkt_dev->n_imix_entries].size = size;
873 pkt_dev->imix_entries[pkt_dev->n_imix_entries].weight = weight;
874
875 i += len;
876 if (get_user(c, &buffer[i]))
877 return -EFAULT;
878
879 i++;
880 pkt_dev->n_imix_entries++;
881
882 if (pkt_dev->n_imix_entries > MAX_IMIX_ENTRIES)
883 return -E2BIG;
884 } while (c == ' ');
885
886 return i;
887}
888
795static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
796{
797 unsigned int n = 0;
798 char c;
799 ssize_t i = 0;
800 int len;
801
802 pkt_dev->nr_labels = 0;

--- 152 unchanged lines hidden (view full) ---

955 pkt_dev->min_pkt_size = value;
956 pkt_dev->max_pkt_size = value;
957 pkt_dev->cur_pkt_size = value;
958 }
959 sprintf(pg_result, "OK: pkt_size=%d", pkt_dev->min_pkt_size);
960 return count;
961 }
962
889static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev)
890{
891 unsigned int n = 0;
892 char c;
893 ssize_t i = 0;
894 int len;
895
896 pkt_dev->nr_labels = 0;

--- 152 unchanged lines hidden (view full) ---

1049 pkt_dev->min_pkt_size = value;
1050 pkt_dev->max_pkt_size = value;
1051 pkt_dev->cur_pkt_size = value;
1052 }
1053 sprintf(pg_result, "OK: pkt_size=%d", pkt_dev->min_pkt_size);
1054 return count;
1055 }
1056
1057 if (!strcmp(name, "imix_weights")) {
1058 if (pkt_dev->clone_skb > 0)
1059 return -EINVAL;
1060
1061 len = get_imix_entries(&user_buffer[i], pkt_dev);
1062 if (len < 0)
1063 return len;
1064
1065 fill_imix_distribution(pkt_dev);
1066
1067 i += len;
1068 return count;
1069 }
1070
963 if (!strcmp(name, "debug")) {
964 len = num_arg(&user_buffer[i], 10, &value);
965 if (len < 0)
966 return len;
967
968 i += len;
969 debug = value;
970 sprintf(pg_result, "OK: debug=%u", debug);

--- 106 unchanged lines hidden (view full) ---

1077 }
1078 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
1079 return count;
1080 }
1081 if (!strcmp(name, "clone_skb")) {
1082 len = num_arg(&user_buffer[i], 10, &value);
1083 if (len < 0)
1084 return len;
1071 if (!strcmp(name, "debug")) {
1072 len = num_arg(&user_buffer[i], 10, &value);
1073 if (len < 0)
1074 return len;
1075
1076 i += len;
1077 debug = value;
1078 sprintf(pg_result, "OK: debug=%u", debug);

--- 106 unchanged lines hidden (view full) ---

1185 }
1186 sprintf(pg_result, "OK: udp_dst_max=%u", pkt_dev->udp_dst_max);
1187 return count;
1188 }
1189 if (!strcmp(name, "clone_skb")) {
1190 len = num_arg(&user_buffer[i], 10, &value);
1191 if (len < 0)
1192 return len;
1193 /* clone_skb is not supported for netif_receive xmit_mode and
1194 * IMIX mode.
1195 */
1085 if ((value > 0) &&
1086 ((pkt_dev->xmit_mode == M_NETIF_RECEIVE) ||
1087 !(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
1088 return -ENOTSUPP;
1196 if ((value > 0) &&
1197 ((pkt_dev->xmit_mode == M_NETIF_RECEIVE) ||
1198 !(pkt_dev->odev->priv_flags & IFF_TX_SKB_SHARING)))
1199 return -ENOTSUPP;
1200 if (value > 0 && pkt_dev->n_imix_entries > 0)
1201 return -EINVAL;
1202
1089 i += len;
1090 pkt_dev->clone_skb = value;
1091
1092 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
1093 return count;
1094 }
1095 if (!strcmp(name, "count")) {
1096 len = num_arg(&user_buffer[i], 10, &value);

--- 88 unchanged lines hidden (view full) ---

1185 return -ENOTSUPP;
1186
1187 pkt_dev->xmit_mode = M_NETIF_RECEIVE;
1188
1189 /* make sure new packet is allocated every time
1190 * pktgen_xmit() is called
1191 */
1192 pkt_dev->last_ok = 1;
1203 i += len;
1204 pkt_dev->clone_skb = value;
1205
1206 sprintf(pg_result, "OK: clone_skb=%d", pkt_dev->clone_skb);
1207 return count;
1208 }
1209 if (!strcmp(name, "count")) {
1210 len = num_arg(&user_buffer[i], 10, &value);

--- 88 unchanged lines hidden (view full) ---

1299 return -ENOTSUPP;
1300
1301 pkt_dev->xmit_mode = M_NETIF_RECEIVE;
1302
1303 /* make sure new packet is allocated every time
1304 * pktgen_xmit() is called
1305 */
1306 pkt_dev->last_ok = 1;
1193
1194 /* override clone_skb if user passed default value
1195 * at module loading time
1196 */
1197 pkt_dev->clone_skb = 0;
1198 } else if (strcmp(f, "queue_xmit") == 0) {
1199 pkt_dev->xmit_mode = M_QUEUE_XMIT;
1200 pkt_dev->last_ok = 1;
1201 } else {
1202 sprintf(pg_result,
1203 "xmit_mode -:%s:- unknown\nAvailable modes: %s",
1204 f, "start_xmit, netif_receive\n");
1205 return count;

--- 1266 unchanged lines hidden (view full) ---

2472 (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
2473 + pkt_dev->min_pkt_size;
2474 } else {
2475 t = pkt_dev->cur_pkt_size + 1;
2476 if (t > pkt_dev->max_pkt_size)
2477 t = pkt_dev->min_pkt_size;
2478 }
2479 pkt_dev->cur_pkt_size = t;
1307 } else if (strcmp(f, "queue_xmit") == 0) {
1308 pkt_dev->xmit_mode = M_QUEUE_XMIT;
1309 pkt_dev->last_ok = 1;
1310 } else {
1311 sprintf(pg_result,
1312 "xmit_mode -:%s:- unknown\nAvailable modes: %s",
1313 f, "start_xmit, netif_receive\n");
1314 return count;

--- 1266 unchanged lines hidden (view full) ---

2581 (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size)
2582 + pkt_dev->min_pkt_size;
2583 } else {
2584 t = pkt_dev->cur_pkt_size + 1;
2585 if (t > pkt_dev->max_pkt_size)
2586 t = pkt_dev->min_pkt_size;
2587 }
2588 pkt_dev->cur_pkt_size = t;
2589 } else if (pkt_dev->n_imix_entries > 0) {
2590 struct imix_pkt *entry;
2591 __u32 t = prandom_u32() % IMIX_PRECISION;
2592 __u8 entry_index = pkt_dev->imix_distribution[t];
2593
2594 entry = &pkt_dev->imix_entries[entry_index];
2595 entry->count_so_far++;
2596 pkt_dev->cur_pkt_size = entry->size;
2480 }
2481
2482 set_cur_queue_map(pkt_dev);
2483
2484 pkt_dev->flows[flow].count++;
2485}
2486
2597 }
2598
2599 set_cur_queue_map(pkt_dev);
2600
2601 pkt_dev->flows[flow].count++;
2602}
2603
2604static void fill_imix_distribution(struct pktgen_dev *pkt_dev)
2605{
2606 int cumulative_probabilites[MAX_IMIX_ENTRIES];
2607 int j = 0;
2608 __u64 cumulative_prob = 0;
2609 __u64 total_weight = 0;
2610 int i = 0;
2487
2611
2612 for (i = 0; i < pkt_dev->n_imix_entries; i++)
2613 total_weight += pkt_dev->imix_entries[i].weight;
2614
2615 /* Fill cumulative_probabilites with sum of normalized probabilities */
2616 for (i = 0; i < pkt_dev->n_imix_entries - 1; i++) {
2617 cumulative_prob += div64_u64(pkt_dev->imix_entries[i].weight *
2618 IMIX_PRECISION,
2619 total_weight);
2620 cumulative_probabilites[i] = cumulative_prob;
2621 }
2622 cumulative_probabilites[pkt_dev->n_imix_entries - 1] = 100;
2623
2624 for (i = 0; i < IMIX_PRECISION; i++) {
2625 if (i == cumulative_probabilites[j])
2626 j++;
2627 pkt_dev->imix_distribution[i] = j;
2628 }
2629}
2630
2488#ifdef CONFIG_XFRM
2489static u32 pktgen_dst_metrics[RTAX_MAX + 1] = {
2490
2491 [RTAX_HOPLIMIT] = 0x5, /* Set a static hoplimit */
2492};
2493
2494static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2495{

--- 644 unchanged lines hidden (view full) ---

3140 (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)),
3141 (unsigned long long)ktime_to_us(idle),
3142 (unsigned long long)pkt_dev->sofar,
3143 pkt_dev->cur_pkt_size, nr_frags);
3144
3145 pps = div64_u64(pkt_dev->sofar * NSEC_PER_SEC,
3146 ktime_to_ns(elapsed));
3147
2631#ifdef CONFIG_XFRM
2632static u32 pktgen_dst_metrics[RTAX_MAX + 1] = {
2633
2634 [RTAX_HOPLIMIT] = 0x5, /* Set a static hoplimit */
2635};
2636
2637static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2638{

--- 644 unchanged lines hidden (view full) ---

3283 (unsigned long long)ktime_to_us(ktime_sub(elapsed, idle)),
3284 (unsigned long long)ktime_to_us(idle),
3285 (unsigned long long)pkt_dev->sofar,
3286 pkt_dev->cur_pkt_size, nr_frags);
3287
3288 pps = div64_u64(pkt_dev->sofar * NSEC_PER_SEC,
3289 ktime_to_ns(elapsed));
3290
3148 bps = pps * 8 * pkt_dev->cur_pkt_size;
3291 if (pkt_dev->n_imix_entries > 0) {
3292 int i;
3293 struct imix_pkt *entry;
3149
3294
3295 bps = 0;
3296 for (i = 0; i < pkt_dev->n_imix_entries; i++) {
3297 entry = &pkt_dev->imix_entries[i];
3298 bps += entry->size * entry->count_so_far;
3299 }
3300 bps = div64_u64(bps * 8 * NSEC_PER_SEC, ktime_to_ns(elapsed));
3301 } else {
3302 bps = pps * 8 * pkt_dev->cur_pkt_size;
3303 }
3304
3150 mbps = bps;
3151 do_div(mbps, 1000000);
3152 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
3153 (unsigned long long)pps,
3154 (unsigned long long)mbps,
3155 (unsigned long long)bps,
3156 (unsigned long long)pkt_dev->errors);
3157}

--- 727 unchanged lines hidden ---
3305 mbps = bps;
3306 do_div(mbps, 1000000);
3307 p += sprintf(p, " %llupps %lluMb/sec (%llubps) errors: %llu",
3308 (unsigned long long)pps,
3309 (unsigned long long)mbps,
3310 (unsigned long long)bps,
3311 (unsigned long long)pkt_dev->errors);
3312}

--- 727 unchanged lines hidden ---