commit 6b2fdf7d3565b5362c09d6714dea4bba1642382d Author: Daniel Turull Date: Fri Aug 27 13:14:05 2010 +0200 commit 8e82f4c8cfe290561d1c00dde56834631321b9d2 Full version of pktgen rx diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 96aa21a..4349589 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -377,6 +377,7 @@ struct pktgen_dev { u16 queue_map_min; u16 queue_map_max; + int config; #ifdef CONFIG_XFRM __u8 ipsmode; /* IPSEC mode (config) */ __u8 ipsproto; /* IPSEC type (config) */ @@ -394,6 +395,13 @@ struct pktgen_hdr { __s64 time; }; +struct pktgen_hdr_config { + __be32 pgh_magic; + __be32 seq_num; + __u64 pkt_to_send; + __be16 pkt_size; +}; + struct pktgen_thread { spinlock_t if_lock; /* for list of devices */ struct list_head if_list; /* All device here */ @@ -448,6 +456,8 @@ struct pktgen_rx_global { u8 display_option; /* Text or no text*/ u64 pkts_to_send; /* Received in the config pkt*/ u64 bytes_to_send; /* Received in the config pkt*/ + spinlock_t config_lock; /* lock for the config */ + ktime_t last_config; /* Used when multiconfig arrive*/ }; #define REMOVE 1 @@ -1013,6 +1023,16 @@ static ssize_t pktgen_if_write(struct file *file, sprintf(pg_result, "OK: debug=%u", debug); return count; } + if (!strcmp(name, "config")) { + len = num_arg(&user_buffer[i], 10, &value); + if (len < 0) + return len; + + i += len; + pkt_dev->config = value; + sprintf(pg_result, "OK: config=%u", debug); + return count; + } if (!strcmp(name, "frags")) { len = num_arg(&user_buffer[i], 10, &value); @@ -2941,7 +2961,10 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, queue_map = pkt_dev->cur_queue_map; mod_cur_headers(pkt_dev); - datalen = (odev->hard_header_len + 16) & ~0xf; + if (unlikely(pkt_dev->config)) + datalen = (odev->hard_header_len + 20) & ~0xf; + else + datalen = (odev->hard_header_len + 16) & ~0xf; skb = __netdev_alloc_skb(odev, pkt_dev->cur_pkt_size + 64 + datalen + pkt_dev->pkt_overhead, GFP_NOWAIT); @@ -2988,8 +3011,13 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, /* Eth + IPh + UDPh + mpls */ datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 - pkt_dev->pkt_overhead; - if (datalen < sizeof(struct pktgen_hdr)) - datalen = sizeof(struct pktgen_hdr); + if (unlikely(pkt_dev->config)) { + if (datalen < sizeof(struct pktgen_hdr_config)) + datalen = sizeof(struct pktgen_hdr_config); + } else { + if (datalen < sizeof(struct pktgen_hdr)) + datalen = sizeof(struct pktgen_hdr); + } udph->source = htons(pkt_dev->cur_udp_src); udph->dest = htons(pkt_dev->cur_udp_dst); @@ -3017,8 +3045,13 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, skb->pkt_type = PACKET_HOST; if (pkt_dev->nfrags <= 0) { - pgh = (struct pktgen_hdr *)skb_put(skb, datalen); - memset(pgh + 1, 0, datalen - sizeof(struct pktgen_hdr)); + header = skb_put(skb, datalen); + if (unlikely(pkt_dev->config)) + memset(header + 1, 0, + datalen - sizeof(struct pktgen_hdr_config)); + else + memset(header + 1, 0, + datalen - sizeof(struct pktgen_hdr)); } else { int frags = pkt_dev->nfrags; int i, len; @@ -3075,14 +3108,23 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, /* Stamp the time, and sequence number, * convert them to network byte order */ - if (pgh) { - struct timeval timestamp; - - pgh->pgh_magic = htonl(PKTGEN_MAGIC); - pgh->seq_num = htonl(pkt_dev->seq_num); - - do_gettimeofday(×tamp); - pgh->time = htonll(ktime_to_ns(ktime_get())); + if (unlikely(pkt_dev->config)) { + struct pktgen_hdr_config *pghc = NULL; + pghc = (struct pktgen_hdr_config *) header; + if (pghc) { + pghc->pgh_magic = htonl(PKTGEN_MAGIC); + pghc->seq_num = 0; + pghc->pkt_to_send = htonl(pkt_dev->count); + pghc->pkt_size = htons(pkt_dev->min_pkt_size); + } + } else { + struct pktgen_hdr *pgh = NULL; + pgh = (struct pktgen_hdr *) header; + if (pgh) { + pgh->pgh_magic = htonl(PKTGEN_MAGIC); + pgh->seq_num = htonl(pkt_dev->seq_num); + pgh->time = htonll(ktime_to_ns(ktime_now())); + } } #ifdef CONFIG_XFRM @@ -3446,7 +3488,10 @@ static struct sk_buff *fill_packet(struct net_device *odev, static void pktgen_clear_counters(struct pktgen_dev *pkt_dev) { - pkt_dev->seq_num = 1; + if (unlikely(pkt_dev->config)) + pkt_dev->seq_num = 0; + else + pkt_dev->seq_num = 1; pkt_dev->idle_acc = 0; pkt_dev->sofar = 0; pkt_dev->tx_bytes = 0; @@ -3788,6 +3833,15 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) return; } + /*Configuration waiting time and reconfiguring*/ + if (unlikely(pkt_dev->config && pkt_dev->last_ok)) { + spin(pkt_dev, ktime_add_us(ktime_now(), TIME_CONFIG_US)); + pkt_dev->sofar--; + pkt_dev->config = 0; + pkt_dev->clone_count = pkt_dev->clone_skb+1; + pkt_dev->started_at = ktime_now(); + } + if (pkt_dev->delay && pkt_dev->last_ok) spin(pkt_dev, pkt_dev->next_tx); @@ -4041,6 +4095,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) pkt_dev->svlan_cfi = 0; pkt_dev->svlan_id = 0xffff; + pkt_dev->config = 0; + err = pktgen_setup_dev(pkt_dev, ifname); if (err) goto out1; @@ -4195,6 +4251,7 @@ void pg_reset_rx(void) if (pg_initialized) { pg_rx_global->pkts_to_send = 0; pg_rx_global->bytes_to_send = 0; + pg_rx_global->last_config.tv64 = 0; } } @@ -4215,6 +4272,7 @@ static int pktgen_add_rx(const char *ifname) GFP_KERNEL); pg_rx_global->stats_option = RX_BASIC; pg_rx_global->display_option = PG_DISPLAY_TEXT; + spin_lock_init(&pg_rx_global->config_lock); pktgen_packet_type.dev = idev; dev_add_pack(&pktgen_packet_type); @@ -4287,6 +4345,50 @@ static int pktgen_clean_rx(void) } return 0; } + +/* + * Check the packet header if its a configuration packet. + * If it is, configure pktgen receiver + */ +static int is_configure_packet(void *header) +{ + struct pktgen_hdr *pgh = (struct pktgen_hdr *) header; + + if (likely(pgh->seq_num) != 0) + return 0; + else{ + struct pktgen_hdr_config *pghc = + (struct pktgen_hdr_config *) header; + u64 pkts = ntohl(pghc->pkt_to_send); + int pkt_size = ntohs(pghc->pkt_size); + + u64 time_from_last; + ktime_t now; + + spin_lock(&(pg_rx_global->config_lock)); + now = ktime_now(); + time_from_last = ktime_to_us(ktime_sub( + now, pg_rx_global->last_config)); + + if (time_from_last < TIME_CONFIG_US) { + pg_rx_global->pkts_to_send += pkts; + pg_rx_global->bytes_to_send += pkt_size*pkts; + } else { + pg_reset_rx(); + pg_rx_global->pkts_to_send = pkts; + pg_rx_global->bytes_to_send = pkt_size*pkts; + } + pg_rx_global->last_config = now; + spin_unlock(&(pg_rx_global->config_lock)); + return 1; + } +} + +/* + * Function that gets the necessary data for througput calculation + */ +static inline int throughput_data(ktime_t now) +{ /* * Function that gets the necessary data for througput calculation */ @@ -4416,6 +4518,8 @@ static int pktgen_rcv_time(struct sk_buff *skb, struct net_device *dev, } if (unlikely(pgh->pgh_magic != PKTGEN_MAGIC_NET)) goto end; + if (unlikely(is_configure_packet((void *) pgh))) + goto end; data_cpu = &__get_cpu_var(pktgen_rx_data); @@ -4451,6 +4555,8 @@ int pktgen_rcv_basic(struct sk_buff *skb, struct net_device *dev, } if (unlikely(pgh->pgh_magic != PKTGEN_MAGIC_NET)) goto end; + if (unlikely(is_configure_packet((void *) pgh))) + goto end; data_cpu = &__get_cpu_var(pktgen_rx_data);