commit d1fef090975d3ab8776e8e98fe31fee5340af894 Author: Daniel Turull Date: Thu Aug 26 16:20:44 2010 +0200 Full version of pktgen rx diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 871002a..1afe40e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -384,6 +384,7 @@ struct pktgen_dev { u16 queue_map_max; int node; /* Memory node */ + int config; #ifdef CONFIG_XFRM __u8 ipsmode; /* IPSEC mode (config) */ __u8 ipsproto; /* IPSEC type (config) */ @@ -401,6 +402,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 */ @@ -455,6 +463,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 @@ -1027,6 +1037,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); @@ -2952,7 +2972,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; if (pkt_dev->flags & F_NODE) { int node; @@ -3017,8 +3040,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); @@ -3046,8 +3074,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; @@ -3104,14 +3137,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 @@ -3474,7 +3516,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; @@ -3817,6 +3862,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); @@ -4068,6 +4122,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) pkt_dev->svlan_id = 0xffff; pkt_dev->node = -1; + pkt_dev->config = 0; + err = pktgen_setup_dev(pkt_dev, ifname); if (err) goto out1; @@ -4219,6 +4275,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; } } @@ -4239,6 +4296,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_HUMAN; + spin_lock_init(&pg_rx_global->config_lock); pktgen_packet_type.dev = idev; dev_add_pack(&pktgen_packet_type); @@ -4311,6 +4369,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 */ @@ -4440,6 +4542,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); @@ -4475,6 +4579,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);