#include "../probe_ng.h"
#include "../pro/pf_ring.h"
#include "stdlib.h"
#include "stdio.h"


pfring_zc_queue *ring_zq[MAX_NUM_PCAP_THREADS];
pfring_zc_cluster *ring_zc[MAX_NUM_PCAP_THREADS];

long stats = 0;


void* thread_fetch(void* notused)
{
	u_long num;
	uint8_t rss_queue_id = *(u_long*)notused;

	pfring_zc_pkt_buff *buffer;

	buffer=pfring_zc_get_packet_handle(ring_zc[rss_queue_id]);

	while(1) {
		if(pfring_zc_recv_pkt(ring_zq[rss_queue_id], &buffer, 1) > 0) {

			stats ++;
			//printf("stats = %d\n", stats);
		}
	}

	return(NULL);
}
int max_packet_len(char *device) {
  pfring *ring;
  pfring_card_settings settings;
  int mtu;

  ring = pfring_open(device, 1536, PF_RING_ZC_NOT_REPROGRAM_RSS);

  if (ring == NULL)
    return 1536;

  pfring_get_card_settings(ring, &settings);

  mtu = pfring_get_mtu_size(ring);

  if (settings.max_packet_size < mtu + 14 /* eth */)
    settings.max_packet_size = mtu + 14 /* eth */ + 4 /* vlan */;

  pfring_close(ring);

  return settings.max_packet_size;
}


pfring_zc_queue* create_ring_cluster(char *dev, int cluster_id, int bind_core)
{
	int buffer_len;
	pfring_zc_cluster *zc;


	if (dev == NULL || cluster_id < 0) {
		//traceEvent(TRACE_ERROR, "device name is null or illegal cluster id, exit");
		exit(-1);
	}

	buffer_len = max_packet_len(dev);

	zc = pfring_zc_create_cluster(
		cluster_id,
		buffer_len,
		0,
		32768 + 32,
		pfring_zc_numa_get_cpu_node(bind_core),
		NULL, /* auto hugetlb mountpoint */
		0);

	if(zc == NULL) {

		return NULL;
	}

	return zc;
}


pfring_zc_queue* open_ring_zc(char *dev, pfring_zc_cluster *zc)
{
	pfring_zc_queue *zq;

	zq = pfring_zc_open_device(zc, dev, rx_only, PF_RING_ZC_DEVICE_SW_TIMESTAMP);

	if(zq == NULL) {

		return NULL;
	}

	return zq;
}


int main()
{
	char interface_name[256];

	int i = 0;
	int cluster_id = 99;
	int rss = 8;
	
	for(i = 0; i < rss; i ++)
	{
		sprintf(interface_name, "%s@%d","zc:p1p2",i );
		ring_zc[i] = create_ring_cluster(interface_name, cluster_id + i, 0);
		if(ring_zc[i] == NULL)
		{
			printf("open interface failed\n");
			return 0;
		}
		ring_zq[i] = open_ring_zc(interface_name, ring_zc[i] );
	}


	u_long thread_id[MAX_NUM_PCAP_THREADS];
	pthread_t *threadhld = (pthread_t*)malloc(sizeof(pthread_t) * rss);
	for (i = 0; i < rss; i++) {
			thread_id[i] = i;

			pthread_create(&threadhld[i], NULL, thread_fetch, (void*) &thread_id[i]);
		}

	while(1);
}

