📄 pktgen.c
字号:
static void pktgen_stop_all_threads_ifs(void);static int pktgen_stop_device(struct pktgen_dev *pkt_dev);static void pktgen_stop(struct pktgen_thread *t);static void pktgen_clear_counters(struct pktgen_dev *pkt_dev);static unsigned int scan_ip6(const char *s, char ip[16]);static unsigned int fmt_ip6(char *s, const char ip[16]);/* Module parameters, defaults. */static int pg_count_d = 1000; /* 1000 pkts by default */static int pg_delay_d;static int pg_clone_skb_d;static int debug;static DEFINE_MUTEX(pktgen_thread_lock);static LIST_HEAD(pktgen_threads);static struct notifier_block pktgen_notifier_block = { .notifier_call = pktgen_device_event,};/* * /proc handling functions * */static int pgctrl_show(struct seq_file *seq, void *v){ seq_puts(seq, VERSION); return 0;}static ssize_t pgctrl_write(struct file *file, const char __user * buf, size_t count, loff_t * ppos){ int err = 0; char data[128]; if (!capable(CAP_NET_ADMIN)) { err = -EPERM; goto out; } if (count > sizeof(data)) count = sizeof(data); if (copy_from_user(data, buf, count)) { err = -EFAULT; goto out; } data[count - 1] = 0; /* Make string */ if (!strcmp(data, "stop")) pktgen_stop_all_threads_ifs(); else if (!strcmp(data, "start")) pktgen_run_all_threads(); else printk(KERN_WARNING "pktgen: Unknown command: %s\n", data); err = count;out: return err;}static int pgctrl_open(struct inode *inode, struct file *file){ return single_open(file, pgctrl_show, PDE(inode)->data);}static const struct file_operations pktgen_fops = { .owner = THIS_MODULE, .open = pgctrl_open, .read = seq_read, .llseek = seq_lseek, .write = pgctrl_write, .release = single_release,};static int pktgen_if_show(struct seq_file *seq, void *v){ struct pktgen_dev *pkt_dev = seq->private; __u64 sa; __u64 stopped; __u64 now = getCurUs(); DECLARE_MAC_BUF(mac); seq_printf(seq, "Params: count %llu min_pkt_size: %u max_pkt_size: %u\n", (unsigned long long)pkt_dev->count, pkt_dev->min_pkt_size, pkt_dev->max_pkt_size); seq_printf(seq, " frags: %d delay: %u clone_skb: %d ifname: %s\n", pkt_dev->nfrags, 1000 * pkt_dev->delay_us + pkt_dev->delay_ns, pkt_dev->clone_skb, pkt_dev->odev->name); seq_printf(seq, " flows: %u flowlen: %u\n", pkt_dev->cflows, pkt_dev->lflow); seq_printf(seq, " queue_map_min: %u queue_map_max: %u\n", pkt_dev->queue_map_min, pkt_dev->queue_map_max); if (pkt_dev->flags & F_IPV6) { char b1[128], b2[128], b3[128]; fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr); fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr); fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr); seq_printf(seq, " saddr: %s min_saddr: %s max_saddr: %s\n", b1, b2, b3); fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr); seq_printf(seq, " daddr: %s min_daddr: %s max_daddr: %s\n", b1, b2, b3); } else seq_printf(seq, " dst_min: %s dst_max: %s\n src_min: %s src_max: %s\n", pkt_dev->dst_min, pkt_dev->dst_max, pkt_dev->src_min, pkt_dev->src_max); seq_puts(seq, " src_mac: "); seq_printf(seq, "%s ", print_mac(mac, is_zero_ether_addr(pkt_dev->src_mac) ? pkt_dev->odev->dev_addr : pkt_dev->src_mac)); seq_printf(seq, "dst_mac: "); seq_printf(seq, "%s\n", print_mac(mac, pkt_dev->dst_mac)); seq_printf(seq, " udp_src_min: %d udp_src_max: %d udp_dst_min: %d udp_dst_max: %d\n", pkt_dev->udp_src_min, pkt_dev->udp_src_max, pkt_dev->udp_dst_min, pkt_dev->udp_dst_max); seq_printf(seq, " src_mac_count: %d dst_mac_count: %d\n", pkt_dev->src_mac_count, pkt_dev->dst_mac_count); if (pkt_dev->nr_labels) { unsigned i; seq_printf(seq, " mpls: "); for (i = 0; i < pkt_dev->nr_labels; i++) seq_printf(seq, "%08x%s", ntohl(pkt_dev->labels[i]), i == pkt_dev->nr_labels-1 ? "\n" : ", "); } if (pkt_dev->vlan_id != 0xffff) { seq_printf(seq, " vlan_id: %u vlan_p: %u vlan_cfi: %u\n", pkt_dev->vlan_id, pkt_dev->vlan_p, pkt_dev->vlan_cfi); } if (pkt_dev->svlan_id != 0xffff) { seq_printf(seq, " svlan_id: %u vlan_p: %u vlan_cfi: %u\n", pkt_dev->svlan_id, pkt_dev->svlan_p, pkt_dev->svlan_cfi); } if (pkt_dev->tos) { seq_printf(seq, " tos: 0x%02x\n", pkt_dev->tos); } if (pkt_dev->traffic_class) { seq_printf(seq, " traffic_class: 0x%02x\n", pkt_dev->traffic_class); } seq_printf(seq, " Flags: "); if (pkt_dev->flags & F_IPV6) seq_printf(seq, "IPV6 "); if (pkt_dev->flags & F_IPSRC_RND) seq_printf(seq, "IPSRC_RND "); if (pkt_dev->flags & F_IPDST_RND) seq_printf(seq, "IPDST_RND "); if (pkt_dev->flags & F_TXSIZE_RND) seq_printf(seq, "TXSIZE_RND "); if (pkt_dev->flags & F_UDPSRC_RND) seq_printf(seq, "UDPSRC_RND "); if (pkt_dev->flags & F_UDPDST_RND) seq_printf(seq, "UDPDST_RND "); if (pkt_dev->flags & F_MPLS_RND) seq_printf(seq, "MPLS_RND "); if (pkt_dev->flags & F_QUEUE_MAP_RND) seq_printf(seq, "QUEUE_MAP_RND "); if (pkt_dev->cflows) { if (pkt_dev->flags & F_FLOW_SEQ) seq_printf(seq, "FLOW_SEQ "); /*in sequence flows*/ else seq_printf(seq, "FLOW_RND "); }#ifdef CONFIG_XFRM if (pkt_dev->flags & F_IPSEC_ON) seq_printf(seq, "IPSEC ");#endif if (pkt_dev->flags & F_MACSRC_RND) seq_printf(seq, "MACSRC_RND "); if (pkt_dev->flags & F_MACDST_RND) seq_printf(seq, "MACDST_RND "); if (pkt_dev->flags & F_VID_RND) seq_printf(seq, "VID_RND "); if (pkt_dev->flags & F_SVID_RND) seq_printf(seq, "SVID_RND "); seq_puts(seq, "\n"); sa = pkt_dev->started_at; stopped = pkt_dev->stopped_at; if (pkt_dev->running) stopped = now; /* not really stopped, more like last-running-at */ seq_printf(seq, "Current:\n pkts-sofar: %llu errors: %llu\n started: %lluus stopped: %lluus idle: %lluus\n", (unsigned long long)pkt_dev->sofar, (unsigned long long)pkt_dev->errors, (unsigned long long)sa, (unsigned long long)stopped, (unsigned long long)pkt_dev->idle_acc); seq_printf(seq, " seq_num: %d cur_dst_mac_offset: %d cur_src_mac_offset: %d\n", pkt_dev->seq_num, pkt_dev->cur_dst_mac_offset, pkt_dev->cur_src_mac_offset); if (pkt_dev->flags & F_IPV6) { char b1[128], b2[128]; fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1); } else seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", pkt_dev->cur_saddr, pkt_dev->cur_daddr); seq_printf(seq, " cur_udp_dst: %d cur_udp_src: %d\n", pkt_dev->cur_udp_dst, pkt_dev->cur_udp_src); seq_printf(seq, " cur_queue_map: %u\n", pkt_dev->cur_queue_map); seq_printf(seq, " flows: %u\n", pkt_dev->nflows); if (pkt_dev->result[0]) seq_printf(seq, "Result: %s\n", pkt_dev->result); else seq_printf(seq, "Result: Idle\n"); return 0;}static int hex32_arg(const char __user *user_buffer, unsigned long maxlen, __u32 *num){ int i = 0; *num = 0; for (; i < maxlen; i++) { char c; *num <<= 4; if (get_user(c, &user_buffer[i])) return -EFAULT; if ((c >= '0') && (c <= '9')) *num |= c - '0'; else if ((c >= 'a') && (c <= 'f')) *num |= c - 'a' + 10; else if ((c >= 'A') && (c <= 'F')) *num |= c - 'A' + 10; else break; } return i;}static int count_trail_chars(const char __user * user_buffer, unsigned int maxlen){ int i; for (i = 0; i < maxlen; i++) { char c; if (get_user(c, &user_buffer[i])) return -EFAULT; switch (c) { case '\"': case '\n': case '\r': case '\t': case ' ': case '=': break; default: goto done; } }done: return i;}static unsigned long num_arg(const char __user * user_buffer, unsigned long maxlen, unsigned long *num){ int i = 0; *num = 0; for (; i < maxlen; i++) { char c; if (get_user(c, &user_buffer[i])) return -EFAULT; if ((c >= '0') && (c <= '9')) { *num *= 10; *num += c - '0'; } else break; } return i;}static int strn_len(const char __user * user_buffer, unsigned int maxlen){ int i = 0; for (; i < maxlen; i++) { char c; if (get_user(c, &user_buffer[i])) return -EFAULT; switch (c) { case '\"': case '\n': case '\r': case '\t': case ' ': goto done_str; break; default: break; } }done_str: return i;}static ssize_t get_labels(const char __user *buffer, struct pktgen_dev *pkt_dev){ unsigned n = 0; char c; ssize_t i = 0; int len; pkt_dev->nr_labels = 0; do { __u32 tmp; len = hex32_arg(&buffer[i], 8, &tmp); if (len <= 0) return len; pkt_dev->labels[n] = htonl(tmp); if (pkt_dev->labels[n] & MPLS_STACK_BOTTOM) pkt_dev->flags |= F_MPLS_RND; i += len; if (get_user(c, &buffer[i])) return -EFAULT; i++; n++; if (n >= MAX_MPLS_LABELS) return -E2BIG; } while (c == ','); pkt_dev->nr_labels = n; return i;}static ssize_t pktgen_if_write(struct file *file, const char __user * user_buffer, size_t count, loff_t * offset){ struct seq_file *seq = (struct seq_file *)file->private_data; struct pktgen_dev *pkt_dev = seq->private; int i = 0, max, len; char name[16], valstr[32]; unsigned long value = 0; char *pg_result = NULL; int tmp = 0; char buf[128]; pg_result = &(pkt_dev->result[0]); if (count < 1) { printk(KERN_WARNING "pktgen: wrong command format\n"); return -EINVAL; } max = count - i; tmp = count_trail_chars(&user_buffer[i], max); if (tmp < 0) { printk(KERN_WARNING "pktgen: illegal format\n"); return tmp; } i += tmp; /* Read variable name */ len = strn_len(&user_buffer[i], sizeof(name) - 1); if (len < 0) { return len; } memset(name, 0, sizeof(name)); if (copy_from_user(name, &user_buffer[i], len)) return -EFAULT; i += len; max = count - i; len = count_trail_chars(&user_buffer[i], max); if (len < 0) return len; i += len; if (debug) { char tb[count + 1]; if (copy_from_user(tb, user_buffer, count)) return -EFAULT; tb[count] = 0; printk(KERN_DEBUG "pktgen: %s,%lu buffer -:%s:-\n", name, (unsigned long)count, tb); } if (!strcmp(name, "min_pkt_size")) { len = num_arg(&user_buffer[i], 10, &value); if (len < 0) { return len; } i += len; if (value < 14 + 20 + 8) value = 14 + 20 + 8; if (value != pkt_dev->min_pkt_size) { pkt_dev->min_pkt_size = value; pkt_dev->cur_pkt_size = value; } sprintf(pg_result, "OK: min_pkt_size=%u", pkt_dev->min_pkt_size); return count; } if (!strcmp(name, "max_pkt_size")) { len = num_arg(&user_buffer[i], 10, &value); if (len < 0) { return len; } i += len; if (value < 14 + 20 + 8) value = 14 + 20 + 8; if (value != pkt_dev->max_pkt_size) { pkt_dev->max_pkt_size = value; pkt_dev->cur_pkt_size = value; } sprintf(pg_result, "OK: max_pkt_size=%u", pkt_dev->max_pkt_size); return count; } /* Shortcut for min = max */ if (!strcmp(name, "pkt_size")) { len = num_arg(&user_buffer[i], 10, &value); if (len < 0) { return len; } i += len; if (value < 14 + 20 + 8) value = 14 + 20 + 8; if (value != pkt_dev->min_pkt_size) { pkt_dev->min_pkt_size = value; pkt_dev->max_pkt_size = value; pkt_dev->cur_pkt_size = value; } sprintf(pg_result, "OK: pkt_size=%u", pkt_dev->min_pkt_size); return count; } if (!strcmp(name, "debug")) { len = num_arg(&user_buffer[i], 10, &value); if (len < 0) { return len; } i += len; debug = value; sprintf(pg_result, "OK: debug=%u", debug); return count; } if (!strcmp(name, "frags")) { len = num_arg(&user_buffer[i], 10, &value); if (len < 0) { return len; } i += len; pkt_dev->nfrags = value; sprintf(pg_result, "OK: frags=%u", pkt_dev->nfrags); return count; } if (!strcmp(name, "delay")) { len = num_arg(&user_buffer[i], 10, &value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -