commit f4b780f6d9c55e820f6fb0e12655626185f17e84 Author: Daniel Turull Date: Wed Dec 1 14:09:47 2010 +0100 Full version of pktgen rx diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 1712c10..d34ac47 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -222,6 +222,8 @@ static struct proc_dir_entry *pg_proc_dir; #define VLAN_TAG_SIZE(x) ((x)->vlan_id == 0xffff ? 0 : 4) #define SVLAN_TAG_SIZE(x) ((x)->svlan_id == 0xffff ? 0 : 4) +#define TIME_CONFIG_US 200000 + struct flow_state { __be32 cur_daddr; int count; @@ -384,6 +386,7 @@ struct pktgen_dev { u16 queue_map_max; __u32 skb_priority; /* skb priority field */ int node; /* Memory node */ + int config; /* Configuration enable/diabled */ #ifdef CONFIG_XFRM __u8 ipsmode; /* IPSEC mode (config) */ @@ -401,6 +404,12 @@ struct pktgen_hdr { __be32 seq_num; __s64 time; }; +struct pktgen_hdr_config { + __be32 pgh_magic; + __be32 seq_num; + __u64 pkt_to_send; + __be16 pkt_size; +}; static bool pktgen_exiting __read_mostly; @@ -458,6 +467,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 @@ -1035,6 +1046,15 @@ 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); @@ -2951,7 +2971,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, struct udphdr *udph; int datalen, iplen; struct iphdr *iph; - struct pktgen_hdr *pgh = NULL; + char *header; __be16 protocol = htons(ETH_P_IP); __be32 *mpls; __be16 *vlan_tci = NULL; /* Encapsulates priority and VLAN ID */ @@ -2972,7 +2992,10 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, mod_cur_headers(pkt_dev); queue_map = pkt_dev->cur_queue_map; - 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; @@ -3039,8 +3062,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); @@ -3068,13 +3096,18 @@ 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; - pgh = (struct pktgen_hdr *)(((char *)(udph)) + 8); + header = (((char *)(udph)) + 8); if (frags > MAX_SKB_FRAGS) frags = MAX_SKB_FRAGS; @@ -3126,16 +3159,24 @@ 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 if (!process_ipsec(pkt_dev, skb, protocol)) return NULL; @@ -3835,6 +3876,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); @@ -4094,7 +4144,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) pkt_dev->svlan_cfi = 0; pkt_dev->svlan_id = 0xffff; pkt_dev->node = -1; - + pkt_dev->config = 0; err = pktgen_setup_dev(pkt_dev, ifname); if (err) goto out1; @@ -4246,6 +4296,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; } } @@ -4266,6 +4317,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); @@ -4343,6 +4395,46 @@ 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)) + 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_lastpkts_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, struct pktgen_rx *data_cpu) @@ -4472,6 +4564,9 @@ 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); inter_arrival_ktime(now, data_cpu); @@ -4507,6 +4602,9 @@ 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); throughput_data(ktime_get(), data_cpu);