⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pktgen.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			 */			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 + -