📄 pktgen.c
字号:
*/ rcu_read_lock(); if ((idev = __in6_dev_get(pkt_dev->odev)) != NULL) { struct inet6_ifaddr *ifp; read_lock_bh(&idev->lock); for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { if (ifp->scope == IFA_LINK && !(ifp-> flags & IFA_F_TENTATIVE)) { ipv6_addr_copy(&pkt_dev-> cur_in6_saddr, &ifp->addr); err = 0; break; } } read_unlock_bh(&idev->lock); } rcu_read_unlock(); if (err) printk(KERN_ERR "pktgen: ERROR: IPv6 link " "address not availble.\n"); }#endif } else { pkt_dev->saddr_min = 0; pkt_dev->saddr_max = 0; if (strlen(pkt_dev->src_min) == 0) { struct in_device *in_dev; rcu_read_lock(); in_dev = __in_dev_get_rcu(pkt_dev->odev); if (in_dev) { if (in_dev->ifa_list) { pkt_dev->saddr_min = in_dev->ifa_list->ifa_address; pkt_dev->saddr_max = pkt_dev->saddr_min; } } rcu_read_unlock(); } else { pkt_dev->saddr_min = in_aton(pkt_dev->src_min); pkt_dev->saddr_max = in_aton(pkt_dev->src_max); } pkt_dev->daddr_min = in_aton(pkt_dev->dst_min); pkt_dev->daddr_max = in_aton(pkt_dev->dst_max); } /* Initialize current values. */ pkt_dev->cur_dst_mac_offset = 0; pkt_dev->cur_src_mac_offset = 0; pkt_dev->cur_saddr = pkt_dev->saddr_min; pkt_dev->cur_daddr = pkt_dev->daddr_min; pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; pkt_dev->cur_udp_src = pkt_dev->udp_src_min; pkt_dev->nflows = 0;}static void spin(struct pktgen_dev *pkt_dev, __u64 spin_until_us){ __u64 start; __u64 now; start = now = getCurUs(); printk(KERN_INFO "sleeping for %d\n", (int)(spin_until_us - now)); while (now < spin_until_us) { /* TODO: optimize sleeping behavior */ if (spin_until_us - now > jiffies_to_usecs(1) + 1) schedule_timeout_interruptible(1); else if (spin_until_us - now > 100) { if (!pkt_dev->running) return; if (need_resched()) schedule(); } now = getCurUs(); } pkt_dev->idle_acc += now - start;}static inline void set_pkt_overhead(struct pktgen_dev *pkt_dev){ pkt_dev->pkt_overhead = 0; pkt_dev->pkt_overhead += pkt_dev->nr_labels*sizeof(u32); pkt_dev->pkt_overhead += VLAN_TAG_SIZE(pkt_dev); pkt_dev->pkt_overhead += SVLAN_TAG_SIZE(pkt_dev);}static inline int f_seen(struct pktgen_dev *pkt_dev, int flow){ if (pkt_dev->flows[flow].flags & F_INIT) return 1; else return 0;}static inline int f_pick(struct pktgen_dev *pkt_dev){ int flow = pkt_dev->curfl; if (pkt_dev->flags & F_FLOW_SEQ) { if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { /* reset time */ pkt_dev->flows[flow].count = 0; pkt_dev->curfl += 1; if (pkt_dev->curfl >= pkt_dev->cflows) pkt_dev->curfl = 0; /*reset */ } } else { flow = random32() % pkt_dev->cflows; if (pkt_dev->flows[flow].count > pkt_dev->lflow) pkt_dev->flows[flow].count = 0; } return pkt_dev->curfl;}#ifdef CONFIG_XFRM/* If there was already an IPSEC SA, we keep it as is, else * we go look for it ...*/static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow){ struct xfrm_state *x = pkt_dev->flows[flow].x; if (!x) { /*slow path: we dont already have xfrm_state*/ x = xfrm_stateonly_find((xfrm_address_t *)&pkt_dev->cur_daddr, (xfrm_address_t *)&pkt_dev->cur_saddr, AF_INET, pkt_dev->ipsmode, pkt_dev->ipsproto, 0); if (x) { pkt_dev->flows[flow].x = x; set_pkt_overhead(pkt_dev); pkt_dev->pkt_overhead+=x->props.header_len; } }}#endif/* Increment/randomize headers according to flags and current values * for IP src/dest, UDP src/dst port, MAC-Addr src/dst */static void mod_cur_headers(struct pktgen_dev *pkt_dev){ __u32 imn; __u32 imx; int flow = 0; if (pkt_dev->cflows) flow = f_pick(pkt_dev); /* Deal with source MAC */ if (pkt_dev->src_mac_count > 1) { __u32 mc; __u32 tmp; if (pkt_dev->flags & F_MACSRC_RND) mc = random32() % pkt_dev->src_mac_count; else { mc = pkt_dev->cur_src_mac_offset++; if (pkt_dev->cur_src_mac_offset > pkt_dev->src_mac_count) pkt_dev->cur_src_mac_offset = 0; } tmp = pkt_dev->src_mac[5] + (mc & 0xFF); pkt_dev->hh[11] = tmp; tmp = (pkt_dev->src_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); pkt_dev->hh[10] = tmp; tmp = (pkt_dev->src_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); pkt_dev->hh[9] = tmp; tmp = (pkt_dev->src_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); pkt_dev->hh[8] = tmp; tmp = (pkt_dev->src_mac[1] + (tmp >> 8)); pkt_dev->hh[7] = tmp; } /* Deal with Destination MAC */ if (pkt_dev->dst_mac_count > 1) { __u32 mc; __u32 tmp; if (pkt_dev->flags & F_MACDST_RND) mc = random32() % pkt_dev->dst_mac_count; else { mc = pkt_dev->cur_dst_mac_offset++; if (pkt_dev->cur_dst_mac_offset > pkt_dev->dst_mac_count) { pkt_dev->cur_dst_mac_offset = 0; } } tmp = pkt_dev->dst_mac[5] + (mc & 0xFF); pkt_dev->hh[5] = tmp; tmp = (pkt_dev->dst_mac[4] + ((mc >> 8) & 0xFF) + (tmp >> 8)); pkt_dev->hh[4] = tmp; tmp = (pkt_dev->dst_mac[3] + ((mc >> 16) & 0xFF) + (tmp >> 8)); pkt_dev->hh[3] = tmp; tmp = (pkt_dev->dst_mac[2] + ((mc >> 24) & 0xFF) + (tmp >> 8)); pkt_dev->hh[2] = tmp; tmp = (pkt_dev->dst_mac[1] + (tmp >> 8)); pkt_dev->hh[1] = tmp; } if (pkt_dev->flags & F_MPLS_RND) { unsigned i; for (i = 0; i < pkt_dev->nr_labels; i++) if (pkt_dev->labels[i] & MPLS_STACK_BOTTOM) pkt_dev->labels[i] = MPLS_STACK_BOTTOM | ((__force __be32)random32() & htonl(0x000fffff)); } if ((pkt_dev->flags & F_VID_RND) && (pkt_dev->vlan_id != 0xffff)) { pkt_dev->vlan_id = random32() & (4096-1); } if ((pkt_dev->flags & F_SVID_RND) && (pkt_dev->svlan_id != 0xffff)) { pkt_dev->svlan_id = random32() & (4096 - 1); } if (pkt_dev->udp_src_min < pkt_dev->udp_src_max) { if (pkt_dev->flags & F_UDPSRC_RND) pkt_dev->cur_udp_src = random32() % (pkt_dev->udp_src_max - pkt_dev->udp_src_min) + pkt_dev->udp_src_min; else { pkt_dev->cur_udp_src++; if (pkt_dev->cur_udp_src >= pkt_dev->udp_src_max) pkt_dev->cur_udp_src = pkt_dev->udp_src_min; } } if (pkt_dev->udp_dst_min < pkt_dev->udp_dst_max) { if (pkt_dev->flags & F_UDPDST_RND) { pkt_dev->cur_udp_dst = random32() % (pkt_dev->udp_dst_max - pkt_dev->udp_dst_min) + pkt_dev->udp_dst_min; } else { pkt_dev->cur_udp_dst++; if (pkt_dev->cur_udp_dst >= pkt_dev->udp_dst_max) pkt_dev->cur_udp_dst = pkt_dev->udp_dst_min; } } if (!(pkt_dev->flags & F_IPV6)) { if ((imn = ntohl(pkt_dev->saddr_min)) < (imx = ntohl(pkt_dev-> saddr_max))) { __u32 t; if (pkt_dev->flags & F_IPSRC_RND) t = random32() % (imx - imn) + imn; else { t = ntohl(pkt_dev->cur_saddr); t++; if (t > imx) { t = imn; } } pkt_dev->cur_saddr = htonl(t); } if (pkt_dev->cflows && f_seen(pkt_dev, flow)) { pkt_dev->cur_daddr = pkt_dev->flows[flow].cur_daddr; } else { imn = ntohl(pkt_dev->daddr_min); imx = ntohl(pkt_dev->daddr_max); if (imn < imx) { __u32 t; __be32 s; if (pkt_dev->flags & F_IPDST_RND) { t = random32() % (imx - imn) + imn; s = htonl(t); while (LOOPBACK(s) || MULTICAST(s) || BADCLASS(s) || ZERONET(s) || LOCAL_MCAST(s)) { t = random32() % (imx - imn) + imn; s = htonl(t); } pkt_dev->cur_daddr = s; } else { t = ntohl(pkt_dev->cur_daddr); t++; if (t > imx) { t = imn; } pkt_dev->cur_daddr = htonl(t); } } if (pkt_dev->cflows) { pkt_dev->flows[flow].flags |= F_INIT; pkt_dev->flows[flow].cur_daddr = pkt_dev->cur_daddr;#ifdef CONFIG_XFRM if (pkt_dev->flags & F_IPSEC_ON) get_ipsec_sa(pkt_dev, flow);#endif pkt_dev->nflows++; } } } else { /* IPV6 * */ if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 && pkt_dev->min_in6_daddr.s6_addr32[1] == 0 && pkt_dev->min_in6_daddr.s6_addr32[2] == 0 && pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ; else { int i; /* Only random destinations yet */ for (i = 0; i < 4; i++) { pkt_dev->cur_in6_daddr.s6_addr32[i] = (((__force __be32)random32() | pkt_dev->min_in6_daddr.s6_addr32[i]) & pkt_dev->max_in6_daddr.s6_addr32[i]); } } } if (pkt_dev->min_pkt_size < pkt_dev->max_pkt_size) { __u32 t; if (pkt_dev->flags & F_TXSIZE_RND) { t = random32() % (pkt_dev->max_pkt_size - pkt_dev->min_pkt_size) + pkt_dev->min_pkt_size; } else { t = pkt_dev->cur_pkt_size + 1; if (t > pkt_dev->max_pkt_size) t = pkt_dev->min_pkt_size; } pkt_dev->cur_pkt_size = t; } if (pkt_dev->queue_map_min < pkt_dev->queue_map_max) { __u16 t; if (pkt_dev->flags & F_QUEUE_MAP_RND) { t = random32() % (pkt_dev->queue_map_max - pkt_dev->queue_map_min + 1) + pkt_dev->queue_map_min; } else { t = pkt_dev->cur_queue_map + 1; if (t > pkt_dev->queue_map_max) t = pkt_dev->queue_map_min; } pkt_dev->cur_queue_map = t; } pkt_dev->flows[flow].count++;}#ifdef CONFIG_XFRMstatic int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev){ struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; int err = 0; struct iphdr *iph; if (!x) return 0; /* XXX: we dont support tunnel mode for now until * we resolve the dst issue */ if (x->props.mode != XFRM_MODE_TRANSPORT) return 0; spin_lock(&x->lock); iph = ip_hdr(skb); err = x->outer_mode->output(x, skb); if (err) goto error; err = x->type->output(x, skb); if (err) goto error; x->curlft.bytes +=skb->len; x->curlft.packets++;error: spin_unlock(&x->lock); return err;}static inline void free_SAs(struct pktgen_dev *pkt_dev){ if (pkt_dev->cflows) { /* let go of the SAs if we have them */ int i = 0; for (; i < pkt_dev->nflows; i++){ struct xfrm_state *x = pkt_dev->flows[i].x; if (x) { xfrm_state_put(x); pkt_dev->flows[i].x = NULL; } } }}static inline int process_ipsec(struct pktgen_dev *pkt_dev, struct sk_buff *skb, __be16 protocol){ if (pkt_dev->flags & F_IPSEC_ON) { struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; int nhead = 0; if (x) { int ret; __u8 *eth; nhead = x->props.header_len - skb_headroom(skb); if (nhead >0) { ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); if (ret < 0) { printk(KERN_ERR "Error expanding " "ipsec packet %d\n",ret); return 0; } } /* ipsec is not expecting ll header */ skb_pull(skb, ETH_HLEN); ret = pktgen_output_ipsec(skb, pkt_dev); if (ret) { printk(KERN_ERR "Error creating ipsec " "packet %d\n",ret); kfree_skb(skb); return 0; } /* restore ll */ eth = (__u8 *) skb_push(skb, ETH_HLEN); memcpy(eth, pkt_dev->hh, 12); *(u16 *) & eth[12] = protocol; } } return 1;}#endifstatic void mpls_push(__be32 *mpls, struct pktgen_dev *pkt_dev){ unsigned i; for (i = 0; i < pkt_dev->nr_labels; i++) { *mpls++ = pkt_dev->labels[i] & ~MPLS_STACK_BOTTOM; } mpls--; *mpls |= MPLS_STACK_BOTTOM;}static inline __be16 build_tci(unsigned int id, unsigned int cfi, unsigned int prio){ return htons(id | (cfi << 12) | (prio << 13));}static struct sk_buff *fill_packet_ipv4(struct net_device *odev, struct pktgen_dev *pkt_dev){ struct sk_buff *skb = NULL; __u8 *eth; struct udphdr *udph; int datalen, iplen; struct iphdr *iph; struct pktgen_hdr *pgh = NULL; __be16 protocol = htons(ETH_P_IP); __be32 *mpls; __be16 *vlan_tci = NULL; /* Encapsulates priority and VLAN ID */ __be16 *vlan_encapsulated_proto = NULL; /* packet type ID field (or len) for VLAN tag */ __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ if (pkt_dev->nr_labels) protocol = htons(ETH_P_MPLS_UC); if (pkt_dev->vlan_id != 0xffff) protocol = htons(ETH_P_8021Q); /* Update any of the values, used when we're incrementing various * fields. */ mod_cur_headers(pkt_dev); datalen = (odev->hard_header_len + 16) & ~0xf; skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen + pkt_dev->pkt_overhead, GFP_ATOMIC); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } skb_reserve(skb, datalen); /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); mpls = (__be32 *)skb_put(skb, pkt_dev->nr_labels*sizeof(__u32)); if (pkt_dev->nr_labels) mpls_push(mpls, pkt_dev); if (pkt_dev->vlan_id != 0xffff) { if (pkt_dev->svlan_id != 0xffff) { svlan_tci = (__be16 *)skb_put(skb, sizeof(__be16)); *svlan_tci = build_tci(pkt_dev->svlan_id, pkt_dev->svla
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -